Android 6.0 运行时权限封装框架

1.概述


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

这里写图片描述

2.框架封装


2.1. 简单例子

public class MainActivity extends AppCompatActivity {
    // 打电话权限申请的请求码
    private static final int CALL_PHONE_REQUEST_CODE = 0x0011;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    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:147****2514");
        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) {
                // Permission Granted
                callPhone();
            } else {
                // Permission Denied
                Toast.makeText(this,"权限被拒绝了",Toast.LENGTH_SHORT).show();
            }
        }
    }
}

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

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

public class PermissionHelper {
    // 1. 传什么参数
    // 1.1. Object Fragment or Activity  1.2. int 请求码   1.3.需要请求的权限  string[]
    private Object mObject;
    private int mRequestCode;
    private String[] mRequestPermission;

    private PermissionHelper(Object object){
        this.mObject = object;
    }

    // 2.已什么的方式传参数
    // 2.1 直接传参数
    public static void  requestPermission(Activity activity,int requestCode,String[] permissions){
            PermissionHelper.with(activity).requestCode(requestCode).
                    requestPermission(permissions).request();
    }

    public static void  requestPermission(Fragment fragment,int requestCode,String[] permissions){
        PermissionHelper.with(fragment).requestCode(requestCode).
                requestPermission(permissions).request();
    }

    // 2.2 链式的方式传
    // 传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;
    }

    // 添加请求的权限数组
    public PermissionHelper requestPermission(String... permissions){
        this.mRequestPermission = permissions;
        return this;
    }

    /**
     * 3.1 真正判断和发起请求权限
     */
    public void request() {
        // 3.2 首先判断当前的版本是不是6.0 及以上
        if(!PermissionUtils.isOverMarshmallow()){
            // 3.3 如果不是6.0以上  那么直接执行方法   反射获取执行方法
            // 执行什么方法并不确定 那么我们只能采用注解的方式给方法打一个标记,
            // 然后通过反射去执行。  注解 + 反射  执行Activity里面的callPhone
            PermissionUtils.executeSucceedMethod(mObject,mRequestCode);
            return;
        }
    }
}

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

    /**
     * 执行成功的方法
     */
    public static void executeSucceedMethod(Object reflectObject, int requestCode) {
        // 获取class中多有的方法
        Method[] methods = reflectObject.getClass().getDeclaredMethods();

        // 遍历找我们打了标记的方法
        for (Method method:methods){
            Log.e("TAG",method+"");
            // 获取该方法上面有没有打这个成功的标记
            PermissionSucceed succeedMethod =  method.getAnnotation(PermissionSucceed.class);
            if(succeedMethod != null){
                // 代表该方法打了标记
                // 并且我们的请求码必须 requestCode 一样
                int methodCode = succeedMethod.requestCode();
                if(methodCode == requestCode){
                    // 这个就是我们要找的成功方法
                    // 反射执行该方法
                    Log.e("TAG","找到了该方法 :"+method);
                    executeMethod(reflectObject,method);
                }
            }
        }
    }

    /**
     * 反射执行该方法
     */
    private static void executeMethod(Object reflectObject,Method method) {
        // 反射执行方法  第一个是传该方法是属于哪个类   第二个参数是反射方法的参数
        try {
            method.setAccessible(true); // 允许执行私有方法
            method.invoke(reflectObject,new Object[]{});
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

2.3. 处理6.0以上的版本

    /**
     * 3.1 真正判断和发起请求权限
     */
    public void request() {
        // 3.2 首先判断当前的版本是不是6.0 及以上
        if(!PermissionUtils.isOverMarshmallow()){
            // 3.3 如果不是6.0以上  那么直接执行方法   反射获取执行方法
            // 执行什么方法并不确定 那么我们只能采用注解的方式给方法打一个标记,
            // 然后通过反射去执行。  注解 + 反射  执行Activity里面的callPhone
            PermissionUtils.executeSucceedMethod(mObject,mRequestCode);
            return;
        }

        // 3.3 如果是6.0以上  那么首先需要判断权限是否授予
        // 需要申请的权限中 获取没有授予过得权限
        List<String> deniedPermissions = PermissionUtils.getDeniedPermissions(mObject,mRequestPermission);

        // 3.3.1 如果授予了 那么我们直接执行方法   反射获取执行方法
        if(deniedPermissions.size() == 0){
            // 全部都是授予过的
            PermissionUtils.executeSucceedMethod(mObject,mRequestCode);
        }else {
            // 3.3.2 如果没有授予 那么我们就申请权限  申请权限
            ActivityCompat.requestPermissions(PermissionUtils.getActivity(mObject),
                    deniedPermissions.toArray(new String[deniedPermissions.size()]),
                    mRequestCode);
        }
    }

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

    /**
     * 处理申请权限的回调
     */
    public static void requestPermissionsResult(Object object,int requestCode,
                                                String[] permissions) {
        // 再次获取没有授予的权限
        List<String> deniedPermissions = PermissionUtils.getDeniedPermissions(object,permissions);

        if(deniedPermissions.size() == 0){
            // 权限用户都同意授予了
            PermissionUtils.executeSucceedMethod(object,requestCode);
        }else{
            // 你申请的权限中 有用户不同意的
            PermissionUtils.executeFailMethod(object,requestCode);
        }
    }

2.5. 最后的事例

public class MainActivity extends AppCompatActivity {
    // 打电话权限申请的请求码
    private static final int CALL_PHONE_REQUEST_CODE = 0x0011;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

   public void phoneClick(View view){
        PermissionHelper.with(this).requestCode(CALL_PHONE_REQUEST_CODE)
                .requestPermission(Manifest.permission.CALL_PHONE).request();
    }

    @PermissionSucceed(requestCode =  CALL_PHONE_REQUEST_CODE)
    private void callPhone() {
        Intent intent = new Intent(Intent.ACTION_CALL);
        Uri data = Uri.parse("tel:147****2514");
        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) {
    PermissionHelper.requestPermissionsResult(this,
        CALL_PHONE_REQUEST_CODE,permissions);
    }
}

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

这里写图片描述

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,470评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,393评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,577评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,176评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,189评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,155评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,041评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,903评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,319评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,539评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,703评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,417评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,013评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,664评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,818评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,711评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,601评论 2 353

推荐阅读更多精彩内容