Android 6.0 运行时权限封装框架

1.概述


视频讲解都已经录了好几天,但是最近实在抽不开身一直在忙Unity3D,就连光棍节都在写,上次我们只是写了Android 6.0 运行时权限处理解析,但是并未对其做代码封装,这一次我们做一个彻底的处理。
  附视频讲解地址:http://pan.baidu.com/s/1bpqqkGn
  

这里写图片描述

2.框架封装


2.1. 简单例子

1public class MainActivity extends AppCompatActivity { 2 // 打电话权限申请的请求码 3 private static final int CALL_PHONE_REQUEST_CODE = 0x0011; 4 5 @Override 6 protected void onCreate(Bundle savedInstanceState) { 7 super.onCreate(savedInstanceState); 8 setContentView(R.layout.activity_main); 9 } 10 11 public void phoneClick(View view){ 12 if(ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) 13 != PackageManager.PERMISSION_GRANTED){ 14 Toast.makeText(this, "申请权限", Toast.LENGTH_SHORT).show(); 15 ActivityCompat.requestPermissions(this, 16 new String[]{"Manifest.permission.CALL_PHONE"}, CALL_PHONE_REQUEST_CODE); 17 }else { 18 callPhone(); 19 } 20 } 21 22 /** 23 * 拨打电话 24 **/ 25 private void callPhone() { 26 Intent intent = new Intent(Intent.ACTION_CALL); 27 Uri data = Uri.parse("tel:147****2514"); 28 intent.setData(data); 29 startActivity(intent); 30 } 31 32 @Override 33 public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { 34 super.onRequestPermissionsResult(requestCode, permissions, grantResults); 35 if(requestCode == CALL_PHONE_REQUEST_CODE){ 36 if (grantResults !=null&&grantResults[0] == PackageManager.PERMISSION_GRANTED) { 37 // Permission Granted 38 callPhone(); 39 } else { 40 // Permission Denied 41 Toast.makeText(this,"权限被拒绝了",Toast.LENGTH_SHORT).show(); 42 } 43 } 44 } 45}

这是从上一篇中复制过来的,并没有做过任何处理,如果每次申请权限的地方都需要这么做,那就比较麻烦了,那么我们肯定要对phoneClick()和onRequestPermissionsResult()里面的代码进行处理,那么要处理成什么样子?当然是所有的代码都可以优化成一行,别人都这么说的。

2.1. 确定方式
  到底采用什么方式去封装,这个github上面有很多,中国人,日本人,韩国人各国人民都有,这个不是开完笑的真的都有,这里我才用反射+注解的方式去实现。
  
  2.2. 参数传递和传递方式
  我们肯定要新建类,至于传什么参数? 第一个参数反射的类this,第二个参数请求码用于监听反馈处理,第三个参数传请求权限的数组
  利用什么方式传递过去那么?可以在工具类里面写一个静态的方法一把塞过去。但是在这里我们可以使用链式调用这种方式我们也经常使用,比如Okhttp,Gilde,甚至是Android的AlertDialog都是使用的这个方式,可以装装B

1public class PermissionHelper { 2 // 1. 传什么参数 3 // 1.1. Object Fragment or Activity 1.2. int 请求码 1.3.需要请求的权限 string[] 4 private Object mObject; 5 private int mRequestCode; 6 private String[] mRequestPermission; 7 8 private PermissionHelper(Object object){ 9 this.mObject = object; 10 } 11 12 // 2.已什么的方式传参数 13 // 2.1 直接传参数 14 public static void requestPermission(Activity activity,int requestCode,String[] permissions){ 15 PermissionHelper.with(activity).requestCode(requestCode). 16 requestPermission(permissions).request(); 17 } 18 19 public static void requestPermission(Fragment fragment,int requestCode,String[] permissions){ 20 PermissionHelper.with(fragment).requestCode(requestCode). 21 requestPermission(permissions).request(); 22 } 23 24 // 2.2 链式的方式传 25 // 传Activity 26 public static PermissionHelper with(Activity activity){ 27 return new PermissionHelper(activity); 28 } 29 30 // 传Fragment 31 public static PermissionHelper with(Fragment fragment){ 32 return new PermissionHelper(fragment); 33 } 34 35 // 添加一个请求码 36 public PermissionHelper requestCode(int requestCode){ 37 this.mRequestCode = requestCode; 38 return this; 39 } 40 41 // 添加请求的权限数组 42 public PermissionHelper requestPermission(String... permissions){ 43 this.mRequestPermission = permissions; 44 return this; 45 } 46 47 /** 48 * 3.1 真正判断和发起请求权限 49 */ 50 public void request() { 51 // 3.2 首先判断当前的版本是不是6.0 及以上 52 if(!PermissionUtils.isOverMarshmallow()){ 53 // 3.3 如果不是6.0以上 那么直接执行方法 反射获取执行方法 54 // 执行什么方法并不确定 那么我们只能采用注解的方式给方法打一个标记, 55 // 然后通过反射去执行。 注解 + 反射 执行Activity里面的callPhone 56 PermissionUtils.executeSucceedMethod(mObject,mRequestCode); 57 return; 58 } 59 } 60}

2.2. 处理6.0以下的版本
  对于6.0以下的版本,我们可以直接反射调用执行成功的方法,如果反射不太理解可以看一下这个视频讲解:http://pan.baidu.com/s/1bpqqkGn

1 /** 2 * 执行成功的方法 3 */ 4 public static void executeSucceedMethod(Object reflectObject, int requestCode) { 5 // 获取class中多有的方法 6 Method[] methods = reflectObject.getClass().getDeclaredMethods(); 7 8 // 遍历找我们打了标记的方法 9 for (Method method:methods){ 10 Log.e("TAG",method+""); 11 // 获取该方法上面有没有打这个成功的标记 12 PermissionSucceed succeedMethod = method.getAnnotation(PermissionSucceed.class); 13 if(succeedMethod != null){ 14 // 代表该方法打了标记 15 // 并且我们的请求码必须 requestCode 一样 16 int methodCode = succeedMethod.requestCode(); 17 if(methodCode == requestCode){ 18 // 这个就是我们要找的成功方法 19 // 反射执行该方法 20 Log.e("TAG","找到了该方法 :"+method); 21 executeMethod(reflectObject,method); 22 } 23 } 24 } 25 } 26 27 /** 28 * 反射执行该方法 29 */ 30 private static void executeMethod(Object reflectObject,Method method) { 31 // 反射执行方法 第一个是传该方法是属于哪个类 第二个参数是反射方法的参数 32 try { 33 method.setAccessible(true); // 允许执行私有方法 34 method.invoke(reflectObject,new Object[]{}); 35 } catch (IllegalAccessException e) { 36 e.printStackTrace(); 37 } catch (InvocationTargetException e) { 38 e.printStackTrace(); 39 } 40 }

2.3. 处理6.0以上的版本

1 /** 2 * 3.1 真正判断和发起请求权限 3 */ 4 public void request() { 5 // 3.2 首先判断当前的版本是不是6.0 及以上 6 if(!PermissionUtils.isOverMarshmallow()){ 7 // 3.3 如果不是6.0以上 那么直接执行方法 反射获取执行方法 8 // 执行什么方法并不确定 那么我们只能采用注解的方式给方法打一个标记, 9 // 然后通过反射去执行。 注解 + 反射 执行Activity里面的callPhone 10 PermissionUtils.executeSucceedMethod(mObject,mRequestCode); 11 return; 12 } 13 14 // 3.3 如果是6.0以上 那么首先需要判断权限是否授予 15 // 需要申请的权限中 获取没有授予过得权限 16 List<String> deniedPermissions = PermissionUtils.getDeniedPermissions(mObject,mRequestPermission); 17 18 // 3.3.1 如果授予了 那么我们直接执行方法 反射获取执行方法 19 if(deniedPermissions.size() == 0){ 20 // 全部都是授予过的 21 PermissionUtils.executeSucceedMethod(mObject,mRequestCode); 22 }else { 23 // 3.3.2 如果没有授予 那么我们就申请权限 申请权限 24 ActivityCompat.requestPermissions(PermissionUtils.getActivity(mObject), 25 deniedPermissions.toArray(new String[deniedPermissions.size()]), 26 mRequestCode); 27 } 28 }

2.4. 处理回调
  如果用户同意或是拒绝那么会回调onRequestPermissionsResult(),我们肯定也需要对它做处理,这个方法就很简单了:

1 /** 2 * 处理申请权限的回调 3 */ 4 public static void requestPermissionsResult(Object object,int requestCode, 5 String[] permissions) { 6 // 再次获取没有授予的权限 7 List<String> deniedPermissions = PermissionUtils.getDeniedPermissions(object,permissions); 8 9 if(deniedPermissions.size() == 0){ 10 // 权限用户都同意授予了 11 PermissionUtils.executeSucceedMethod(object,requestCode); 12 }else{ 13 // 你申请的权限中 有用户不同意的 14 PermissionUtils.executeFailMethod(object,requestCode); 15 } 16 }

2.5. 最后的事例

1public class MainActivity extends AppCompatActivity { 2 // 打电话权限申请的请求码 3 private static final int CALL_PHONE_REQUEST_CODE = 0x0011; 4 5 @Override 6 protected void onCreate(Bundle savedInstanceState) { 7 super.onCreate(savedInstanceState); 8 setContentView(R.layout.activity_main); 9 } 10 11 public void phoneClick(View view){ 12 PermissionHelper.with(this).requestCode(CALL_PHONE_REQUEST_CODE) 13 .requestPermission(Manifest.permission.CALL_PHONE).request(); 14 } 15 16 @PermissionSucceed(requestCode = CALL_PHONE_REQUEST_CODE) 17 private void callPhone() { 18 Intent intent = new Intent(Intent.ACTION_CALL); 19 Uri data = Uri.parse("tel:147****2514"); 20 intent.setData(data); 21 startActivity(intent); 22 } 23 24 @PermissionFail(requestCode = CALL_PHONE_REQUEST_CODE) 25 private void callPhoneFail(){ 26 Toast.makeText(this,"您拒绝了拨打电话", 27 Toast.LENGTH_SHORT).show(); 28 } 29 30 @Override 31 public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { 32 PermissionHelper.requestPermissionsResult(this, 33 CALL_PHONE_REQUEST_CODE,permissions); 34 } 35}

到最后再处理权限请求的时候会轻松很多,一行代码解决问题,反正别人都这么说,我们甚至可以把onRequestPermissionsResult()的处理写到BaseActivity中,因为权限封装我没有把它写入到基础架构部分,这里我就不处理了。

这里写图片描述

  
  项目的代码不能够发给大家,里面涉及到后台接口以及数据加密,如果大家感兴趣可以看一下我录的视频:http://pan.baidu.com/s/1bpqqkGn
  
这里我只附上事例代码地址:
http://download.csdn.net/detail/z240336124/9683704

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

Android无限广告轮播 - 自定义BannerView

1.概述这其实是我第一篇想写的博客,可能是因为我遇到了太多的坑,那个时候刚入行下了很多Demo发现怎么也改不动,可能是能力有限,这次就做一个具体的实现和彻底的封装。  上次讲了,有了源码分析我们对ViewPager就有了一个大概的了解,那么再来封装成自定义View,就会简单许多,附视频讲解地址:    这里写图片描述2.效果封装2.1

Android无限广告轮播 - ViewPager源码分析

1.概述这其实是我第一篇想写的博客,可能是因为我遇到了太多的坑,那个时候刚入行下了很多Demo发现怎么也改不动,可能是能力有限,这次就做一个具体的实现和彻底的封装。  上次讲了,内涵段子项目中的热吧其实还有一个广告轮播的功能没写,这里就以这个项目为例吧,附视频讲解地址:    这里写图片描述2.ViewPager源码分析传递数据的方式决