关于android6.0的权限申请

谷歌在android6.0的权限管理方面做了不少的改动,android6.0以前的话需要什么权限只需要在AndroidManifest文件中进行申请就可以了,android6.0以后的话将权限分为两类;一类是Normal Permissions,这类权限一般不涉及用户隐私,是不需要用户进行授权的,比如手机震动、访问网络等;另一类是Dangerous Permission,一般是涉及到用户隐私的,需要用户进行授权,比如读取sdcard、访问通讯录等;对于Normal Permissions的话还是跟之前一样的做法,Dangerous Permission的话不仅需要在AndroidManifest中注册,还需要动态申请;下面这些的就是Dangerous Permission:

group:permission-group.CONTACTS 
permission:permission.WRITE_CONTACTS 
permission:android.permission.GET_ACCOUNTS 
permission:android.permission.READ_CONTACTS

group:android.permission-group.PHONE 
permission:android.permission.READ_CALL_LOG 
permission:android.permission.READ_PHONE_STATE 
permission:android.permission.CALL_PHONE 
permission:android.permission.WRITE_CALL_LOG 
permission:android.permission.USE_SIP 
permission:android.permission.PROCESS_OUTGOING_CALLS 
permission:com.android.voicemail.permission.ADD_VOICEMAIL

group:android.permission-group.CALENDAR 
permission:android.permission.READ_CALENDAR 
permission:android.permission.WRITE_CALENDAR

group:android.permission-group.CAMERA 
permission:android.permission.CAMERA

group:android.permission-group.SENSORS 
permission:android.permission.BODY_SENSORS

group:android.permission-group.LOCATION 
permission:android.permission.ACCESS_FINE_LOCATION 
permission:android.permission.ACCESS_COARSE_LOCATION

group:android.permission-group.STORAGE 
permission:android.permission.READ_EXTERNAL_STORAGE 
permission:android.permission.WRITE_EXTERNAL_STORAGE

group:android.permission-group.MICROPHONE 
permission:android.permission.RECORD_AUDIO

group:android.permission-group.SMS 
permission:android.permission.READ_SMS 
permission:android.permission.RECEIVE_WAP_PUSH 
permission:android.permission.RECEIVE_MMS 
permission:android.permission.RECEIVE_SMS 
permission:android.permission.SEND_SMS 
permission:android.permission.READ_CELL_BROADCASTS 

对于这些权限在使用的时候就需要注意,要记得动态去申请添加权限;这里也讲下本人的一个大致思路:

1:判断当前的版本是否在android6.0及以上,如果不是就直接AndroidManifest中申请,
2:android6.0及以上的话,判断用户是否赋予该权限,如果赋予该权限,就运行进行相应的操作,
3:6.0及以上同时没有赋予该权限,就动态的申请并提示用户赋予该权限,,如果赋予该权限,就运行进行相应的操作,如果用户拒绝,就提示用户拒绝该权限的赋予,同时不允许用户进行相应操作,如果用户继续操作,还是提示用户要赋予该权限;

其实在http://blog.csdn.net/wangwo1991/article/details/54666737;
这篇博客中已经讲过6.0权限的处理,不过这是另外一种思路处理,这里要讲的是通过反射和注解的方式处理6.0的权限;反射和注解的话在IOC注解里面已经讲到过了;就直接写成功和失败的注解了;

成功的注解:

@Target(ElementType.METHOD)//ElementType.METHOD方法上面  Target代表放在什么位置
@Retention(RetentionPolicy.RUNTIME)//是编译时检测还是运行时检测  Retention代表什么时候去检测
public @interface PermissionSuccess {
    public int requestCode();//请求码
}

失败的注解:

@Target(ElementType.METHOD)//ElementType.METHOD方法上面  Target代表放在什么位置
@Retention(RetentionPolicy.RUNTIME)//是编译时检测还是运行时检测  Retention代表什么时候去检测
public @interface PermissionFail {
    public int requestCode();//请求码
}

首先判断当前系统的版本;

/**
     * 判断其是不是6.0以上的版本
     * @return
     */
    public static boolean isOverMarshmallow(){
        return Build.VERSION.SDK_INT>=Build.VERSION_CODES.M;
    }

根据系统的版本去执行权限的申请或者相应的操作;

      //首先判断当前的版本是不是6.0和6.0以上
        if (!PermissionUtils.isOverMarshmallow()) {
            //如果不是6.0以上,  反射获取执行方法
            PermissionUtils.executeSuccess(mObject,mRequestCode);
            return;
        }
        //如果是6.0以上那么首先需要判断是否授予权限
        List<String> deniedPermission=PermissionUtils.getDeniedPermission(mObject,mPermisson);
        //如果授予了 反射获取执行方法
        if(deniedPermission.size()==0){
            //全部都是授予过权限的
            PermissionUtils.executeSuccess(mObject,mRequestCode);
        }else{
            //如果没有授予 那么我们就申请
            ActivityCompat.requestPermissions(PermissionUtils.getActivity(mObject),
                    deniedPermission.toArray(new String[deniedPermission.size()]),
                    mRequestCode);
        }

