1 权限分类
- 安装时权限
系统会在应用安装时自动授予应用相应权限,包括普通权限和签名权限。
- 运行时权限
运行时权限也称为危险权限,Android 6.0 开始需要在应用中执行权限申请相关代码,系统会弹出授权框提示框,需要用户点击才可以授权。
- 特殊权限
Android 6.0 开始需要用户在应用设置界面中才能开启权限。
基本上每个版本,权限都会有一定的修改,而且系统对这方面的限制是越来越严格,所以正确的做法是请求最少数量的权限。
2 特殊权限
这类权限需要在使用的时候用户动态申请。比如:当用户打开相机拍摄照片的时候,需要开发人员通过代码的方式在打开相机的地方去申请权限
注意: 权限是分组的,同一组的权限申请其中一个,同组的权限就全部都申请了。比如,应用被授予READ_EXTERNAL_STORAGE权限之后,如果再申请WRITE_EXTERNAL_STORAGE权限,系统会立即授予该权限,不会再弹出权限授予询问的对话框。
普通权限,只需要在AndroidManifest.xml中申请即可
特殊权限组
| 权限组 | 权限 |
|---|---|
| CALENDAR 日历 | permission:android.permission.READ_CALENDAR permission:android.permission.WRITE_CALENDAR |
| CAMERA 相机 | permission:android.permission.CAMERA |
| CONTACTS 联系人 | permission:android.permission.WRITE_CONTACTS permission:android.permission.GET_ACCOUNTS permission:android.permission.READ_CONTACTS |
| LOCATION 定位 | permission:android.permission.ACCESS_FINE_LOCATION permission:android.permission.ACCESS_COARSE_LOCATION |
| MICROPHONE麦克风相关,比如录音 | permission:android.permission.RECORD_AUDIO |
| PHONE 手机状态 | permission:android.permission.READ_CALL_LOG permission:android.permission.READ_PHONE_STATE permission:android.permission.CALL_PHONE permission:android.permission.WRITE_CALL_LOG permission:android.permission.USE_SIP permission:android.permission.PROCESS_OUTGOING_CALLS permission:com.android.voicemail.permission.ADD_VOICEMAI |
| SENSORS 传感器 | permission:android.permission.BODY_SENSORS |
| SMS 短信 | permission:android.permission.READ_SMS permission:android.permission.RECEIVE_WAP_PUSH permission:android.permission.RECEIVE_MMS permission:android.permission.RECEIVE_SMS permission:android.permission.SEND_SMS permission:android.permission.READ_CELL_BROADCASTS |
| STORAGE 存储权限 | permission:android.permission.READ_EXTERNAL_STORAGE permission:android.permission.WRITE_EXTERNAL_STORAGE |
3 动态权限申请
checkSelfPermission(@NonNull Context context, @NonNull String permission)//检查是否开启权限。
requestPermissions(Activity activity, String[] permissions, int requestCode)//请求开启权限
- 动态权限申请也要在AndroidManifest.xml里面写明
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- 判断当前是否有权限
if (PackageManager.PERMISSION_GRANTED == ActivityCompat.checkSelfPermission(context, permission)) {
//已授权
} else {
//未授权
}
- 进行权限申请
ActivityCompat.requestPermissions(context, permissions, mRequestCode);
- 用户授权后操作
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
PermissionsUtils.getInstance().onRequestPermissionsResult(this,requestCode,permissions,grantResults);
}
完整代码: 最好使用工具类,封装成单例
public class PermissionsUtils {
private final int mRequestCode = 1001;//权限请求码
public static boolean showSystemSetting = true;
AlertDialog mPermissionDialog;
private List<String> mPermissionList;
private PermissionsUtils() {
}
private static PermissionsUtils permissionsUtils;
private IPermissionsResult mPermissionsResult;
public static PermissionsUtils getInstance() {
if (permissionsUtils == null) {
permissionsUtils = new PermissionsUtils();
}
return permissionsUtils;
}
public void checkPermissions(Activity context, String[] permissions, IPermissionsResult permissionsResult) {
mPermissionsResult = permissionsResult;
if (Build.VERSION.SDK_INT < 23) {//6.0才用动态权限
permissionsResult.passPermissions();
}
//创建一个mPermissionList,逐个判断哪些权限未授予,未授予的权限存储到mPermissionList中
mPermissionList = new ArrayList<>();
//逐个判断你要的权限是否已经通过
for (int i = 0; i < permissions.length; i++) {
if (ContextCompat.checkSelfPermission(context, permissions[i]) != PackageManager.PERMISSION_GRANTED) {
mPermissionList.add(permissions[i]);//添加还未授予的权限
}
}
//申请权限
if (mPermissionList.size() > 0) {//有权限没有通过,需要申请
ActivityCompat.requestPermissions(context, permissions, mRequestCode);
} else {
//说明权限都已经通过
permissionsResult.passPermissions();
}
}
/**
* 请求权限后回调的方法
* @param context
* @param requestCode 自定义的权限请求码
* @param permissions 请求的权限数组
* @param grantResults 在弹出页面后是否允许权限的标识数组,数组的长度对应的是权限名称数组的长度,数组的数据0表示允许权限,-1表示我们点击了禁止权限
*/
public void onRequestPermissionsResult(Activity context, int requestCode, String[] permissions, int[] grantResults) {
boolean hasPermissionDismiss = false;//有权限没有通过
if (mRequestCode == requestCode) {
for (int i = 0; i < grantResults.length; i++) {
if (grantResults[i] == -1) {
hasPermissionDismiss = true;
}
}
//如果有权限没有被允许
if (hasPermissionDismiss) {
if (showSystemSetting) {
showSystemPermissionsSettingDialog(context);//跳转到系统设置权限页面,或者直接关闭页面,不让他继续访问
} else {
mPermissionsResult.forbidPermissions();
}
} else {
//全部权限通过,可以进行下一步操作
mPermissionsResult.passPermissions();
}
}
}
/**
* 不再提示权限时的展示对话框
*/
private void showSystemPermissionsSettingDialog(final Activity context) {
final String mPackName = context.getPackageName();
if (mPermissionDialog == null) {
mPermissionDialog = new AlertDialog.Builder(context)
.setMessage("已禁用权限,请手动授予")
.setPositiveButton("设置", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
cancelPermissionDialog();
Uri packageURI = Uri.parse("package:" + mPackName);
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, packageURI);
context.startActivity(intent);
context.finish();
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//关闭页面或者做其他操作
cancelPermissionDialog();
//mContext.finish();
mPermissionsResult.forbidPermissions();
}
}).create();
}
mPermissionDialog.show();
}
//关闭对话框
private void cancelPermissionDialog() {
if (mPermissionDialog != null) {
mPermissionDialog.dismiss();
mPermissionDialog = null;
}
}
public interface IPermissionsResult {
void passPermissions();
void forbidPermissions();
}
}
\