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,则说明之前用户绝拒绝了授权,并且勾选了不再提示,这个时候应用可以提示用户去设置中开启权限。

介绍了上面的几个方法,下面给出之前我们项目中实现高德地图定位,动态申请权限的代码
高德地图定位需要动态申请的权限有:

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
 /**
     * 初始化高德定位
     */
    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()方法,我们只需要在该回调方法中去提示用户去设置中开启权限即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值