概述
Android在Android 6.0版本时提出了动态权限概念,在Android 6.0之上的系统上安装的APP需要手动去申请部分重要权限。
在6.0之前,Android应用中的权限使用只需要在AndroidManifest.xml文件中配置对应的权限,那么就只会在安装时显示出当前应用所需要的权限,安装之后就可以持续使用。
在6.0之后,Android中的权限除了需要在AndroidMainfest.xml文件中进行配置,部分核心权限必须在应用中向用户进行申请,需要用户主动点击才能够进行使用。
在6.0之前,APP如果申请的隐私权限,在安装时被直接允许,就能够在在用户毫不执行的情况下访问权限内的隐私信息,这项改动使得用户对于当前APP的使用的重要权限进行知晓,有利于保护用户隐私。
一、基本的权限申请
首先需要说明的一点是权限申请是需要在targetSDKVersion在23及之上才需要设置的。
权限申请包括有如下几个重要的方法:
- 权限检查
ActivityCompat.checkSelfPermission(this, Manifest.permission.XX)
- 权限申请
ActivityCompat.requestPermissions(final Activity activity,final String[] permissions, final int requestCode)
- 申请结果回调
onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
- 申请被拒接处理
ActivityCompat.shouldShowRequestPermissionRationale(Activity activity,String permission)可再次申请
该方法返回false时表明本次申请权限被禁止询问申请,此时需要进行手动开启应用设置页手动允许
- 跳转至应用设置页
以悬浮窗权限为例
val intent = Intent()
intent.action = Settings.ACTION_MANAGE_OVERLAY_PERMISSION
intent.data = Uri.parse("package:$packageName")
startActivityForResult(intent, 0)
二、权限规避
由于动态权限是在Android6.0之后才需要进行设置的,所以当我们的targetSDKVersion设置在23(M)之下时,不需要去申请权限,即使调用了权限判断方法也是返回权限已经拥有的状态(PERMISSION_GRANTED),此时就可以产生一个权限规避的效果。
此方法需要设置targetSDKVersion为23以下,冒然更改大项目的targetSDKVersion不可取,需要谨慎使用。
当编译targetSDKVersion < 23
时使用
ContextCompat.checkSelfPermission
和 Context.checkSelfPermission
将会不起作用
需要使用
PermissionChecker.checkSelfPermission
。
同样targetSDKVersion >= 23
时PermissionChecker.checkSelfPermission
也会无效,
需要使用ContextCompat.checkSelfPermission
。
注意此方法仅可以在Android8.0之下使用。
三、特殊权限
Android O
之后多了一些权限需要额外申请,部分如下:
- 应用内安装应用权限
- 悬浮窗权限
这些权限同样需要申请,但是不会像文件读写权限一样直接弹出dialog点击就可以申请到权限,而是需要跳转到设置页由用户手动打开,其判断权限是否拥有的方法也不相同。示例代码如下:
//申请悬浮窗权限
private fun requestPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) {
val intent = Intent()
intent.action = Settings.ACTION_MANAGE_OVERLAY_PERMISSION
intent.data = Uri.parse("package:$packageName")
startActivityForResult(intent, 0)
}
}
//申请应用内安装应用权限
private fun requestInstallPermission(){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
var haveInstallPermission = this.packageManager.canRequestPackageInstalls()
if (!haveInstallPermission) {
var packageURI = Uri.parse ("package:$packageName");
var intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageURI)
startActivityForResult(intent, 1)
}
}
}
从代码可以看出,判断权限是否拥有上调用的方法有所不同:
- 悬浮窗权限使用的方法是
Settings.canDrawOverlays(context))
- 应用内安装权限的方法是
packageManager.canRequestPackageInstalls()
四、Android 10 文件读写
在Android 10 系统上,系统对于应用对文件的读写管理变得更加严格:
- app私有目录,不需要权限就可以访问。
- 媒体目录(相册、视频、音频...),需求申请READ_EATERNAL_STORAGE权限,访问方式使用MediaStore。
- 其他目录只能访问文件列表,不能再读写文件,需要将文件放到自己的私有目录才能读写。
因此需要在AndroidManifest.xml
的Application
标签内添加如下配置才能够正常的进行文件读写:
android:requestLegacyExternalStorage="true"
总结
对Android目前权限的问题进行一个总结备忘。
网友评论