(TOP)Android-M权限——关于shouldShowRequestPermissionRationale详解

众所周知,在Android M,也就是6.0的手机上,权限在安装的时候是不默认获取的,和iOS的做法一样,只有在需要的时候动态获取。

概述

关于权限的请求回调之类的文章很多,官网见:https://developer.android.com/training/permissions/requesting.html,我之前转载过一篇文章:Android-M动态权限获取

小小的需求

本文不打算重复这些,而是要说一个有意思的API:shouldShowRequestPermissionRationale。

说下一个简单的需求:希望在用户需要这个权限而这个权限之前就已经不再提示的时候,弹出一个解释的弹窗,大家可以先思考一下怎么实现。

国内的几乎所有讲权限的文章都忽略了这个点,大部分可能是直接翻译了官网文章,其他人可能是没遇到这个需求?

流程

首先先说下官网请求权限的大概流程(官网的demohttps://github.com/googlesamples/android-RuntimePermissions):

首先判断是否已有权限,使用

ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED

如果有权限,则直接执行业务逻辑,如果没有权限,则请求权限,但是!在请求之前,可能需要先解释一下为什么需要这个权限,通过

ActivityCompat.shouldShowRequestPermissionRationale(this,permission)

为什么要有这一步呢?是因为权限第一次弹出的时候用户点击了拒绝,那么下一次弹出的时候这个弹窗上面就会有是否不再提示的选择,第一次shouldShowRequestPermissionRationale返回false,表示不需要解释,那么就直接请求权限,如果是第二次,确切地说,应该是弹窗应该显示不再提示的勾选项而用户之前没有勾选不再提示,那么shouldShowRequestPermissionRationale返回true,表示需要向用户先解释一下再请求。这句话有点绕,可是我找不到更好的表达方式了。

所以,你需要在这个方法返回true的时候先toast一下或者弹出个弹窗,告诉用户你为什么需要这个权限,然后再调用

ActivityCompat.requestPermissions(MainActivity.this,new String[]{permission},REQUEST_CODE);

去真正请求权限。

这里就有埋了一个坑,如果用户之前勾选了不再提示,shouldShowRequestPermissionRationale返回什么?答案是false。也就是说,我们在请求权限的时候是区分不出第一次请求还是之前选过不再提示的。当然,现在我们还不需要区分这点。

ok,这时候我们已经发出了权限请求,然后activity会收到回调

onRequestPermissionsResult

在这个回调里我们可以知道请求的哪些权限获取到了,哪些拒绝了,根据这些信息我们很轻松地就可以知道自己需不需要执行后续逻辑,perfect。

前方有坑

但是!现在产品经理突然和你提了文章开头说的那个需求。

这里有一个点需要解释一下,如果用户之前点过不再提示,那么requestPermissions将不再弹出系统的请求权限弹窗,而是直接回调到activity的onRequestPermissionsResult中,并且该权限为拒绝状态。

这TM就尴尬了,产品经理的需求听上去很有道理的样子,我都无法反驳,但是系统似乎没告诉我这个API啊…

一点思考

上面说到,在请求权限的时候,shouldShowRequestPermissionRationale区分不出第一次请求还是之前选过不再提示的,但是,请求回调中,针对第一次请求权限来说,拒绝了权限之后,shouldShowRequestPermissionRationale返回true,而针对之前勾选不再提示的请求,shouldShowRequestPermissionRationale是返回false。这就意味着,我只要整合一下请求和回调的结果就可以知道哪些权限是第一次请求且拒绝的,哪些是之前选过不再提示所以回调自动拒绝的。

具体解决方案

说了这么多,就说下解决方案:在requestPermissions之前先判断下shouldShowRequestPermissionRationale,记录下返回false的权限,这些权限要么是第一次请求的,要么是之前选了不再提示。然后再权限回调onRequestPermissionsResult中,对拒绝的权限同样判断shouldShowRequestPermissionRationale,对第一次请求的权限,这个API返回的是true,而对之前选择不再提示的权限返回的是false。

我看了一下网易的权限流程是可以在不再提示之后再次请求弹出弹窗的,不清楚具体是不是这样做的。

ok,关于shouldShowRequestPermissionRationale就这么多,有解释不清楚的地方记得给我反馈,反正我不会改。

写完收工~