8月更文挑战|Android基础开发-应用权限使用管理

725 阅读4分钟

这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战

应用权限介绍

Android在6.0时代之后就有权限申请机制,将应用权限划分为普通权限和危险权限。应用在使用危险权限时需要动态申请获取授权后才能使用,否则将无法正常使用功能并会抛出异常。

为什么会划分正常权限和危险权限?正常权限的使用范围不会侵犯到用户隐私,比如马达震动、设置闹钟等;危险权限则可能会干涉到用户隐私,比如拍照、访问文件、打电话等。

权限动态申请方法

  • 在AndroidManifest文件中注册需要的权限
<uses-permission android:name="android.permission.CAMERA" />
  • 检查权限是否已经同意
ContextCompat.checkSelfPermission(this@PermissionActivity,Manifest.permission.CAMERA)
  • 申请该权限
ActivityCompat.requestPermissions(this@PermissionActivity, arrayOf(Manifest.permission.CAMERA), 0)
  • 解释并引导用户申请权限
ActivityCompat.shouldShowRequestPermissionRationale(this@PermissionActivity,Manifest.permission.CAMERA)

该方法主要是用于当用户多次拒绝权限申请的时候使用,因为在权限访问弹窗上会有”不再提醒“勾选项。当用户勾选以后申请权限都不会去执行requestPermissions方法了。因此通过shouldShowRequestPermissionRationale方法当上次弹窗权限被禁止并且勾选”不再提醒“时返回false可以引导并告知用户申请权限理由。

PS: 在实际开发中并没有特别多使用到该方法去提升用户体验。主要原因是国产Room很多做过魔改并不能保证方法返回的结果是够准确,可以通过其他方式实现一样的效果。

  • 申请权限结果回调
override fun onRequestPermissionsResult(
    requestCode: Int,
    permissions: Array<out String>,
    grantResults: IntArray
) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}

在申请权限结果回调中再次使用checkSelfPermission判断权限是否申请通过若结果等于PackageManager.PERMISSION_GRANTED则表示申请成功。

权限申请要素

在官方权限使用指导文档中提到了,在为应用注册申请权限前开发者需要认真考虑,当前应用是否真的需要去申请危险权限。因为过度权限申请和权限滥用可能会导致用户的使用体验甚至卸载应用。

  1. 可通过Intent将任务委托给其他应用 例如简单使用拍摄照片功能可调用ACTION_IMAGE_CAPTUREintent操作;录制视频可调用ACTION_VIDEO_CAPTUREintent操作。此时就不会涉及到应用动态申请权限的问题。具体情况具体分析,若应用需要有更多相机相关能力采用自定义相机方式实现功能则不适用此方法。

  2. 在用户需要使用相关权限功能时再请求权限 不要一次性动态申请应用所有权限,比如在启动页申请所有权限开屏各种权限弹窗。过去还有应用存在不给权限无法正常使用的情况。杜绝滥用权限申请,只做使用功能时才去申请。

  3. 同时多次调用requestPermissions 这个case在之前开发中遇到过,触发场景是当多个Fragment初始化时同时申请相同权限,一个相机拍照页面申请读写权限,一个相册页面申请读写权限。这个过程导致了用户没有选择是否同意权限系统主动执行了授权结果回调onRequestPermissionsResult,导致权限没有申请通过却执行了下一步引起应用崩溃。

  4. 国产Room低端机权限申请 Android碎片化严重和国产机Room魔改导致原有低端机(6.0 API23以下系统)并不需要动态申请权限,只要在manifest注册即可使用却也需要用户授权。 6.0 API23以下系统的国产手机使用checkSelfPermission是无法正常检查权限是否通过授权的,只能通过try-catch对权限功能做保护,若抛出异常指导用户去系统设置中开启应用权限。

权限申请第三方解决方案

官方提供的权限申请可能并不完美,可以试试使用第三方权限申请开源库去兼容权限相关功能能力。 PermissionX是比较不错的权限申请库,具备相关权限申请外还支持特殊权限申请(悬浮窗、修改设置、管理外部存储等)

依赖

implementation 'com.guolindev.permissionx:permissionx:1.5.1'

调用使用

PermissionX.init(activity)
    .permissions(Manifest.permission.READ_CONTACTS, Manifest.permission.CAMERA, Manifest.permission.CALL_PHONE)
    .request { allGranted, grantedList, deniedList ->
        if (allGranted) {
            Toast.makeText(this, "All permissions are granted", Toast.LENGTH_LONG).show()
        } else {
            Toast.makeText(this, "These permissions are denied: $deniedList", Toast.LENGTH_LONG).show()
        }
    }