Android6.0新应用权限管理机制详解

随着Android系统的不断升级,Android系统在系统安全这一块也有了一定的提升,比如在Android5.0之前,用户安装任何应用都必须无条件接受该应用在AndroidManifest.xml文件中声明的权限,否则就只能不安装此应用,这也给了一些别有用心的应用可乘之机,用户的隐私也没法得到保证。到了Android5.0开始,用户在安装应用时会出现一个复选框,让用户选择授予该应用的一些权限,不选择则该应用不会拥有该权限。进入Android6.0以后,Google进一步对权限进行了控制,对于一些危险权限,必须在使用时动态申请,由用户授权之后,应用才会拥有该权限,这更加加强了应用的安全性。但这个变化也使得我们以前可以正常运行的应用受到了一定的影响,我们必须对其做一定的适配才能保证我们的应用正常运行,下面我们就来一起学习一下Android6.0的权限管理机制。

一、正常权限和危险权限

下面是Android官网对正常权限危险权限的解释:

  • 正常权限涵盖应用需要访问其沙盒外部数据或资源,但对用户隐私或其他应用操作风险很小的区域。例如,设置时区的权限就是正常权限。如果应用声明其需要正常权限,系统会自动向应用授予该权限。
  • 危险权限涵盖应用需要涉及用户隐私信息的数据或资源,或者可能对用户存储的数据或其他应用的操作产生影响的区域。例如,能够读取用户的联系人属于危险权限。如果应用声明其需要危险权限,则用户必须明确向应用授予该权限。

除了上面说的正常权限和危险权限,还有一个权限组的概念需要了解,权限组简单点理解就是讲权限进行分组,比如READ_CALENDAR权限和WRITE_CALENDAR权限属于CALENDAR这个组。任何权限都可属于一个权限组,包括正常权限和应用定义的权限。但权限组仅当权限危险时才影响用户体验。可以忽略正常权限的权限组,所以可以说所有危险的 Android 系统权限都属于权限组。

下面列出危险权限及其所属的组:

权限组 权限
CALENDAR READ_CALENDAR
WRITE_CALENDAR
CAMERA CAMERA
CONTACTS READ_CONTACTS
WRITE_CONTACTS
GET_ACCOUNTS
LOCATION ACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION
MICROPHONE RECORD_AUDIO
PHONE READ_PHONE_STATE
CALL_PHONE
READ_CALL_LOG
WRITE_CALL_LOG
ADD_VOICEMAIL
USE_SIP
PROCESS_OUTGOING_CALLS
SENSORS BODY_SENSORS
SMS SEND_SMS
RECEIVE_SMS
READ_SMS
RECEIVE_WAP_PUSH
RECEIVE_MMS
STORAGE READ_EXTERNAL_STORAGE
WRITE_EXTERNAL_STORAGE

除了上面的表,我们还可以在命令行中查看危险权限及其所属的组,在命令行中输入以下内容即可得到结果:

adb shell pm list permissions -g -d

二、应用请求危险权限的处理

下面我们说说应用在请求危险权限时系统的处理,如果设备运行的是 Android 6.0(API 级别 23),并且应用的 targetSdkVersion 是 23 或更高版本,则当用户请求危险权限时系统会发生以下行为:

  • 如果应用请求其清单中列出的危险权限,而应用目前在权限组中没有任何权限,则系统会向用户显示一个对话框,描述应用要访问的权限组。对话框不描述该组内的具体权限。例如,如果应用请求 READ_CONTACTS 权限,系统对话框只说明该应用需要访问设备的联系信息。如果用户批准,系统将向应用授予其请求的权限。
  • 如果应用请求其清单中列出的危险权限,而应用在同一权限组中已有另一项危险权限,则系统会立即授予该权限,而无需与用户进行任何交互。例如,如果某应用已经请求并且被授予了 READ_CONTACTS 权限,然后它又请求 WRITE_CONTACTS,系统将立即授予该权限。

上面是Android官网的介绍,从中可以看到很重要的一点 系统只告诉用户应用需要的权限组,而不告知具体权限

三、代码实战权限管理机制

