Android 6.0动态权限介绍
image.png
使用权限
Android应用默认情况未关联任何权限,这就意味着它无法执行对用户体验或设备上的数据产生不利影响的操作。要使用受保护的设备功能,必须在Manifest中包含<uses-permission>
标记。
使用权限分为2个级别:
- 正常权限:不会对用户隐私或设备操作造成很大风险的权限,系统会自动授予这些全选。
- 危险权限:可能对用户隐私或设备操作造成风险的权限。系统会根据Android版本做不同处理。Android6.0以上(targetSdkVersion >= 23)的版本,会提示用户明确授予该权限;6.0以下版本系统会默认授予该权限。
危险权限列表:
动态请求权限
此处针对Android6.0以上版本。
如果需要用到危险权限,例如拍照、存储文件、读取文件等操作,就需要在代码中动态申请该权限。
有两种申请方式:
1. RxPermissions
这是一种很简便的方式,并且可以结合RxJava一起使用,具体使用方式网上有很多介绍,此处就简单说一下。
RxPermissions地址:https://github.com/tbruyelle/RxPermissions
在模块build.gradle文件中添加依赖:
implementation 'com.github.tbruyelle:rxpermissions:0.10.2'
创建一个RxPermissions对象:
val rxPermissions = RxPermissions(this)
this
表示FragmentActivity或者Fragment,RxPermissions的构造方法如下:
public RxPermissions(@NonNull FragmentActivity activity) {
this.mRxPermissionsFragment = this.getLazySingleton(activity.getSupportFragmentManager());
}
public RxPermissions(@NonNull Fragment fragment) {
this.mRxPermissionsFragment = this.getLazySingleton(fragment.getChildFragmentManager());
}
申请权限,一次可申请一个或多个:
rxPermissions.requestEach(Manifest.permission.CAMERA, Manifest.permission.READ_PHONE_STATE,
Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.CALL_PHONE)
.subscribe {
when {
it.granted -> { //授权成功
LogUtil.i("zf_tag", it.name + " granted success")
}
it.shouldShowRequestPermissionRationale -> { //授权失败,可再次弹框请求
LogUtil.i("zf_tag", it.name + " denied permission with ask again")
}
else -> {//授权失败,不能再次请求,只能到系统设置页面去修改权限
LogUtil.i("zf_tag", it.name + " denied permission without ask again")
}
}
}
使用RxPermissions请求权限很简单吧。RxPermissions有几个优点:
- 使用过程中不用关注系统版本,RxPermissions内部会区分版本,并且做统一的处理。
- 使用简单,请求权限和处理结果回调不用分开处理。
- 支持Rx提供的各种操作符
但使用过程中也有一些受限制的地方。
初始化RxPermissions对象依赖于Activity和Fragment,如果工具类中涉及到权限请求,不好判断。
下面提供一个判断是否具有某个权限的判断方法,可用于非Activity、Fragment的判断:
/**
* 判断应用是否具有某个权限
*/
public static boolean isPermissionGranted(Context context, String permission) {
if (context == null) {
return false;
}
// For Android < Android M, self permissions are always granted.
boolean result = true;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (DeviceUtil.getTargetSdkVersion(context) >= Build.VERSION_CODES.M) {
// targetSdkVersion >= Android M, we can
// use Context#checkSelfPermission
result = context.checkSelfPermission(permission)
== PackageManager.PERMISSION_GRANTED;
} else {
// targetSdkVersion < Android M, we have to use PermissionChecker
result = PermissionChecker.checkSelfPermission(context, permission)
== PermissionChecker.PERMISSION_GRANTED;
}
}
return result;
}
2. 系统requestPermissions方法
通过系统方法requestPermissions方法请求危险权限,代码如下:
private fun requestPermissions() {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA, Manifest.permission.READ_PHONE_STATE,
Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.CALL_PHONE), 100)
}
Activity的回调方法onRequestPermissionsResult方法可以获取请求结果:
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
请求的时候传入一个权限数组,回调方法返回一个结果数组,根据结果数组判断权限是否请求成功。
总结
对比RxPermissions和系统的requestPermissions方法,明显RxPermissions操作更加简单,而且不用区分Android系统版本。所以实际项目中推荐使用RxPermissions方式。