Android6.0运行时权限申请

作者: 空_欢喜 | 来源:发表于2018-06-24 19:34 被阅读217次

    1.简介

    在Android6.0之前版本,权限请求较为简单,仅在用户安装app时将自己需要使用的所有权限列出来告知用户,若用户授权,则app安装后可随时使用该权限。自6.0开始,一些涉及用户隐私的敏感权限需在使用时动态申请,且用户可选择授权或拒绝。当然,权限的改进对用户而言是好事,毕竟更能保护用户隐私。但对于开发者而言,也多了一项动态权限申请的工作

    2.权限分类

    对开发者而言,权限则主要分为以下两类:
    1)普通权限(normal permissions): 只需在manifest中注册
    2)危险权限(dangerous permissions):除需在manifest中注册外,还需动态申请
    危险权限如下:

    危险权限.png

    3.运行时权限申请(使用系统提供的API)

    1)权限检查

    int result = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
    if (result == PackageManager.PERMISSION_GRANTED) {
        //请求的权限权限被授予
    }else {
        //请求的权限被拒绝
    }
    

    2)请求权限

    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 
    requestCode);
    

    注意:Fragment中请求需使用自己的requestPermissions方法

    3)处理请求结果

    请求权限后系统会回调申请权限的Activity的onRequestPermissionsResult(),若使用的是Fragment的requestPermissions方法,则回调对应Fragment的onRequestPermissionsResult()

        @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            if (requestCode != this.requestCode) {
                return;
            }
            for (int i = 0; i < grantResults.length; i++) {
                String permission = permissions[i];
                if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                    Toast.makeText(this, permission + "已被授权", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(this, permission + "已被拒绝", Toast.LENGTH_SHORT).show();
                    if (shouldShowRequestPermissionRationale(permission)) {
                        //请求被用户拒绝但用户未勾选不再询问框,可继续请求权限
                    } else {
                        //请求被用户拒绝且用户勾选了不再询问框,需要用户前往设置中授权
                    }
                }
            }
        }
    

    4)总结

    用系统提供的api进行申请步骤较为繁琐,且请求和处理代码不在相同位置,代码量多了的话可读性变差。那有没有什么好的方法可以简化流程并能提高可读性呢?答案是肯定的,著名基佬交流网站github上就有丰富的权限请求库供各位客官享用

    4.使用EasyPermissions进行权限申请

    1)EasyPermissions简介

    github上有很多动态权限申请库,比如rxpermissions,该库最大的亮点是和rxjava配合使用,链式操作简单方便。但rxpermissions要求我们必须依赖rxjava,而有时我们可能并不想依赖rxjava,并且rxpermissions连续执行相同权限的请求可能会回调多次。因此,可使用EasyPermissions进行运行时权限申请,该库特点如下:

    • 链式操作(这点和rxpermissions一样,不同的是无需依赖rxjava)
    • 请求前会自动检查是否已被授予 (这样在请求前就不必再进行权限检查了)
    • 请求间互不影响,即使每次请求的是相同权限
    • 若请求的权限未在manifest中注册,将抛出明确的异常 (请求未在manifest注册的权限将导致不弹出dialog而直接返回false,有时我们可能对此十分懵逼,因为这既不报错也不弹出dialog代码也OK就是请求失败,可能要很久才反应过来忘了在manifest中注册)

    地址:https://github.com/Ficat/EasyPermissions

    2)依赖

    A.在根build.gradle中添加

    allprojects {
        repositories {
            maven { url 'https://jitpack.io' }
        }
    }
    

    B.添加依赖

    dependencies {
        implementation 'com.github.Ficat:EasyPermissions:v1.0.1'
    }
    

    3)使用

    A.创建easypermissions对象

    EasyPermissions easyPermissions = new EasyPermissions(activity);
    

    B.请求权限

    //request方式,请求的所有权限被用户授权后返回true,否则返回false  
    easyPermissions.request(Manifest.permission.CAMERA,Manifest.permission.CALL_PHONE)
                   .subscribe(new RequestSubscriber<Boolean>() {
                       @Override
                       public void onPermissionsRequestResult(Boolean granted) {
                           if (granted) {
                               //摄像头、拨打电话都被用户授权
                           } else {
                               //摄像头、拨打电话任意一项被拒绝或两者都被拒绝
                           }
                       }
                   });
    
    //requestEach方式
    easyPermissions.requestEach(Manifest.permission.CAMERA,Manifest.permission.CALL_PHONE)
                   .subscribe(new RequestSubscriber<Permission>() {
                       @Override
                       public void onPermissionsRequestResult(Permission permission) {
                           //权限名
                           String name = permission.name;
                           if (permission.granted) {
                               //name权限被授予
                           } else {
                               if (permission.shouldShowRequestPermissionRationale) {
                                   //name权限被拒绝但用户未勾选不再询问框
                               } else {
                                   //name权限被拒绝且用户勾选了不再询问框
                                   //此时就不能再次请求name权限了,而需user前往设置界面授权
                               }
                           }
                       }
                   });
    

    相关文章

      网友评论

      • 哈士奇9:很想知道如何将动态权限制作成库的方法,小编可以支招不?

      本文标题:Android6.0运行时权限申请

      本文链接:https://www.haomeiwen.com/subject/lgfsyftx.html