Android6.0运行时权限处理架构搭建

来源:互联网 发布:岛国片在淘宝怎么搜索 编辑:程序博客网 时间:2024/06/06 08:24

Android6.0运行时权限处理架构搭建

介绍

对于6.0以下的权限及在安装的时候,根据权限声明产生一个权限列表,用户只有在同意之后才能完成app的安装,造成了我们想要使用某个app,就要默默忍受其一些不必要的权限(比如是个app都要访问通讯录、短信等)。而在6.0以后,我们可以直接安装,当app需要我们授予不恰当的权限的时候,我们可以予以拒绝(比如:单机的象棋对战,请求访问任何权限,我都是不同意的)。当然你也可以在设置界面对每个app的权限进行查看,以及对单个权限进行授权或者解除授权。

新的权限机制更好的保护了用户的隐私,Google将权限分为两类,一类是Normal Permissions,这类权限一般不涉及用户隐私,是不需要用户进行授权的,比如手机震动、访问网络等;另一类是Dangerous Permission,一般是涉及到用户隐私的,需要用户进行授权,比如读取sdcard、访问通讯录等。

Dangerous Permissions:

group:android.permission-group.CONTACTS  permission:android.permission.WRITE_CONTACTS  permission:android.permission.GET_ACCOUNTS  permission:android.permission.READ_CONTACTSgroup: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_VOICEMAILgroup:android.permission-group.CALENDAR  permission:android.permission.READ_CALENDAR  permission:android.permission.WRITE_CALENDARgroup:android.permission-group.CAMERA  permission:android.permission.CAMERAgroup:android.permission-group.SENSORS  permission:android.permission.BODY_SENSORSgroup:android.permission-group.LOCATION  permission:android.permission.ACCESS_FINE_LOCATION  permission:android.permission.ACCESS_COARSE_LOCATIONgroup:android.permission-group.STORAGE  permission:android.permission.READ_EXTERNAL_STORAGE  permission:android.permission.WRITE_EXTERNAL_STORAGEgroup:android.permission-group.MICROPHONE  permission:android.permission.RECORD_AUDIOgroup: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

我们发现危险的权限全是一组一组的,如果你申请某个危险的权限,假设你的app早已被用户授权了同一组的某个危险权限,那么系统会立即授权,而不需要用户去点击授权。此外,对于申请时弹出的dialog上面的文本说明也是对整个权限组的说明,而不是单个权限。

申请权限的方式

1.对于6.0版本以下和6.0以上的Normal Permissions,还和以前一样

<uses-permission android:name="android.permission.INTERNET"></uses-permission>

2.对于6.0以上的Dangerous Permission,就需要运行时申请权限

