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

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335

推荐阅读更多精彩内容

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