Android(安卓)动态权限申请之 shouldShowRequestPermissionRationale方法异常
我们知道从Android 6.0(API 23) 开始,Google在Android上引入了动态权限模式,即用户可在应用运行时管理权限, 这种模式让用户能够更好地了解和控制权限,用户可为所安装的各个应用分别授予或撤销权限。 但是对于开发者来说,为了适配Android 6.0(API 23)及以上版本,除了在AndroidManifest.xml中去声明相关权限, 对于Android官网中划分的危险权限 https://developer.android.com/guide/topics/permissions/overview, 还需要在代码中判断该应用是否被授予权限,以保证程序的正常运行。
(1)ContextCompat.checkSelfPermission()
ContextCompat.checkSelfPermission()方法来检测某个权限是否被授予
(2) ActivityCompat.requestPermissions()
ActivityCompat.requestPermissions()方法用来动态申请权限,我们在调用requestPermission()方法去申请权限时,系统会弹出权限申请提示框,可以同意授予,用户可以拒绝,如果用户选择了拒绝,并且勾选了不再提示,那么再次调用ActivityCompat.requestPermissions()方法申请该权限时,系统就不会弹出权限申请的弹窗了。
(3)onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
回调方法
无论用户同意授权,还是拒绝了授权,都会在onReuqestPermissionResult()回调方法中返回用户的选择结果。
(4)shouldShowRequestPermissionRationale()
前面说过,使用ActivityCompat.requestPermissions()方法用来动态申请权限,系统会弹出权限申请提示框,可以同意授予,用户可以拒绝,如果用户选择了拒绝,并且勾选了不再提示,那么再次调用ActivityCompat.requestPermissions()方法申请该权限时,系统就不会弹出权限申请的弹窗了,那么我们该怎么告知用户需要去开启某个权限呢?
这个时候就要引出我们今天说的主角shouldShowRequestPermissionRationale(),该方法来判断用户是否拒绝过授予权限,并且勾选了不再提示操作。如果shouldShowRequestPermissionRationale()返回true,则说明之前用户绝拒绝了授权,并且勾选了不再提示,这个时候应用可以提示用户去设置中开启权限。
介绍了上面的几个方法,下面给出之前我们项目中实现高德地图定位,动态申请权限的代码
高德地图定位需要动态申请的权限有:
/** * 初始化高德定位 */ private void initGaoDeLocation() { if (Build.VERSION.SDK_INT >= 23) { if (ContextCompat.checkSelfPermission(mActivity, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { if (ActivityCompat.shouldShowRequestPermissionRationale(mActivity, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { //用户已拒绝过一次 //提示用户如果想要正常使用,要手动去设置中授权。 ToastUtil.showShort(mActivity, "请到设置-应用管理中开启此应用的读写权限"); } else { ActivityCompat.requestPermissions(mActivity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_PHONE_STATE}, PERMISSION_REQUEST_CODE_LOCATION); } } else if (ContextCompat.checkSelfPermission(mActivity, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { if (ActivityCompat.shouldShowRequestPermissionRationale(mActivity, Manifest.permission.ACCESS_FINE_LOCATION)) { //用户已拒绝过一次 //提示用户如果想要正常使用,要手动去设置中授权。 ToastUtil.showShort(mActivity, "请到设置-应用管理中开启此应用的定位权限"); } else { ActivityCompat.requestPermissions(mActivity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_PHONE_STATE}, PERMISSION_REQUEST_CODE_LOCATION); } } else if (ContextCompat.checkSelfPermission(mActivity, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) { if (ActivityCompat.shouldShowRequestPermissionRationale(mActivity, Manifest.permission.READ_PHONE_STATE)) { //用户已拒绝过一次 //提示用户如果想要正常使用,要手动去设置中授权。 ToastUtil.showShort(mActivity, "请到设置-应用管理中开启此应用的电话权限"); } else { ActivityCompat.requestPermissions(mActivity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_PHONE_STATE}, PERMISSION_REQUEST_CODE_LOCATION); } } else { DialogUtil.showUnCancelableProgress(mActivity, "正在进行定位"); gaoDeLocation(); } } else { DialogUtil.showUnCancelableProgress(mActivity, "正在进行定位"); gaoDeLocation(); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case PERMISSION_REQUEST_CODE_LOCATION: if (grantResults[0] != PackageManager.PERMISSION_GRANTED) { ToastUtil.showShort(mActivity, "请在到设置-应用管理中开启此应用的储存授权"); return; } if (grantResults[1] != PackageManager.PERMISSION_GRANTED) { ToastUtil.showShort(mActivity, "请在到设置-应用管理中开启此应用的定位权限"); return; } if (grantResults[2] != PackageManager.PERMISSION_GRANTED) { ToastUtil.showShort(mActivity, "请在到设置-应用管理中开启此应用的获取电话权限"); return; } DialogUtil.showUnCancelableProgress(mActivity, "正在进行定位"); gaoDeLocation(); break; } }
但是我们今天的标题是Android 动态权限申请之 shouldShowRequestPermissionRationale方法异常,所以回到我们的主题,由于Android系统的碎片化,在国内,不同手机厂商都对Android系统都做了不同的定制,上面的代码在大部分手机上测试没有任何问题,直到某天在公司的测试机 努比亚 Z17 mini S,Android系统版本是Android 7.1.1,发现首次执行该段代码,shouldShowRequestPermissionRationale()就返回true,
也就是说在这个努比亚手机上,用户没有拒绝过授予权限,并且也没有勾选不再提示,shouldShowRequestPermissionRationale()也会返回true,所以上面的这段代码,永远也不会执行到ActivityCompat.requestPermissions(mActivity,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_PHONE_STATE},
PERMISSION_REQUEST_CODE_LOCATION);
永远不会弹出权限授予弹窗。
所以为了适配努比亚手机,我将上述代码改成了如下:
/** * 初始化高德定位 */ private void initGaoDeLocation() { if (Build.VERSION.SDK_INT >= 23) { if (ContextCompat.checkSelfPermission(mActivity, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(mActivity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_PHONE_STATE}, PERMISSION_REQUEST_CODE_LOCATION); } else if (ContextCompat.checkSelfPermission(mActivity, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(mActivity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_PHONE_STATE}, PERMISSION_REQUEST_CODE_LOCATION); } else if (ContextCompat.checkSelfPermission(mActivity, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(mActivity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_PHONE_STATE}, PERMISSION_REQUEST_CODE_LOCATION); } else { DialogUtil.showUnCancelableProgress(mActivity, "正在进行定位"); gaoDeLocation(); } } else { DialogUtil.showUnCancelableProgress(mActivity, "正在进行定位"); gaoDeLocation(); } }
不再使用shouldShowRequestPermissionRationale,只要判断到权限没有被授予,就去调用 ActivityCompat.requestPermissions()去申请权限;如果用户选择了拒绝,并且勾选了不再提示,调用ActivityCompat.requestPermissions(),虽然不会弹出权限申请弹窗,但是会直接
回调onRequestPermissionResult()方法,我们只需要在该回调方法中去提示用户去设置中开启权限即可。
更多相关文章
- Android(安卓)版本适配6.0到9.0
- Android(安卓)root 原理
- 2010最佳Android和iPhone/iPad游戏应用出炉
- Android中文件读写错误 open failed: ENOENT (No such file or d
- Android通过代码获取ROOT权限
- ubuntu下运行android emulator权限不够解决方法
- android 模拟器 sdcard权限修改
- Android系统权限和root权限的获取以及应用权限列表
- Android(安卓)M 运行时权限