Android6.0运行时权限适配封装

一 前言

对于Android6.0我想大家听到的最多的就是运行时权限了,运行时权限是一种全新的权限管理机制,在6.0以下系统app安装的时候会根据权限列表里的声明让用户同意权限之后才能安装,这就造成用户还没开始使用app就要去同意一堆权限。而在6.0之后,某一些权限就需要在用户使用过程中用到该功能的时候才去选择同意与否。如果你的项目targetSdk高于23的话,也就是高于6.0,就必须进行权限的适配,否则在使用一些需要权限申请的功能时就会崩溃,比如照相,录音等。

二 需要适配的权限

运行时权限.jpg

权限分为几个组,每个组里面有具体的权限,同一组里面的权限只要某一个权限通过申请了,其它权限也默认通过申请。具体的权限大家看名字应该就知道了 ,我就不一一解释了。

三 适配方法

关于适配方案网上有许许多多的文章,有使用框架的,有自己写的,我看了很多方法都觉得过于繁琐,所以想自己通过原生方法简单的封装一下,所以接下来我直接讲解我的封装方案。

    /**
     * 权限请求结果回调
     */
    interface PermissionCallBack{
        /**
         * 允许权限
         */
        void permGrant(String[] permsGranted);

        /**
         * 拒绝权限
         */
        void permDeny(String[] permsDenied);
    }
    public void baseRequestPermission(String[] perms,PermissionCallBack callBack,String settingMsg){
        mPermCallBack=callBack;
        mPermSettingMsg=settingMsg;
        if (!checkPerm(perms)){
            requestPermissions(perms,REQUESTCODE);
        }else {
            if (callBack!=null){
                callBack.permGrant(perms);
            }
        }

    }

    /**
     * 权限检查
     */
    public boolean checkPerm(String[] perms){
        for (String perm:perms){
            if (ContextCompat.checkSelfPermission(this,perm)!= PackageManager.PERMISSION_GRANTED){
                return false;
            }
        }
        return true;

    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        /**
         * 允许的权限
         */
        List<String> permsGranted=new ArrayList<>();
        /**
         * 拒绝的权限
         */
        List<String> permsDenied=new ArrayList<>();
        if (requestCode==REQUESTCODE){
            /**
             * 添加允许权限和拒绝权限到相应的集合中
             */
            for (int i=0;i<permissions.length;i++){
                if (grantResults[i]==PackageManager.PERMISSION_GRANTED){
                    permsGranted.add(permissions[i]);
                }else {
                    permsDenied.add(permissions[i]);
                }

            }
            /**
             *进行权限回调
             */
            if (permsGranted.size()!=0&&permsDenied.size()==0){
                if (mPermCallBack!=null){
                    mPermCallBack.permGrant((String[]) permsGranted.toArray(new String[permsGranted.size()]));
                }
            }else {
                if (mPermCallBack!=null){
                    mPermCallBack.permDeny((String[]) permsDenied.toArray(new String[permsDenied.size()]));
                }
                /**
                 * 点击不再提醒拒绝权限
                 * 提示是否进入设置界面设置权限
                 */
                for (String permDenied:permsDenied){
                    if (!shouldShowRequestPermissionRationale(permDenied)){
                        gotoSetting(mPermSettingMsg);
                        return;
                    }
                }

            }
        }
    }

    /**
     * 进入应用设置界面设置权限
     * @param msg
     */
    private void gotoSetting(String msg) {
        new AlertDialog.Builder(this)
                .setMessage(msg)
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Intent localIntent = new Intent();
                        localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        localIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
                        localIntent.setData(Uri.fromParts("package", getPackageName(), null));
                        startActivity(localIntent);
                    }

                })
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                })
                .show();
    }

我的做法是把权限申请封装在activity的基类中,我想大多数项目都会建这个基类。首先定义一个回调接口PermissionCallBack用来回调权限申请接口,主要有两个方法一个允许一个拒绝。baseRequestPermission方法是用来检查权限和申请权限,其中checkPerm是用来检查权限是否通过申请的,因为可以同时申请多个权限,所以需要遍历检查。最后需要重写FragmentActivity中的onRequestPermissionsResult方法进行权限结果处理,注意这其中的逻辑才是重点。
因为可能会申请多个权限,所以我定义了两个集合,一个申请通过的权限集合,另一个是拒绝的权限集合。而通过权限的判断条件是申请通过的权限集合不为空,且拒绝的权限集合为空,这样就证明了所有权限已经通过,可以调用某些功能了。这里面还有一个很重要的方法就是shouldShowRequestPermissionRationale(permDenied),这个方法是用来判断用户是否点击了不再提醒按钮后拒绝的权限,一旦用户点击了不再提醒则会返回false,这时候可以提示用户进入设置界面进行权限设置。这就是在基类的封装,然后在你需要申请权限的地方直接调用baseRequestPermission就行,代码如下:

 private void takePic() {
        String[] perms={Manifest.permission.CAMERA,Manifest.permission.READ_SMS};
        baseRequestPermission(perms, new PermissionCallBack() {

            @Override
            public void permGrant(String[] permsGranted) {
                Toast.makeText(MainActivity.this, "已授权", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void permDeny(String[] permsDenied) {
                Toast.makeText(MainActivity.this, "未授权", Toast.LENGTH_SHORT).show();
            }
        },"调用拍照功能需要获取权限,是否跳转权限设置?");

    }

以后申请权限只要像上面这样调用就行,看起来就简洁很多了。

四 参考

https://github.com/googlesamples/easypermissions
这是google官方出的一个框架,用起来也挺简单的,大家可以看看。
https://github.com/tsy12321/easypermissions
这个是对上面那个框架做了一些封装,我觉得官方封装好了自己再封装一遍有点过度封装的感觉,所以参考了他的封装方式自己简化了一下。

五 END

Git地址:https://github.com/Godlwl/PermissionRequest
第一次写文章,有点不知所言,希望大家多多支持和指正。

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

推荐阅读更多精彩内容