Android6.0执行时权限解析,RxPermissions的使用。自己封装一套权限框架


在Android6.0中,新添加了一个执行时的权限,我相信非常多人都已经知道了。预计也知道怎么用了,这篇博客非常easy。就是告诉大家怎样去申请执行时权限和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) {//假设应用之前请求过此权限但用户拒绝了请求,此方法将返回 trueif (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方法

   //权限的回调@Overridepublic 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);} }

我在这里申请了一个电话。一个相机的权限。另一个窗体权限。那我们结果的处理怎样呢

    //权限的回调@Overridepublic 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为样例

加入依赖

    //RxPermissionscompile 'com.tbruyelle.rxpermissions2:rxpermissions:0.9.3@aar'//RxJava2compile "io.reactivex.rxjava2:rxjava:2.0.0"

他的使用假设用正常的RxJava语法。那就是这样:

RxPermissions rxPermissions = new RxPermissions(MainActivity.this);
rxPermissions.request(Manifest.permission.CALL_PHONE).subscribe(new Observer<Boolean>() {@Overridepublic void onSubscribe(Disposable d) {}@Overridepublic void onNext(Boolean value) {if(value){Toast.makeText(MainActivity.this, "允许权限", Toast.LENGTH_SHORT).show();}else {Toast.makeText(MainActivity.this, "拒绝权限", Toast.LENGTH_SHORT).show();}}@Overridepublic void onError(Throwable e) {}@Overridepublic 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() {@Overridepublic 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();}}}@Overridepublic 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<>();@Overrideprotected 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();}}@Overridepublic 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的使用,自己封装一套权限框架相关推荐

  1. 这可能是最精简的Android6.0运行时权限处理,百行代码的工具类,支持Rationale,附:各种权限详细处理

    0x00:前言 对于Android6.0运行时权限的处理方式网上有很多,包括注解,RxJava等等.一直没有正面提到我关心的问题–如果我不在Activity或者Fragment里面,需要运行时权限该怎 ...

  2. 获取权限android sync,GitHub - AndSync/XPermissionUtils: 可能是最精简的Android6.0运行时权限处理方式,支持Rationale提示...

    # XPermissionUtils 可能是最精简的Android6.0运行时权限处理方式,支持Rationale提示,只有一个类,100行代码,所有弹窗等操作由用户自行处理,在Demo中也有提供代码 ...

  3. Android6.0运行时权限解决方案

    今天在测试APP的时候发现部分手机APP定位权限使用不了.看了一下机型都是Android6.0以上版本的Android手机. 之前就听说Android6.0以上版本权限管理更严格了,没想到今天踩坑了. ...

  4. Android6.0运行时权限处理

    前言 在Android6.0版本以前,往往是应用程序需要什么权限直接在manifest.xml中直接声明,当你安装程序的时候,如果不想让该程序使用某种权限,唯一的办法只能是不装这个应用,但是我们生活中 ...

  5. 【转】关于使用Android6.0编译程序时,出现getSlotFromBufferLocked: unknown buffer: 0xac0f8650问题的解释...

    这个问题是在测试leakCanaryTestDemo时发现的,期初看到有点蒙,这个demo中只使用了一个button和一个textView控件进行测试,按理说是不应该出现这种问题,在 网上查找这个问题 ...

  6. Android6.0运行时权限(危险权限列表)

    从 Android 6.0(API 23)开始,用户开始在应用运行时向其授予权限,而不是在应用安装时授予.这种权限机制可以让用户更好的管理应用的权限,保障用户隐私. Android将权限分为普通权限和 ...

  7. Android6.0之后的权限机制对App开发的影响

    随着Android系统的更新换代,每次重大更新的方面也逐步扩展,从4.*主要是增强功能,到5.*主要是美化界面,到6.*主要提高系统安全性,再到7.*和8.*主要支撑各种大屏设备,因此开发者需要对每个 ...

  8. [Android Studio]详细讲解Android6.0以上请求应用权限(解决请求权限窗口一闪而过的问题)

    现在的主流手机的Android版本都是8.0/9.0(笔者的华为手机为9.0),所以在开发Android的时候尽量使用Android8.0的版本(SDK 26).随着Android版本的提升,系统的安 ...

  9. Android6.0以上打电话动态权限

    // 检查是否获得了权限(Android6.0运行时权限)if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permissio ...

最新文章

  1. iOS 之 UICollectionView
  2. BottomNavigationBar使用详解
  3. oracle存储查询出来的值_技术分享|浅析ORACLE数据库物理体系结构及其对应优化策略...
  4. ifstat,iftop
  5. WEB安全基础-XSS基础
  6. mysql分表全局查询_mysql如何查询多样同样的表/sql分表查询、java项目日志表分表的开发思路/按月分表...
  7. Windows Server 2008 R2 install Visual Studio 2015 failed
  8. C# 判断程序是否已经在运行
  9. 一道看似简单的sql需求却难倒各路高手 - 你也来挑战下吗?
  10. Storm之——使用monit监控Storm
  11. Photoshop使用边缘功能打造后期画意
  12. 在线视频转音频怎么弄?这几个软件建议你们收藏
  13. lemming games 3 ! hdlbits
  14. html语言计算圆周长和面积,纯JSP实现计算圆的面积和周长
  15. 2011Android技术面试整理附有详细答案【ZT】
  16. FS4052】12.6v2A三节锂电池充电芯片方案
  17. 怎么做出可以卖的电路板
  18. 二叉树前中后序遍历+刷题【中】【数据结构/初阶/C语言实现】
  19. APT38:进行金融犯罪的朝鲜官方组织/APT28近期ioc汇总
  20. php放 土豆视频,PHP实现使用优酷土豆视频地址获取swf播放器分享地址_PHP

热门文章

  1. python中BeautifulSoup简单使用
  2. java 正则 任意字符_Java正则表达式 去掉括号内任意字符
  3. 昼猫笔记 JavaScript -- 异步执行 | 定时器真的定时执行?
  4. Linux(CentOS 5)下安装Oracle10 客户端(转)
  5. iptables防火墙的连接状态
  6. 在夕阳下第一次写文章的菜鸟
  7. zabbix自动发现实现批量监控docker状态
  8. Jetty开发指导:框架
  9. Linux 下 RMAN无反应问题处理
  10. 持币过节也能让钱生钱