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();}
看到没,使用很方便呀!
下面给出处理框架的代码:点击查看
- Android6.0运行时权限处理架构搭建
- Android6.0运行时权限处理
- Android6.0运行时权限处理详解
- android6.0运行时权限处理简介
- Android6.0运行时权限处理
- Android6.0运行时权限处理透析
- Android6.0运行时权限的处理
- 关于Android6.0运行时权限处理
- Android6.0+运行时权限的处理
- Android6.0运行时权限的处理及解决办法
- android6.0 运行时权限处理完全解析
- Android6.0运行时权限处理-超简单封装
- Android6.0运行时权限:处理定位和存储问题
- 再谈Android6.0 运行时权限(快速处理)
- Android6.0运行时权限的处理及解决办法
- Android6.0 运行时权限
- Android6.0 运行时权限
- Android6.0运行时权限
- mian函数跳转到mainret = main(argc, argv, envp)
- 条款 03
- 五分钟学会Kotlin语法
- 阿里巴巴java开发手册
- .h头文件 .lib库文件 .dll动态库文件之间的关系
- Android6.0运行时权限处理架构搭建
- LintCode刷题之路---二叉树的路径
- 从头开始搭建一个dubbo+zookeeper平台
- Redis入门
- caffe+win8+vs2013+Gpu配置记录
- 【开发笔记】Redis 3.0 Windows x64版本的安装
- 开源整理:Android App新手指引开源控件
- 项目中应用eventbus解决的问题
- htmlDom对象转成jquery对象才可以使用jquery的方法