1、封装成工具库的必要性
- 权限申请状态判断逻辑复用:
这些权限在和用户交互过程中可能全部授予、部分授予或全部拒绝 - Rational 对话框时机管理: 如果应用之前请求过此权限但用户拒绝了请求,
shouldShowRequestPermissionRationale 方法将返回 true,此时建议提醒用户我们为什么需要此权限。 - 不同手机、不同系统版本兼容:例如小米手机有自己的权限管理,所以在权限判断部分会有不同。
2、runtime permission 接入流程封装
android 6.0 如何接入参考这篇文章:《Android 6.0 在运行时请求权限》,以下介绍以下6.0权限接入流程:

- App调用方需要在需要申请权限的逻辑前调用Facade申请关联的权限
- (filter permissions)Facade从系统查询申请的权限列表中哪些已授权,哪些是拒绝的待授权。当sdk-ver >=23 && target-sdk-ver >= 23时使用ActivityCompat.checkSelfPermission;当sdk-ver >=23 && target-sdk-ver < 23时使用PermissionChecker.checkSelfPermission;其它条件都认为是已授权的
- Facade会对sdk-ver(手机操作系统版本)和 target-sdk-ver (App的targetsdkversion)做不同流程处理:当sdk-ver >=23 && target-sdk-ver >= 23时,需要对拒绝的权限主动申请,反之是不需要向系统申请权限的
- 如果需要像系统申请权限,需要根据shouldShowRequestPermissionRationale 为true时向用户弹窗提示申请权限的理由。该弹窗的确认按钮的操作应该是继续申请权限
- 最终将权限的申请结果返回给调用方来决定是否继续此前的操作
3、 GitHub 开源权限框架分析 —PermissionsDispatcher
PermissionsDispatcher的框架是就是上面的流程设计的,但是他的绿色部分(App调用方)使用annotationProcessor来处理的。一个很明显的效果是接入代码只需要在相应的注解下面写业务代码即可,让代码逻辑变的更简单。
该框架的github地址:https://github.com/permissions-dispatcher/PermissionsDispatcher
java 注解处理:https://www.race604.com/annotation-processing/
4、一个简单的工具方法,封装动态权限申请操作
对于第二节工具层的简单的封装示例如下(不包括其中的Rationale对话框逻辑)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
/** * 一个方便的方法,用于在执行操作前检查特定的权限 * * @param sceneId 用于统计打点使用,业务场景ID,不能和其它业务场景重复 * @param checkResult * @param permissions */ public static void operateWithPermissions(int sceneId, final PermissionCheckResult checkResult, final String... permissions) { //过滤出没有权限,需要申请的权限列表 List<String> needCheckPermissionList = filterGrantedPermissions(permissions); int needCheckPermissionSize = needCheckPermissionList.size(); //如果申请的权限都已经授权,则返回所有权限授权成功 if(needCheckPermissionSize == 0) { if(checkResult != null) { checkResult.onAllPermissionGranted(); } } else { //如果需要申请权限,则根据当前的系统版本和targetsdkversion判断是否需要动态申请权限 if(needRequestPermission()) { final String[] toCheckPermissionArr = new String[needCheckPermissionSize]; needCheckPermissionList.toArray(toCheckPermissionArr); //动态申请权限 PermissionUtils.requestPermissionsForResult(toCheckPermissionArr, new PermissionResultCallbackBridge() { @Override public void onGranted(String permission) { } @Override public void onDenied(String permission) { } @Override public void finished(Bundle data) { //检查权限的申请结果 boolean hasAllPermissions = true; for(String perm : toCheckPermissionArr) { boolean hasPermission = data.getBoolean(perm, false); if(!hasPermission) { hasAllPermissions = false; break; } } if(checkResult != null) { if(hasAllPermissions) { checkResult.onAllPermissionGranted(); } else { checkResult.onPermissionDenied(); } } } }, null, sceneId); } else { //如果不能动态申请权限,用户也没有赋予该权限,则返回失败,此时调用方应该拉起设置页面 if(checkResult != null) { checkResult.onPermissionDenied(); } } } } private static List<String> filterGrantedPermissions(String... permissions) { List<String> needCheckPermissionList = new ArrayList<String>(); for(String permission : permissions) { if(!PermissionUtils.checkPermission(permission)) { needCheckPermissionList.add(permission); } } return needCheckPermissionList; } public static boolean needRequestPermission() { final int TARGETSDKVERSION = AppContextHelper.appContext().getApplicationInfo().targetSdkVersion; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && TARGETSDKVERSION >= Build.VERSION_CODES.M) { return true; } else { return false; } } public interface PermissionCheckResult { void onAllPermissionGranted(); void onPermissionDenied(); } |