Android 权限请求 -- 对开发者更友好的危险权限请求处理

基于 Easypermissions 简化危险权限请求流程

搬运直接从3.实现效果开始看就行了

目录

1.概述

2. 分析

3.实现效果

4.实现步骤

4.1-导入EasyPermissions库

4.2-声明回调接口

4.3-声明帮助类

4.4 具体使用

参考文献


1.概述

Android 6.0开始引入权限申请机制,应用的相关功能每次在使用危险权限时需要动态的申请并得到用户的授权才能使用。

正常权限:不会直接给用户隐私权带来风险。如果您的应用在其清单中列出了正常权限,系统将自动授予该权限。

危险权限:会授予应用访问用户机密数据的权限。如果您的应用在其清单中列出了正常权限,系统将自动授予该权限。如果您列出了危险权限,则用户必须明确批准您的应用使用这些权限。

特殊权限

有许多权限其行为方式与正常权限及危险权限都不同。SYSTEM_ALERT_WINDOW 和 WRITE_SETTINGS 特别敏感,因此大多数应用不应该使用它们。如果某应用需要其中一种权限,必须在清单中声明该权限,并且发送请求用户授权的 intent。系统将向用户显示详细管理屏幕,以响应该 intent。  

权限组

所有危险的 Android 系统权限都属于权限组。每组只要有一个权限申请成功了,就默认整组权限都可以使用了。

2. 分析

Android6.0及以上危险权限申请流程

如图可见,如果用户未勾选“不再询问”(永久拒绝),那么申请流程是从左往右横向走下去的,对于开发者就能很方便的得到权限请求成功/失败的回调。

但当用户勾选了“不再询问”并拒绝了当次请求(也就是永久拒绝)后,下次再发起权限请求时,则无法直接弹出“权限请求询问弹窗”了,此时就要引导用户前往设置页面手动设置权限。

在Activity/Fragment的onRequestPermissionsResult()方法里获取权限请求回调,判断成功/拒绝、成功几个、拒绝几个、是否有被永久拒绝

用户前往设置页面手动设置权限或未操作,回到APP后,市面上不同APP有不同的做法。假设身为开发者我希望APP监听到用户从设置页面回到APP后,希望继续走我的流程:有权限TODO、没权限TODO,那我就不得不继续在onActivityResult方法里写判断做处理......加上上面onRequestPermissionsResult方法里的代码量,想想就觉得得简化一下

想达到的流程效果图

如上流程图,动态权限的请求流程就很好的闭环了,而且对于开发者来说,每次发起请求就只会出现两种结果回调:允许or拒绝。

 

3.实现效果

开发者只需发起申请并监听成功和失败的回调即可,至于用户是否勾选永久拒绝、是否跳转设置页面、从设置页面回来后是否真的有拿到权限等判断,都在RequestPermissionHelper里接受处理了

getRequestPermissionHelper().requestPermissions(this, REQUEST_CODE_PERMISSION, "获取相机和读写权限", new PermissionCallback() {
            @Override
            public void requestPermissionSuccess(int requestCode) {
                //TODO 用户授予权限
            }

            @Override
            public void requestPermissionFailed(int requestCode) {
                //TODO 用户拒绝授予权限

            }
        }, Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE);

 

4.实现步骤

4.1-导入EasyPermissions库

model的build.gradle文件内添加

...

dependencies {
    ...

    implementation 'pub.devrel:easypermissions:3.0.0'
}

4.2-声明回调接口

/**
 * Author : Ziwen Lan
 * Date : 2019/10/25
 * Time : 10:45
 * Introduction :
 */
public interface PermissionCallback {
    /**
     * 请求权限成功回调
     */
    void requestPermissionSuccess(int requestCode);

    /**
     * 请求权限失败回调
     */
    void requestPermissionFailed(int requestCode);
}

4.3-声明帮助类

/**
 * Author : Ziwen Lan
 * Date : 2019/10/25
 * Time : 11:32
 * Introduction : 权限请求帮助类
 */
public class RequestPermissionHelper {
    private Activity mActivity;
    private Fragment mFragment;
    //请求码
    private int mPermissionRequestCode;
    //请求描述
    private String mPermissionsRequestRationale;
    //请求结果回调
    private PermissionCallback mPermissionCallback;
    //请求的权限数组
    private String[] mRequestPermissions;
    //永久拒绝时弹窗
    private AppSettingsDialog mAppSettingsDialog;

