Android动态权限(兼容6.0以下和魅族手机方案)

这里以照相机权限为例说明问题。实际开发过程中遇到了不少的坑。

1、一般情况下,6.0以上的手机:
①判断是否具有某项权限:
ContextCompat.checkSelfPermission()
下面这段代码展示了判断手机是否具有相机权限:

boolean hasCameraPermission = hasPermission(Manifest.permission.CAMERA);@TargetApi(Build.VERSION_CODES.M)public boolean hasPermission(String permission) {    return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED;}

2、在需要使用相机权限的页面中,我们需要判断应用是否具有相机权限,如果没有就进行申请。

以下代码可以检查应用是否具备调用照相机的权限,并根据需要请求该权限:

// Here, thisActivity is the current activityif (ContextCompat.checkSelfPermission(thisActivity,Manifest.permission.CAMERA)        != PackageManager.PERMISSION_GRANTED) {    //①如果用户之前请求过此权限但用户拒绝了请求,并且用户没有勾选Don’t ask again选项,此方法会返回true;    //②如果用户之前请求过此权限但用户拒绝了请求,并且用户勾选了Don’t ask again选项,此方法会返回false;    if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,            Manifest.permission.CAMERA)) {        // 这里给用户一个提示对话框,让用户选择是否再次请求权限    } else {                // 逻辑走到这里说明用户已经拒绝了相机权限,并且都选了Don’t ask again选项,就算在这里直接请求相机权限,用户界面也不会弹出权限对话框,而是直接返回权限拒绝的结果。针对这种情况,我们可以考虑让用户进入设置页面,手动开启相机权限。        ActivityCompat.requestPermissions(thisActivity,                new String[]{Manifest.permission.CAMERA},                MY_PERMISSIONS_REQUEST_CAMERA);    }}

上述代码用流程图表示,如下所示:

3、请求权限的对话框:
当应用请求权限之后:
①如果用户之前没有做“拒绝并勾选’Don’t ask again’”的操作,那么系统会向用户展示一个对话框,如下所示:
Ps:第一次请求时是没有Don’t ask again选择框的。

该对话框是个阻塞操作,不论用户点击了拒绝还是确认按钮,系统都会有对应的结果返回。
②如果用户之前做了“拒绝并勾选’Don’t ask again’”的操作,那么该对话框就不会展示,而是直接返回权限拒绝的结果。

4、请求权限的结果处理:
权限请求的回调方法是Activity#onRequestPermissionResult方法,如下所示。

public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,        @NonNull int[] grantResults) {    /* callback - no nothing */}

这里我们需要重写该方法,获取权限请求的结果。
官方demo如下所示:

@Overridepublic void onRequestPermissionsResult(int requestCode,        String permissions[], int[] grantResults) {    switch (requestCode) {        case MY_PERMISSIONS_REQUEST_CAMERA: {            // 如果请求取消,grantResults会为空,所以这里需要做非空判断。            if (grantResults.length > 0                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {                        // 权限被授予了。恭喜!            } else {                // 权限被拒绝了。这里需要提示用户,并提供去设置页面开启的选项。            }            return;        }        //对其他权限进行处理,如果有的话。    }}

5、6.0以上手机(不包含魅族)完整版的解决方案:如下图所示:

6、说完正常的之后,就说说不正常的,在实际开发中发现,6.0以下的某些手机(华为、OPPO等)和魅族手机(包括6.0以上)的表现有些与众不同,在需要使用相机权限之前,系统会额外弹出一个“禁止、允许”对话框,用户点击了允许按钮的话还好,如果点击了禁止按钮,那么上面对6.0手机的处理会对魅族高版本手机失效,很蛋疼。经过Google,发现了一篇帖子是可以适配这种情况的,具体链接在文章末尾的参考3中。
文章中介绍了一种可行的处理方法,使用抓取Camera.open()异常的方法来解决,比较暴力。

/** * 判断摄像头是否可用 * 主要针对6.0 之前的版本,现在主要是依靠try...catch... 报错信息,感觉不太好, * 以后有更好的方法的话可适当替换 * * https://blog.csdn.net/jm_beizi/article/details/51728495 * * @return */public static boolean isCameraCanUse() {    boolean canUse = true;    Camera mCamera = null;    try {        mCamera = Camera.open();        // setParameters 是针对魅族MX5 做的。MX5 通过Camera.open() 拿到的Camera        // 对象不为null        Camera.Parameters mParameters = mCamera.getParameters();        mCamera.setParameters(mParameters);    } catch (Exception e) {        canUse = false;    }    if (mCamera != null) {        mCamera.release();    }    return canUse;}

7、最终方案:

参考:
1、https://developer.android.com/training/permissions/requesting?hl=zh-cn
2、https://github.com/android-cn/android-discuss/issues/174
3、https://blog.csdn.net/jm_beizi/article/details/51728495

更多相关文章

  1. android hook方法收集及选择优化
  2. Android(安卓)如何永久性开启adb 的root权限
  3. soap in android HTTP协议实现
  4. 每天学习一个Android中的常用框架——3.OkHttp
  5. Android中Google Authenticator验证系统工作原理分析
  6. android中的配置权限
  7. 人人都能看懂的 6 种限流实现方案!(纯干货)
  8. 搭建Flutter环境及创建第一个demo
  9. Android应用设计提示:Google Play和属性

随机推荐

  1. Applying Styles and Themes - 应用Style
  2. Eclipse 查看Android(安卓)程序在模拟器
  3. Android(安卓)8.1.0 SystemUI 修改之 -
  4. Android设置中清除应用数据源码分析
  5. android failed to start daemon 问题
  6. Android(安卓)MediaScannerConnection,And
  7. android Broadcast 广播 注册方式
  8. Android(安卓)mdpi ldpi hdpi区别(转)
  9. 举例说明如何在android中实现设置黑名单
  10. Android(安卓)+ Axis2