美文网首页
Android 6.0 运行时权限封装框架

Android 6.0 运行时权限封装框架

作者: 如愿以偿丶 | 来源:发表于2019-09-29 21:23 被阅读0次

    1.概述

      上篇文章文章介绍了Android 6.0 运行时权限处理解析,只是写了运行时申请权限处理,但是并未对其做代码封装,这一次我们做一个彻底的封装处理,供以后项目中使用。

    2.框架封装

      2.1.简单事例:
        public class TextActivity extends AppCompatActivity {
              // 打电话权限申请的请求码
              private static final int CALL_PHONE_REQUEST_CODE = 0x0011;
    
              @Override
              protected void onCreate(Bundle savedInstanceState) {
                   super.onCreate(savedInstanceState);
                  setContentView(R.layout.activity_text);
              }
             
             /**
              * 检察权限
              */    
              public void phoneClick(View view) {
                   if (ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE)
                    != PackageManager.PERMISSION_GRANTED) {
                   Toast.makeText(this, "申请权限", Toast.LENGTH_SHORT).show();
                   ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.CALL_PHONE}, CALL_PHONE_REQUEST_CODE);
                  } else {
                    callPhone();
                  }
              }
    
              /**
               * 拨打电话
               **/
              private void callPhone() {
                  Intent intent = new Intent(Intent.ACTION_CALL);
                  Uri data = Uri.parse("tel:130****7927");
                  intent.setData(data);
                  startActivity(intent);
              }
    
              @Override
              public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
                  super.onRequestPermissionsResult(requestCode, permissions, grantResults);
                  if(requestCode == CALL_PHONE_REQUEST_CODE){
                      if (grantResults !=null&&grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                          // 授予权限
                          callPhone();
                      } else {
                          // 拒绝权限
                          Toast.makeText(this,"权限被您拒绝了",Toast.LENGTH_SHORT).show();
                      }
                  }
              }
          }
    

      这是从上一篇中复制过来的,没有任何地方改变,如果我们每次申请权限的地方都需要这么写,那就比较麻烦了,那么我们肯定要对 callPhone()onRequestPermissionsResult() 里面的代码进行处理,那么要怎么处理呢?

      2.2.什么方式进行封装

        到底采用什么方式去封装,这个github上面也有很多,这里我才用反射+注解的方式去实现。这里就不在详细介绍了,这里我采用 反射 + 注解 的方式去实现。
        反射 + 注解刚开始不是太了解,看了 辉哥 Darren,的视频文章懂了很多,非常感谢。大家也可以去看看,每篇文章下边都会附带视频,讲解很详细。

      2.3.都需要什么

        1.反射我们需要当前的类,第一个参数反射的类this
        2.我们的请求码,第二个参数请求码用于监听反馈处理
        3.要申请的权限数组,第三个参数传请求权限的数组

      2.4 利用什么方式传递参数

        可以在工具类里面写一个静态的方法一把塞过去。但是在这里我们可以使用链式调用这种方式我们也经常使用,例如:Retrofit,Okhttp,Gilde,甚至是Android自带的的AlertDialog都是使用的这个方式,也采用这种方式,装装B


    3 开始封装

      3.1 创建注解文件
        //成功注解
        @Target(ElementType.METHOD)
        @Retention(RetentionPolicy.RUNTIME)
        public @interface PermissionSuccess {
            public int requestCode();   //请求码
        }
    
        //失败的注解
        @Target(ElementType.METHOD)
        @Retention(RetentionPolicy.RUNTIME)
        public @interface PermissionFail {
             public int requestCode();   //请求码
        }
    

    注解作用:在类,方法,属性上做一个标记,一般配合类反射使用
      Target:表示作用在谁身上,方法METHOD,属性FIELD,类TYPE等等
      @Target(ElementType.METHOD)
      Retention:代表什么时候检测,编译时检测 运行时检测
      @Retention(RetentionPolicy.RUNTIME)

    3.2 创建PermissionHelper辅助类
    public class PermissionHelper {
    
        //1.需要传什么参数
        //1.1 Object 可以是Fragment 或 Activity    
        private Object mObject;
        //1.2 int 请求码
        private int mRequestCode;
        //1.3 String[] 需要申请权限数组
        private String[] mRequestPermission;
    
        public PermissionHelper(Object object) {
            this.mObject = object;
        }
    
        //1.可以直接方法传递
        public void requestPermission(Activity activity, int requestCode, String[] permissions) {
            PermissionHelper.with(activity).requestCode(requestCode).requestPermission(permissions).request();
        }
    
    
        public void requestPermission(Fragment fragment, int requestCode, String[] permissions) {
            PermissionHelper.with(fragment).requestCode(requestCode).requestPermission(permissions).request();
        }
    
    
        //2.可以使用链式调用,链式调用返回的都是this,才可以继续调用
        //传Activity
        public static PermissionHelper with(Activity activity) {
            return new PermissionHelper(activity);
        }
    
        //传Fragment
        public static PermissionHelper with(Fragment fragment) {
            return new PermissionHelper(fragment);
        }
    
        //传请求码
        public PermissionHelper requestCode(int requestCode) {
            this.mRequestCode = requestCode;
            return this;
        }
    
        //添加请求权限数组 String[] 想同于 String...
        public PermissionHelper requestPermission(String... permissions) {
            this.mRequestPermission = permissions;
            return this;
        }
    
        //3.执行链式调用
        public void request() {
            //3.1 首先判断是否是6.0以上版本
            if (!PermissionUtils.isOverMarshmallow()) {
                //如果不是就不需要申请权限,直接执行方法,通过反射获取方法
                //问题:执行哪个方法不确定,需要通过注解方式来声明,通过反射 + 注解执行
                PermissionUtils.executeSuccessMethod(mObject, mRequestCode);
                return;
            }
            //3.2 如果是6.0以上首先判断是否已经给予权限
            //判断需要申请的权限中,用户没有授予过的权限,添加到集合中
            List<String> deniedPermissions = PermissionUtils.getDeniedPermissions(mObject, mRequestPermission);
            //3.2.1 如果授权了,直接执行方法  反射获取执行方法
            //如果没有授予的权限为0,表示都已经授予了,就直接执行
            if (deniedPermissions.size() == 0) {
                PermissionUtils.executeSuccessMethod(mObject, mRequestCode);
            }else {
                //3.2.2 如果没有授权,就申请授权
                ActivityCompat.requestPermissions(PermissionUtils.getActivity(mObject),
                        deniedPermissions.toArray(new String[deniedPermissions.size()]),
                        mRequestCode);
            }
        }
    
        /**
         * 获取权限的回掉
         * @param object
         * @param requestCode
         * @param permissions
         */
        public static void requestPermissionsResult(Object object, int requestCode, String[] permissions) {
            //再次获取数组中没有授予的权限
            List<String> deniedPermissions = PermissionUtils.getDeniedPermissions(object,permissions);
            if (deniedPermissions.size() == 0){
                //都已经授予了,直接执行方法
                PermissionUtils.executeSuccessMethod(object, requestCode);
            }else {
                //申请的权限中,有用户不同意的
                PermissionUtils.executeFailMethod(object,requestCode);
            }
        }
    }
    
    3.3 创建PermissionHelper辅助类
    public class PermissionUtils {
        private List<String> deniedPermissions;
    
        //不允许使用者来new对象,也可以写
        public PermissionUtils() {
            throw new UnsupportedOperationException("Cannot be instantiated");
        }
    
        /**
         * 判断是否是6.0以上
         * Marshmallow 棉花糖
         */
        public static boolean isOverMarshmallow(){
            return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
        }
    
        /**
         * 执行我们成功方法
         * @param reflectObject     类对象
         * @param requestCode       请求码
         */
        public static void executeSuccessMethod(Object reflectObject, int requestCode) {
            //1.获取类中的所以有方法
            Method[] methods = reflectObject.getClass().getDeclaredMethods();
            //2.遍历找到我们方法上打了标记的方法
            for (Method method : methods) {
                //3.获取方法上是否打了标记
                PermissionSuccess permissionSuccess =  method.getAnnotation(PermissionSuccess.class);
                if (permissionSuccess!=null){
                    //4.不为空证明该方法打了标记,并判断方法上请求码和申请的是否一样
                    int methodCode = permissionSuccess.requestCode();
                    if (methodCode == requestCode){
                        //相同就是我们要找的方法,反射执行方法
                        executeMethod(reflectObject,method);
                    }
                }
            }
        }
    
        /**
         * 用户拒绝的权限,执行失败的方法
         * @param reflectObject
         * @param requestCode
         */
        public static void executeFailMethod(Object reflectObject, int requestCode) {
            //1.获取所有的方法
            Method[] methods = reflectObject.getClass().getDeclaredMethods();
            //2.遍历所有的方法,找到失败注解
            for (Method method : methods) {
                PermissionFail permissionFail =  method.getAnnotation(PermissionFail.class);
                int methodCode = permissionFail.requestCode();
                if (methodCode == requestCode){
                    //相同是我们要找的方法,反射执行方法
                    executeMethod(reflectObject,method);
                }
            }
        }
    
    
        /**
         * 执行方法
         * @param reflectObject
         * @param method
         */
        public static void executeMethod(Object reflectObject, Method method) {
            /**
             *  参数1:该方法属于哪个类
             *  参数2:该方法的参数,这里没有
             */
            try {
                method.setAccessible(true); //强制执行私有方法
                method.invoke(reflectObject,new Object[]{});
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 获取没有授予过的权限
         * @param object  Fragment 或者 Activity
         * @param requestPermissions
         * @return
         */
        public static List<String> getDeniedPermissions(Object object, String[] requestPermissions) {
            //创建数组,将用户未授予的权限添加到一个集合中
            deniedPermissions = new ArrayList<>();
            for (String requestPermission : requestPermissions) {
                //将没有授予过的权限添加到集合
                if (ContextCompat.checkSelfPermission(getActivity(object),requestPermission) == PackageManager.PERMISSION_DENIED){
                    deniedPermissions.add(requestPermission);
                }
            }
            return deniedPermissions;
        }
    
        /**
         * 获取Context上下文
         * @param object
         * @return
         */
        public static Activity getActivity(Object object) {
            if (object instanceof Activity){
                return (Activity) object;
            }
            if (object instanceof Fragment){
                return ((Fragment) object).getActivity();
            }
            return null;
        }
    }
    

    4.最后使用

    
    public class TextActivity extends AppCompatActivity {
    
        // 打电话权限申请的请求码
        private static final int CALL_PHONE_REQUEST_CODE = 0x0011;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_text);
        }
    
        /**
         * 调用打电话,只需一行代码
         * @param view
         */
        public void phoneClick(View view) {
            PermissionHelper.with(this).requestCode(CALL_PHONE_REQUEST_CODE).requestPermission(Manifest.permission.CALL_PHONE).request();
        }
    
        /**
         * 用户允许成功方法
         **/
        @PermissionSuccess(requestCode = CALL_PHONE_REQUEST_CODE)
        private void callPhone() {
            Intent intent = new Intent(Intent.ACTION_CALL);
            Uri data = Uri.parse("tel:130****7927");
            intent.setData(data);
            startActivity(intent);
        }
    
        /**
         * 用户拒绝失败方法
         */
        @PermissionFail(requestCode = CALL_PHONE_REQUEST_CODE)
        private void callPhoneFail() {
            Toast.makeText(this,"您拒绝了拨打电话",Toast.LENGTH_SHORT).show();
        }
    
        @Override
        public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            //处理用户的回掉
            PermissionHelper.requestPermissionsResult(this,requestCode,permissions);
        }
    }
    

    这样封装后,是不是清晰很多,一行代码解决问题,我们还可以把onRequestPermissionsResult()的处理写到我们的基类BaseActivity中

    相关文章

      网友评论

          本文标题:Android 6.0 运行时权限封装框架

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