    /**
     * EasyPermissions请求结果回调
     */
    private EasyPermissions.PermissionCallbacks mPermissionCallbacks = new EasyPermissions.PermissionCallbacks() {
        @Override
        public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {
            //获得授予的权限
            //请求的全部权限获取成功才表示获取成功
            if (perms.size() == mRequestPermissions.length) {
                mPermissionCallback.requestPermissionSuccess(requestCode);
            }
        }

        @Override
        public void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {
            //被拒绝的权限
            if ((mActivity == null && EasyPermissions.somePermissionPermanentlyDenied(mFragment, perms))
                    || (mFragment == null && EasyPermissions.somePermissionPermanentlyDenied(mActivity, perms))) {
                //存在权限被永久拒绝 -- 此时要跳转系统软件设置页面,让用户手动给予权限
                    if (mAppSettingsDialog == null) {
                    AppSettingsDialog.Builder builder;
                    if (mActivity == null) {
                        builder = new AppSettingsDialog.Builder(mFragment);
                    } else {
                        builder = new AppSettingsDialog.Builder(mActivity);
                    }
                    mAppSettingsDialog = builder
                            .setTitle("权限申请")
                            .setRationale(mPermissionsRequestRationale + "失败,请手动授权")
                            .setPositiveButton("确定")
                            .setNegativeButton("取消")
                            .setRequestCode(mPermissionRequestCode)
                            .build();
                    mAppSettingsDialog.show();
                } else {
                    //权限获取失败
                    mAppSettingsDialog = null;
                    mPermissionCallback.requestPermissionFailed(requestCode);
                }
            } else {
                //权限获取失败
                mPermissionCallback.requestPermissionFailed(requestCode);
            }
        }

        @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

        }
    };


    /**
     * 重复请求
     */
    public void requestPermissionsAgain(int requestCode) {
        if (requestCode == mPermissionRequestCode) {
            if (mActivity == null) {
                requestPermissions(mFragment, mPermissionRequestCode, mPermissionsRequestRationale, mPermissionCallback, mRequestPermissions);
            } else {
                requestPermissions(mActivity, mPermissionRequestCode, mPermissionsRequestRationale, mPermissionCallback, mRequestPermissions);
            }
        }
    }

    /**
     * 请求权限
     *
     * @param requestCode 权限请求码
     * @param rationale   权限请求描述(eg: 申请获取定位权限、图片相关权限)
     * @param perms       Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.ACCESS_FINE_LOCATION
     */
    public void requestPermissions(Activity activity, int requestCode, @NonNull String rationale, PermissionCallback permissionCallback, @NonNull String... perms) {
        mActivity = activity;
        mPermissionRequestCode = requestCode;
        mPermissionsRequestRationale = rationale;
        mPermissionCallback = permissionCallback;
        mRequestPermissions = perms;
        if (EasyPermissions.hasPermissions(mActivity, perms)) {
            //存在权限
            mPermissionCallback.requestPermissionSuccess(requestCode);
        } else {
            //不存在权限,发起申请
            EasyPermissions.requestPermissions(mActivity, rationale, requestCode, perms);
        }
    }

    /**
     * 请求权限
     *
     * @param requestCode 权限请求码
     * @param rationale   权限请求描述(eg: 申请获取定位权限、图片相关权限)
     * @param perms       Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.ACCESS_FINE_LOCATION
     */
    public void requestPermissions(Fragment fragment, int requestCode, @NonNull String rationale, PermissionCallback permissionCallback, @NonNull String... perms) {
        mFragment = fragment;
        mPermissionRequestCode = requestCode;
        mPermissionsRequestRationale = rationale;
        mPermissionCallback = permissionCallback;
        mRequestPermissions = perms;
        if (EasyPermissions.hasPermissions(mFragment.getContext(), perms)) {
            //存在权限
            mPermissionCallback.requestPermissionSuccess(requestCode);
        } else {
            //不存在权限,发起申请
            EasyPermissions.requestPermissions(mFragment, rationale, requestCode, perms);
        }
    }

    public EasyPermissions.PermissionCallbacks getPermissionCallbacks() {
        return mPermissionCallbacks;
    }
}

4.4 具体使用

BaseActivity/BaseFragment(推荐)或者是你要发起权限申请的Activity/Fragment里重写以下方法

//------------权限请求相关 start------------
    private RequestPermissionHelper mRequestPermissionHelper;

    public RequestPermissionHelper getRequestPermissionHelper() {
        if (mRequestPermissionHelper == null) {
            mRequestPermissionHelper = new RequestPermissionHelper();
        }
        return mRequestPermissionHelper;
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (mRequestPermissionHelper != null) {
            //设置页面授予权限回调
            mRequestPermissionHelper.requestPermissionsAgain(requestCode);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (mRequestPermissionHelper != null) {
            EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, mRequestPermissionHelper.getPermissionCallbacks());
        }
    }
//------------权限请求相关 end------------

AndroidManifest中声明要申请的权限

发起申请

getRequestPermissionHelper().requestPermissions(this, REQUEST_CODE_PERMISSION, "获取相机和读写权限", new PermissionCallback() {
            @Override
            public void requestPermissionSuccess(int requestCode) {
                //TODO 用户授予权限
            }

            @Override
            public void requestPermissionFailed(int requestCode) {
                //TODO 用户拒绝授予权限

            }
        }, Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE);

到此结束,如有更好的见解或建议,欢迎留言

 

参考文献

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值