上面说了那么多理论,现在就开始真正的实战,其实就简单的下面几步即可完成,我们下面以申请打电话权限为例:

1 . 在AndroidManifest.xml文件中添加需要的权限(适配Android6.0以下的系统)

AndroidManifest.xml文件中添加如下权限

<uses-permission android:name="android.permission.CALL_PHONE"/>

2 . 检查危险权限

我们在开始打电话之前必须先要检查我们是否拥有打电话的权限,对于正常的权限,系统默认是授予的,但对于打电话这种危险权限我们就必须先进行检查,此处调用ContextCompat.checkSelfPermission()方法进行检查,如果检查的结果是用户已经授予了我们此权限,那我们就可以直接调用打电话的逻辑,如果没有,那我们必须进行权限申请。

if (ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE)
        != PackageManager.PERMISSION_GRANTED){
    //做权限申请处理
    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CALL_PHONE}, CALL_PHONE_REQUEST_CODE);
}else{
    //用户已经授权,直接处理业务逻辑打电话
    doCallPhone();
}

3 . 申请授权

可以看出我们上面使用ActivityCompat.requestPermissions()方法申请权限,此方法的第二个参数可以传入一个权限数组,我们可以一次性申请多个权限,第三个参数是一个请求码,用于我们在下一步中根据申请的结果做回调处理。

ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CALL_PHONE}, CALL_PHONE_REQUEST_CODE);

4 . 处理申请回调

我们通过重写onRequestPermissionsResult()方法来处理回调结果

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    switch (requestCode){
        case CALL_PHONE_REQUEST_CODE:
            //打电话权限回调处理
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED){
                //打电话权限被授予
                doCallPhone();
            }else {
                //本次拒绝了权限请求,提示用户权限未被授予
                Toast.makeText(this, "权限申请失败", Toast.LENGTH_SHORT).show();
            }
            break;
        default:
            break;
    }
}

上面的requestCode就是我们在申请权限时提供的请求码,grantResults中存放着我们每个权限所对应的申请结果,由于我们只申请了一个权限,所以grantResults[0]即可。

当然,如果你向用户申请一个权限,而用户又拒绝了你的权限,等下次用户申请的时候还是会弹出用户授权窗口,这个时候你或许想更加清楚地给用户解释一下你为什么使用该权限,这个时候就需要用到ActivityCompat.shouldShowRequestPermissionRationale()这个方法。

这个方法会在应用首次安装时返回false,当用户拒绝了一次你的权限后也会返回true

注:当用户点击了授权窗口上的不再询问复选框时,该方法会返回false,你可以根据用户的行为来做出一些反应,但一般的权限申请窗口都对所申请的权限有一定的说明,除非特别情况,我们没有必要自己进行权限的说明解释。

四、更加优雅的实现权限申请及管理

说了上面那么多,你会发现权限申请最主要的就那么几步,但我们不能总是在每次需要申请的时候重复写代码,这个时候我们就可以去看看别人封装的库,其实也可以自己进行封装,下面推荐两个PermissionGenMPermissions

上面的两个库都有详细的使用方法,这里不再赘述,第一个库是基于运行时注解,使用时会影响性能,第二个库是基于编译时注解,对性能不会有影响。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 这是一篇迟到的文章。在6.0之前,在应用安装的时候,提示用户所需要用到的权限列表,同意之后安装,该app就被赋予所...
    蛋西阅读 5,667评论 1 5
  • 一、引言 随着Android6.0发布,系统增加了一些新的特性和功能。这次的发布介绍了一种新的权限机制。用户可以在...
    宇是我阅读 7,602评论 7 41
  • Android 是一个特权分离(privilege-separated)操作系统,在其中每个应用都以一个不同的系统...
    DanieX阅读 4,137评论 0 3
  • 姓名:张义跃 245期谦虚1组学员 公司:本一设计 【日精进打卡第118天】 【知~学习】 《六项精进》诵读0遍共...
    小小蛋儿阅读 174评论 0 0
  • 最近新浪微盘、迅雷快盘、华为网盘、UC网盘等相继宣布关闭,停止个人云存储服务,唱衰网盘的论调不绝于耳,那么到底是什...
    淡雅的清新阅读 1,756评论 0 0