Android6.0运行时权限解析,RxPermissions的使用,自己封装一套权限框架
来源:互联网 发布:南风知我意七微女主 编辑:程序博客网 时间:2024/05/10 20:59
Android6.0运行时权限解析,RxPermissions的使用,自己封装一套权限框架
在Android6.0中,新增加了一个运行时的权限,我相信很多人都已经知道了,估计也知道怎么用了,这篇博客很简单,就是告诉大家如何去申请运行时权限和RxPermission这个权限框架的使用,同时根据现有的技术封装思想,去封装一个自己可用的权限框架,好的,我们继续往下看
一.Android M 运行时权限介绍
关于Android M的更新变化,我就不啰嗦了,有兴趣的可以看下Android M更新
而我们的这篇文章,也是直接参考的Google api文档中关于运行时权限这一块的来相应的讲解Google API 运行时权限
先来说一些概念性的东西,从 Android 6.0(API 级别 23)开始,用户开始在应用运行时向其授予权限,而不是在应用安装时授予。此方法可以简化应用安装过程,因为用户在安装或更新应用时不需要授予权限。它还让用户可以对应用的功能进行更多控制;这句话的意思就是你安装的时候,Android6.0之前,假设你看到很多权限,有一两个权限你不想给他,但是如果你不给他,就无法安装,可是像QQ,微信这样的应用,是你不想安装就不想安装的吗?这是非常流氓的,而运行时权限出来后,正常安装,但是如果你想使用这个功能,再去申请权限,这就比较合理了,我们接着往下看
系统权限分为两类:正常权限和危险权限:
正常权限不会直接给用户隐私权带来风险。如果您的应用在其清单中列出了正常权限,系统将自动授予该权限。
危险权限会授予应用访问用户机密数据的权限。如果您的应用在其清单中列出了正常权限,系统将自动授予该权限。如果您列出了危险权限,则用户必须明确批准您的应用使用这些权限。
这里也比较好理解,危险权限我们需要去申请就OK了,如果你搞不清楚这些权限的区别,这里我推荐你去看正常权限和危险权限 ,在这个表中,列举了所有的权限,你可以根据自己的需求去搜索
我们说了这些概念,其实我觉得你们都会了,那我们直接进入代码环节吧
二.申请权限
权限你可以申请单个,也可以申请多个,我们一步步看,假设我们以打电话的权限为例子,我们在清单文件中填写电话权限
<uses-permission android:name="android.permission.CALL_PHONE"/>
正常来讲,我们只需要调用这段打电话的代码就可以拨打电话了,所有我们写了一个打电话的方法,但是他却报错了,那是因为我们使用的targetSdkVersion是25,大于23,所有他会检查权限,也就是这样
他警告我们需要去判断权限,那我们就按照他的提示一步步来,首先判断是否同意了该权限
//正常获取权限 private void checkPermissionForNormal() { //判断是否同意此权限 if (ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) { //如果应用之前请求过此权限但用户拒绝了请求,此方法将返回 true if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CALL_PHONE)) { Toast.makeText(this, "你之前拒绝过此权限", Toast.LENGTH_SHORT).show(); } else { //申请权限 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CALL_PHONE}, 100); } } else { callPhone(); } }
这代码看起来还是比较正常的,首先他会去检查你当前的权限是否等于PackageManager.PERMISSION_GRANTED,0为成功,-1为失败,如果他不等于0,那我就去检查你之前是否请求过该权限,同时你点击了拒绝。
注:如果用户在过去拒绝了权限请求,并在权限请求系统对话框中选择了 不再提醒 选项,此方法将返回 false。如果设备规范禁止应用具有该权限,此方法也会返回 false。
好的,如果都没有,那我就通过ActivityCompat的requestPermissions方法去请求权限,里面的几个参数要注意一下,第一个是上下文,第二个是权限数组,也就是说他支持单个和多个权限的申请,第三个是回调的resultCode,我们来运行一下,看下他是如何申请的
好的,那我们现在来处理一下结果吧,实现一下onRequestPermissionsResult方法
//权限的回调 @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { switch (requestCode) { case 100: { //返回的结果数组大于0说明有结果 if (grantResults.length > 0 //因为我们只判断了一个打电话的权限,所有是数组的0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { Toast.makeText(this, "同意了权限", Toast.LENGTH_SHORT).show(); callPhone(); } else { Toast.makeText(this, "拒绝了权限", Toast.LENGTH_SHORT).show(); } return; } } }
这段代码的注释也很清楚,我们只要判断有结果,然后就可以去做相应的,处理了,这个是单个的权限
我们再来看下多个权限的申请,首先是申请了
//正常获取权限 private void checkPermissionForNormal() { //判断是否同意此权限 if (ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this, Manifest.permission.SYSTEM_ALERT_WINDOW) != PackageManager.PERMISSION_GRANTED) { //申请权限 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CALL_PHONE, Manifest.permission.CAMERA , Manifest.permission.SYSTEM_ALERT_WINDOW}, 100); } }
我在这里申请了一个电话,一个相机的权限,还有一个窗口权限,那我们结果的处理如何呢
//权限的回调 @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { switch (requestCode) { case 100: { if (grantResults.length > 0) { for (int i = 0; i < grantResults.length; i++) { if (grantResults[i] == PackageManager.PERMISSION_GRANTED) { Toast.makeText(this, "同意权限", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(this, "拒绝权限", Toast.LENGTH_SHORT).show(); } } } else { Toast.makeText(this, "拒绝了权限", Toast.LENGTH_SHORT).show(); } return; } } }
同样的我们只需要去判断我们的返回值0或者-1就可以了,那我们来看下最终的演示结果
这里要注意一点的就是你计算申请了运行时权限,你的清单文件中,也还是要加入添加相应的权限
<uses-permission android:name="android.permission.CALL_PHONE"/> <uses-permission android:name="android.permission.CAMERA"/> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
三.RxPermissions
RxPermissions是一个封装的权限库,因为使用比较简单,所有我也提出来给大伙讲讲,地址可以参考RxPermissions GitHub
先来说一下这个RxPermissions库的集成工作,因为他是跟着RxJava一起的,如果要使用,还得添加RxJava,而且RxJava有两个版本,我们这里以RxJava2为例子
添加依赖
//RxPermissions compile 'com.tbruyelle.rxpermissions2:rxpermissions:0.9.3@aar' //RxJava2 compile "io.reactivex.rxjava2:rxjava:2.0.0"
他的使用如果用正常的RxJava语法,那就是这样:
RxPermissions rxPermissions = new RxPermissions(MainActivity.this);rxPermissions.request(Manifest.permission.CALL_PHONE) .subscribe(new Observer<Boolean>() { @Override public void onSubscribe(Disposable d) { } @Override public void onNext(Boolean value) { if(value){ Toast.makeText(MainActivity.this, "同意权限", Toast.LENGTH_SHORT).show(); }else { Toast.makeText(MainActivity.this, "拒绝权限", Toast.LENGTH_SHORT).show(); } } @Override public void onError(Throwable e) { } @Override public void onComplete() { } });
这样我们可以申请到权限了,如图
当然如果你使用lambda表达式,你会更爽的
RxPermissions rxPermissions = new RxPermissions(MainActivity.this);rxPermissions .request(Manifest.permission.CALL_PHONE) .subscribe(granted -> { if (granted) { Toast.makeText(MainActivity.this, "同意权限", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(MainActivity.this, "拒绝权限", Toast.LENGTH_SHORT).show(); } });
四.权限封装
关于权限的封装其实还是比较纠结的,我们分析下,首先判断权限,是没有什么问题的,申请权限也是没有什么问题的,但是处理结果就麻烦了,他是在Activity的回调中,其实在fragment也有这个回调处理,所有现在市面上比较多的就是fragment中处理,而我们上面的RxPermissions也是这样处理的,我们看一下他的源码
private RxPermissionsFragment getRxPermissionsFragment(Activity activity) { RxPermissionsFragment rxPermissionsFragment = findRxPermissionsFragment(activity); boolean isNewInstance = rxPermissionsFragment == null; if (isNewInstance) { rxPermissionsFragment = new RxPermissionsFragment(); FragmentManager fragmentManager = activity.getFragmentManager(); fragmentManager .beginTransaction() .add(rxPermissionsFragment, TAG) .commitAllowingStateLoss(); fragmentManager.executePendingTransactions(); } return rxPermissionsFragment; }
他把这个fragment add在这个activity中,然后再fragment中处理,说实话,挺巧妙的,那我们今天就换一种方式来处理,这就是我们的统配Activity中处理,而我现在教大家另一种封装的方法,那就是实现一个Activity的基类,先看下我们如何去使用的
checkPermissions(new String[]{Manifest.permission.CALL_PHONE, Manifest.permission.CAMERA,}, 300, new PermissionsResultListener() { @Override public void onSuccessful(int[] grantResults) { for (int i = 0; i < grantResults.length; i++) { if (grantResults[i] == PackageManager.PERMISSION_GRANTED) { Toast.makeText(MainActivity.this, "同意权限", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(MainActivity.this, "拒绝权限", Toast.LENGTH_SHORT).show(); } } } @Override public void onFailure() { Toast.makeText(MainActivity.this, "失败", Toast.LENGTH_SHORT).show(); }});
可以发现,这里我们就一行代码,checkPermissions调用,里面的参数一个是权限数组,一个是返回码,还有一个是回调,那如何去做呢,其实就是实现一个接口
public interface PermissionsResultListener { //成功 void onSuccessful(int[] grantResults); //失败 void onFailure();}
以及在PermissionsActivity中完成它的操作,不过有一个弊端就是需要继承PermissionsActivity,所有我们要写我们的checkPermissions方法,就需要继承这个PermissionsActivity,而这里面的代码说不上难
public class PermissionsActivity extends AppCompatActivity { private PermissionsResultListener mListener; private int mRequestCode; private List<String> mListPermissions = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } protected void checkPermissions(String[] permissions, int requestCode, PermissionsResultListener listener) { //权限不能为空 if (permissions != null || permissions.length != 0) { mListener = listener; mRequestCode = requestCode; for (int i = 0; i < permissions.length; i++) { if (!isHavePermissions(permissions[i])) { mListPermissions.add(permissions[i]); } } //遍历完后申请 applyPermissions(); } } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == mRequestCode) { if (grantResults.length > 0) { mListener.onSuccessful(grantResults); } else { mListener.onFailure(); } } } //判断权限是否申请 private boolean isHavePermissions(String permissions) { if (ContextCompat.checkSelfPermission(this, permissions) != PackageManager.PERMISSION_GRANTED) { return false; } return true; } //申请权限 private void applyPermissions() { if (!mListPermissions.isEmpty()) { int size = mListPermissions.size(); ActivityCompat.requestPermissions(this, mListPermissions.toArray(new String[size]), mRequestCode); } }}
这就是我们的权限封装了,到这里你应该明白或者说掌握了运行时权限的绝大部分操作吧,我们运行一下看下
Sample下载
有兴趣的加群讨论:555974449
付费群
- Android6.0运行时权限解析,RxPermissions的使用,自己封装一套权限框架
- Android6.0运行时权限解析,RxPermissions的使用,自己封装一套权限框架
- Android6.0运行时权限解析,RxPermissions的使用
- Android6.0运行时权限以及RxPermissions的使用
- Android6.0使用RxPermissions获取运行时权限
- android 运行时权限解析RxPermissions的使用
- android6.0新权限申请以及RxPermissions库的使用
- Android6.0运行时权限的封装
- Android6.0------权限申请RxPermissions
- Android6.0动态运行时权限封装使用
- android6.0运行时权限完美封装
- android6.0运行时权限完美封装
- Android6.0M运行时权限封装
- Android6.0运行时权限的理解和封装
- android6.0权限适配RxPermissions
- RxPermissions 获取运行时权限
- Android6.0运行时权限解析
- Android6.0权限封装使用
- Bluetooth tethering不能用问题
- 机器学习第一阶段记录
- Ubuntu 中的 nautilus 命令
- 配置Server Side TAF
- myeclipse10破解详细教程
- Android6.0运行时权限解析,RxPermissions的使用,自己封装一套权限框架
- 敏捷开发中的测试
- 带分数
- [LeetCode]315. Count of Smaller Numbers After Self
- 教你轻松将Android library 发布到JCenter
- JavaScript,调用函数的5种方法
- 腾讯云数据库团队:Greenplum 简单性能测试与分析
- Opencv 字符识别-分类器(SVM,KNearest,RTrees,Boost,MLP)
- web学习笔记11-angularjs指令基础学习