private void callPhone(){    //需要申请的权限    String[] usePermissions=new String[]{Manifest.permission.CALL_PHONE};    //检测是否已经授权码    int permission = ContextCompat.checkSelfPermission(this,            Manifest.permission.CALL_PHONE);    if(permission!= PackageManager.PERMISSION_GRANTED){        //没有授权,申请权限        ActivityCompat.requestPermissions(this,usePermissions,CALL_REQUEST_CODE);    }else {        //已经授权,拨打电话        Intent intent = new Intent(Intent.ACTION_CALL);        Uri data = Uri.parse("tel:" + "10086");        intent.setData(data);        startActivity(intent);    }}

申请权限时,用户可能授权,也可能拒绝,那我们怎么知道用户的选择呢?Activity提供了申请权限后的回调onRequestPermissionsResult,我们来看下它的使用:

@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {    super.onRequestPermissionsResult(requestCode, permissions, grantResults);    //判断请求码    if(requestCode==CALL_REQUEST_CODE){        //用户是否同意授权        if(grantResults[0] == PackageManager.PERMISSION_GRANTED){            callPhone();        }else {            Toast.makeText(MainActivity.this, "Call Phone Permission Denied", Toast.LENGTH_SHORT).show();        }    }}

原理很简单吧!但是每个需要权限的地方都这样调用,是不是有点麻烦?接下来我们就自己手写一个处理运行时权限的框架。

封装框架

我们先来看下libray的结构:

这里写图片描述

我们先看下注解:

@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface PermissionSuccess {    /**     * 请求码     * @return     */    int requestCode() ;}

基于运行时注解,下面我们来看下StonePermission:
public class StonePermission {
//参数
private Object mObject;//activity or fragment
private String[] mPermissions;
private int mRequestCode;//请求码

    private StonePermission(Object object){        this.mObject=object;    }    /**     * 直接请求权限     * @param activity     * @param requestCode     * @param permissions     */    public static void requestPermission(Activity activity,int requestCode,String... permissions){        realRequestPermission(activity,requestCode,permissions);    }    /**     * 直接请求权限     * @param fragment     * @param requestCode     * @param permissions     */    public static void requestPermission(Fragment fragment, int requestCode, String... permissions){        realRequestPermission(fragment,requestCode,permissions);    }    /**     * 关联调用类     * @param activity     * @return     */    public static StonePermission with(Activity activity){        return new StonePermission(activity);    }    public static StonePermission with(Fragment fragment){        return new StonePermission(fragment);    }    /**     * 添加请求码     * @param requestCode     * @return     */    public StonePermission addRequestCode(int requestCode){        this.mRequestCode=requestCode;        return this;    }    /**     * 添加申请权限     * @param permissions     * @return     */    public StonePermission permissions(String... permissions){        this.mPermissions=permissions;        return this;    }    /**     * 执行请求权限     */    public void request(){        realRequestPermission(mObject,mRequestCode,mPermissions);    }    /**     * 正在处理请求权限的地方     * @param object     * @param requestCode     * @param permissions     */    @TargetApi(Build.VERSION_CODES.M)    private static void realRequestPermission(Object object, int requestCode, String... permissions){        //1.如果小于6.0,直接调用成功方法        if(!PermissionUtil.isOverMarshmallow()){            PermissionUtil.executeSuccessMethod(object,requestCode);            return;        }        //2.0 检查没有申请的权限        List<String> deniedPermissions= PermissionUtil.checkAndObtainDeniedPermissions(object,permissions);        if(deniedPermissions.size()>0){            //3.0 申请权限            ActivityCompat.requestPermissions(PermissionUtil.getActivity(object),deniedPermissions.toArray(new String[deniedPermissions.size()]),requestCode);        }else {            PermissionUtil.executeSuccessMethod(object,requestCode);        }    }    /**     * 在 onRequestPermissionsResult 中调用,处理权限申请结果     * @param activity     * @param requestCode     * @param permissions     * @param grantResults     */    public static void onRequestPermissionsResult(Activity activity,int requestCode,String[] permissions,int[] grantResults){        requestPermissionsResult(activity,requestCode,permissions,grantResults);    }    /**     * 在 onRequestPermissionsResult 中调用,处理权限申请结果     * @param fragment     * @param requestCode     * @param permissions     * @param grantResults     */    public static void onRequestPermissionsResult(Fragment fragment, int requestCode, String[] permissions, int[] grantResults){        requestPermissionsResult(fragment,requestCode,permissions,grantResults);    }    /**     * 真正回调的地方     * @param object     * @param requestCode     * @param permissions     * @param grantResults     */    private static void requestPermissionsResult(Object object,int requestCode,String[] permissions,int[] grantResults){        List<String> deniedPermissions=new ArrayList<>();        int length = grantResults.length;        for (int i = 0; i < length; i++) {            if(grantResults[i] != PackageManager.PERMISSION_GRANTED){                deniedPermissions.add(permissions[i]);            }        }        if(deniedPermissions.size() > 0){            PermissionUtil.executeFaildMethod(object,requestCode);        }else {            PermissionUtil.executeSuccessMethod(object,requestCode);        }    }}

上面就是提供给使用者的方法,是不是很简单?

接下来让我们一起来看下具体的使用:

private void callPhone(){    //申请权限的方式:        //第一种方式        //StonePermission.requestPermission(this,CALL_REQUEST_CODE,Manifest.permission.CALL_PHONE);        //第二种方式        StonePermission.with(this)                .addRequestCode(CALL_REQUEST_CODE)                .permissions(Manifest.permission.CALL_PHONE)                .request();}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {    super.onRequestPermissionsResult(requestCode, permissions, grantResults);    //将申请权限处理交给StonePermission    StonePermission.onRequestPermissionsResult(this,requestCode,permissions,grantResults);}//成功授权后调用@PermissionSuccess(requestCode = CALL_REQUEST_CODE)public void success() {    Intent intent = new Intent(Intent.ACTION_CALL);    Uri data = Uri.parse("tel:" + "10086");    intent.setData(data);    startActivity(intent);}//申请权限失败后调用@PermissionFail(requestCode = CALL_REQUEST_CODE)private void  faild(){    Toast.makeText(MainActivity.this,"申请权限失败",Toast.LENGTH_SHORT).show();}

看到没,使用很方便呀!


下面给出处理框架的代码:点击查看