Android 动态权限备忘

概述

Android在Android 6.0版本时提出了动态权限概念,在Android 6.0之上的系统上安装的APP需要手动去申请部分重要权限。
在6.0之前,Android应用中的权限使用只需要在AndroidManifest.xml文件中配置对应的权限,那么就只会在安装时显示出当前应用所需要的权限,安装之后就可以持续使用。
在6.0之后,Android中的权限除了需要在AndroidMainfest.xml文件中进行配置,部分核心权限必须在应用中向用户进行申请,需要用户主动点击才能够进行使用。

在6.0之前,APP如果申请的隐私权限,在安装时被直接允许,就能够在在用户毫不执行的情况下访问权限内的隐私信息,这项改动使得用户对于当前APP的使用的重要权限进行知晓,有利于保护用户隐私。

一、基本的权限申请

首先需要说明的一点是权限申请是需要在targetSDKVersion在23及之上才需要设置的。
权限申请包括有如下几个重要的方法:

  1. 权限检查

ActivityCompat.checkSelfPermission(this, Manifest.permission.XX)

  1. 权限申请

ActivityCompat.requestPermissions(final Activity activity,final String[] permissions, final int requestCode)

  1. 申请结果回调

onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)

  1. 申请被拒接处理

ActivityCompat.shouldShowRequestPermissionRationale(Activity activity,String permission)可再次申请
该方法返回false时表明本次申请权限被禁止询问申请,此时需要进行手动开启应用设置页手动允许

  1. 跳转至应用设置页

以悬浮窗权限为例

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.checkSelfPermissionContext.checkSelfPermission将会不起作用
需要使用
PermissionChecker.checkSelfPermission

同样targetSDKVersion >= 23PermissionChecker.checkSelfPermission也会无效,
需要使用ContextCompat.checkSelfPermission

注意此方法仅可以在Android8.0之下使用。

三、特殊权限

Android O之后多了一些权限需要额外申请,部分如下:

  1. 应用内安装应用权限
  2. 悬浮窗权限

这些权限同样需要申请,但是不会像文件读写权限一样直接弹出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)
            }
        }
    }

从代码可以看出,判断权限是否拥有上调用的方法有所不同:

  1. 悬浮窗权限使用的方法是Settings.canDrawOverlays(context))
  2. 应用内安装权限的方法是packageManager.canRequestPackageInstalls()

四、Android 10 文件读写

在Android 10 系统上,系统对于应用对文件的读写管理变得更加严格:

  1. app私有目录,不需要权限就可以访问。
  2. 媒体目录(相册、视频、音频...),需求申请READ_EATERNAL_STORAGE权限,访问方式使用MediaStore。
  3. 其他目录只能访问文件列表,不能再读写文件,需要将文件放到自己的私有目录才能读写。

因此需要在AndroidManifest.xmlApplication标签内添加如下配置才能够正常的进行文件读写:

android:requestLegacyExternalStorage="true"

总结

对Android目前权限的问题进行一个总结备忘。

你可能感兴趣的:(Android 动态权限备忘)