如果是6.0及以上并没有授予权限,就需要去动态申请,谷歌提供了

ActivityCompat.requestPermissions(PermissionUtils.getActivity(mObject),
                    deniedPermission.toArray(new String[deniedPermission.size()]),
                    mRequestCode);

方法可以去申请权限,当然了肯定还要去处理申请后的回调;

  public static void requestPermissionsResult(Object mObject,int requestCode, String[] permissions, int[] grantResults) {
        //再次获取是否授予的权限
        List<String> deniedPermission=PermissionUtils.getDeniedPermission(mObject,permissions);
        if(deniedPermission.size()==0){
            //这些权限全部同一
            PermissionUtils.executeSuccess(mObject,requestCode);
        }else{
            //申请中权限中有用户不同意的
            PermissionUtils.executeFailMethod(mObject,requestCode);
        }
    }

申请的过程以及成功或者失败都是通过反射来执行和实现;如果是成功的话,通过invoke();方法去执行相应的操作;

  public static void executeSuccess(Object mOhject, int requestCode) {
        //获取class中所有的方法
        Method[] methods = mOhject.getClass().getDeclaredMethods();
        for(Method method:methods){
            System.out.println("--------"+method);
            //获取该方法上有没有打这个成功的标记
            PermissionSuccess successMethod = method.getAnnotation(PermissionSuccess.class);
            if(successMethod!=null){
                //代表该方法打了标记
                //遍历找到打了标记的方法并且我们的请求码要一致
                int methodCode = successMethod.requestCode();
                if(methodCode==requestCode){
                    //这个就是我们要找的成功的方法
                    //反射执行该方法
                    executeMethod(mOhject,method);
                }
            }
        }
    }

通过反射获取该类中所有的方法,根据传入的requestCode和方法注解中的methodCode对比,如果一致的话,就调用executeMethod();去执行;

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

获取失败的处理和执行也是一样的;

    /**
     * 执行失败的方法
     * @param mObject
     * @param requestCode
     */
    public static void executeFailMethod(Object mObject, int requestCode) {
        //获取class中所有的方法
        Method[] methods = mObject.getClass().getDeclaredMethods();
        for(Method method:methods){
            System.out.println("--------"+method);
            //获取该方法上有没有打这个失败的标记
            PermissionFail failMethod = method.getAnnotation(PermissionFail.class);
            if(failMethod!=null){
                //代表该方法打了标记
                //遍历找到打了标记的方法并且我们的请求码要一致
                int methodCode = failMethod.requestCode();
                if(methodCode==requestCode){
                    //这个就是我们要找的成功的方法
                    //反射执行该方法
                    executeMethod(mObject,method);
                }
            }
        }
    }

这里提供了Activity、Fragment以及FragmentActivity的使用,调用下面这些方法进行请求码和需要申请的权限;

  //传请求码
    public PermissionHelper requestCode(int requestCode) {
        this.mRequestCode = requestCode;
        return this;
    }

    //传请求权限
    public PermissionHelper requestPermission(String... permisson) {
        this.mPermisson = permisson;
        return this;
    }

使用的时候肯定是要先进行权限的申请;

PermissionHelper.with(MainActivity.this).
                        requestPermission(new String[]{Manifest.permission.CALL_PHONE}).
                        requestCode(CALL_PHONE_REQUEST_DODE).
                        request();
@PermissionSuccess(requestCode =CALL_PHONE_REQUEST_DODE)
    private void callPhone(){
        Intent intent=new Intent(Intent.ACTION_CALL);
        Uri data=Uri.parse("tel:"+"15889548152");
        intent.setData(data);
        startActivity(intent);
    }

这里是成功要执行的相应操作;如果需要对失败也进行相应提示的话,写一个失败的方法就可以了,也可以不处理;

@PermissionFail(requestCode =CALL_PHONE_REQUEST_DODE)
    private void callPhoneFail(){
        Toast.makeText(this, "你拒绝了拨打电话", Toast.LENGTH_SHORT).show();
    }

下面这个的话是申请结果的一个回调;

  @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        PermissionHelper.requestPermissionsResult(this,requestCode,permissions,grantResults);
    }

这样就ok了,使用起来还是蛮简单的,效果如下:

GIF.gif

源码地址:http://pan.baidu.com/s/1sldiMx3

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

推荐阅读更多精彩内容