关于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 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 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

你可能感兴趣的:(关于android6.0的权限申请)