Android 6.0 运行时权限 总结 & 实践

版权声明:本文来自书生依旧的简书,转载请注明出处 。

一. 运行时权限适配前

  1. 什么时候会触发运行时权限机制?

    targetSdkVersion >= 23 ,运行在 Android 6.0 及以上设备上,使用 危险权限 的时候。

  2. 触发了运行时权限,没有进行适配会怎么样?

    应用崩溃。

  3. 来不及适配怎么办?

    设置 targetSdkVersion < 23,会和以前一样,在应用安装申请所有的权限。值得注意的是用户依然可以在设置里取消已授权的权限,这时候应用虽然不会崩溃,但是肯定是无法使用这个权限的,而且不会给用户任何的提示。

二. 权限组

  • Android 将不同的权限分组管理,任何权限都会属于一个权限组,包括正常权限和危险权限。
  • 应用申请危险权限时,系统会向用户显示一个对话框,描述应用要访问的权限组,而不是不描述要申请的具体权限。一个权限组有一个权限申请成功,则默认该权限组所有权限申请成功,再次申请该组其他权限时,系统将立即授予该权限,不会再显示申请权限的对话框。
  • 危险权限共 9 组 24 个
权限组 权限
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

三. API 详解

  1. checkSelfPermission
   // 检查某个权限是否已授权
   ActivityCompat.checkSelfPermission(Context context, String permission)  
   // permission:要检查的权限
   // 返回值是 int 类型,PackageManager#PERMISSION_GRANTED 表示有权限,PackageManager#PERMISSION_DENIED 表示没有权限
  1. requestPermissions
   // 申请权限
   ActivityCompat.requestPermissions(final @NonNull Activity activity, final @NonNull String[] permissions, final @IntRange(from = 0) int requesPackageManager#PERMISSION_GRANTEDtCode)
   // permissions:要申请的权限,可以一次申请多个
   // requestCode:请求码,在申请权限的回调中用到
  • 调用这个方法必然会走 onRequestPermissionsResult 的回调。
  1. onRequestPermissionsResult
   // 申请权限的回调,在 Activity 和 Fragment 中都有
   onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
   // requestCode:requestPermissions 的参数,请求码
   // permissions:请求授权的权限,是一个数组,对应我们前面申请的多个权限
   // grantResults:授权结果,也是一个数组,对应上面每个权限的申请结果,PERMISSION_GRANTED 同意,PERMISSION_DENIED 拒绝
  1. shouldShowRequestPermissionRationale
   // 申请某个权限时我们是否要给用户解释一下
   ActivityCompat.shouldShowRequestPermissionRationale(@NonNull Activity activity, @NonNull String permission)
   // permission:要解释的权限
  • 如果用户拒绝过我们的权限申请,shouldShowRequestPermissionRationale 会返回 true。此时我们最好弹出一个对话框告诉用户,你拒绝过我的权限申请,我申请这个权限是做什么用的,希望你能同意等等。
  • shouldShowRequestPermissionRationale 会返回 true 的时候,我们再次申请权限,会有一个 "不再提醒" 的 checkBox ,当用户勾选上时,我们再次调用 shouldShowRequestPermissionRationale 会返回 false,意思说用户都不想看到了,就没有必要再解释了。
  • 注意:用户选择 "不再提醒" 后,再次 requestPermissions 总是会失败,但是会走 onRequestPermissionsResult 的回调。
  • 总结:shouldShowRequestPermissionRationale 返回 false,有两种可能,一是我们第一次申请权限的时候,二是用户选择了 "不再提醒"。shouldShowRequestPermissionRationale 返回 true 是用户拒绝过我们的权限申请但是没有勾选 "不再提醒"。

四. 权限适配最佳套路

  1. 在 AndroidManifest.xml 添加权限声明。

  2. 使用 checkSelfPermission 检查某个权限是否已经申请。

  3. 权限未申请,使用 requestPermissions 申请权限。

  4. 在 onRequestPermissionsResult 回调中判断权限是否申请成功。

  5. 申请失败使用 shouldShowRequestPermissionRationale 判断用户是否勾选了 "不再提醒"。

    • shouldShowRequestPermissionRationale 返回 fasle 勾选了的话,弹出一个 Dialog 引导用户到设置界面授予权限,并在返回 Result 中再次判断用户是否同意权限,不同意的话怎给出提示。

      // 到设置界面授予权限
      Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
      Uri uri = Uri.fromParts("package",getPackageName(), null);
      intent.setData(uri);
      
      // startActivityForResult(intent);
      // 我这里使用的是 RxActivityResult 这个库
      RxActivityResult.on(context)
                      .startIntent(intent)
                      .subscribe(activityResult -> {
                         // 再次判断用户是否同意的权限,同意执行后面的操作,不同给出提示。
                         checkPermission();
                      });
      

    • 没有勾选,可以什么都不做,也可以弹出弹出一个 Dialog 引导用户到设置界面授予权限。

五. 需要注意的地方

  • READ_PHONE_STATE、READ_EXTERNAL_STORAGE、WRITE_EXTERNAL_STORAGE 几乎是必须的,可以放在启动页申请,用户拒绝后引导至设置页面。
  • 同时申请多个权限时,用户可能仅仅同意某个权限,在 onRequestPermissionsResult 要循环判断每个是否申请成功,然后进行后续的操作。

六. 推荐几个类库

两个 star 比较多的运行时权限管理库

  • RxPermissions

  • PermissionsDispatcher

    值得一说的是,第二个库我在他的 issues 看到了解决了小米手机的相关问题(具体没有去探究),第一个嘛,看名字也知道支持 RxJava 。

还有就是上文我使用的 RxActivityResult

Thanks

Android M 新的运行时权限开发者需要知道的一切

Android 6.0 运行时权限处理完全解析

6.0运行时权限的总结与实践

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

推荐阅读更多精彩内容