Android6.0执行时权限解析,RxPermissions的使用,自己封装一套权限框架
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。全部他会检查权限,也就是这样
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMjY3ODcxMTU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描写叙述" title="">
他警告我们须要去推断权限。那我们就依照他的提示一步步来,首先推断是否允许了该权限
//正常获取权限
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,我们来执行一下,看下他是怎样申请的
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMjY3ODcxMTU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描写叙述" title="">
好的,那我们如今来处理一下结果吧,实现一下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
付费群
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMjY3ODcxMTU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描写叙述" title="">
Android6.0执行时权限解析,RxPermissions的使用,自己封装一套权限框架的更多相关文章
- Android 6.0 执行时权限处理全然解析
转载请标明出处: http://blog.csdn.net/lmj623565791/article/details/50709663: 本文出自:[张鸿洋的博客] 一.概述 随着Android 6. ...
- Android6.0运行时权限(基于RxPermission开源库)
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 在6.0以前的系统,都是权限一刀切的处理方式,只要用户安装,Manifest申请的权限都会被赋予,并且安装后权限也撤销不了. And ...
- Android6.0运行时权限管理
自从Android6.0发布以来,在权限上做出了很大的变动,不再是之前的只要在manifest设置就可以任意获取权限,而是更加的注重用户的隐私和体验,不会再强迫用户因拒绝不该拥有的权限而导致的无法安装 ...
- Android开发学习之路-Android6.0运行时权限
在Android6.0以后开始,对于部分敏感的“危险”权限,需要在应用运行时向用户申请,只有用户允许的情况下这个权限才会被授予给应用.这对于用户来说,无疑是一个提升安全性的做法.那么对于开发者,应该怎 ...
- Android6.0运行时权限的处理Demo
MainActivity.java package com.loaderman.permissionsdemo; import android.Manifest; import android.con ...
- imx6 Android6.0.1 init.rc解析
1. 概述 1.1 概述 之前分析过android5的init.rc,不过还是不够仔细,现在来看看android6的,多的就不写了,只写关键点 忘记一些基本概念可以先看看之前的笔记: Android5 ...
- 【转】关于使用Android6.0编译程序时,出现getSlotFromBufferLocked: unknown buffer: 0xac0f8650问题的解释
这个问题是在测试leakCanaryTestDemo时发现的,期初看到有点蒙,这个demo中只使用了一个button和一个textView控件进行测试,按理说是不应该出现这种问题,在 网上查找这个问题 ...
- [Erlang危机](5.0)执行时指标
原创文章.转载请注明出处:server非业余研究http://blog.csdn.net/erlib 作者Sunface . Then, in times of need, it's also po ...
- 【Android】打电话Demo及Android6.0的运行时权限
新手开局,查看一些旧资料,从打电话.发短信的小应用开始.代码很简单,主要是学习了: 用StartActivity()激活一个Activity组件.这里是激活了系统原生的打电话和发短信Activity. ...
随机推荐
- [ 原创 ]学习笔记-Android 学习笔记 Contacts (一)ContentResolver query 参数详解 [转载]
此博文转载自:http://blog.csdn.net/wssiqi/article/details/8132603 1.获取联系人姓名 一个简单的例子,这个函数获取设备上所有的联系人ID和联系人NA ...
- ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
登录服务器,使用root用户连接mysql时出现错误提示: $ bin/mysql -uroot -p Enter password: ERROR (HY000): Can't connect to ...
- android 后台 activity 被系统回收 保存状态
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha 活动被系统回收, 要保存状态 ,用到 活动的 在保存实例时候 的 这个方法. 当系统异常 ...
- Codeforces Round #354 (Div. 2) B. Pyramid of Glasses 模拟
B. Pyramid of Glasses 题目连接: http://www.codeforces.com/contest/676/problem/B Description Mary has jus ...
- php中赋值和引用真真的理解
php的引用(就是在变量或者函数.对象等前面加上&符号) //最重要就是 删除引用的变量 ,只是引用的变量访问不了,但是内容并没有销毁 在PHP 中引用的意思是:不同的名字访问同一个变量内容. ...
- 如何编写LVS对Real Server的健康状态检测脚本
简介:Linux 虚拟服务器(Linux Virtual Server. LVS),是一个由章文松开发的自由软件.利用KVS可以实现高可用的.可伸缩缩的Web, Mail, Cache和Medial等 ...
- PowerDesigner关系线显示名称
选中关联关系线,右击选择“格式”,打开如下窗口,将“Name” 选项进行勾选上即可. 参考: http://loginleft.iteye.com/blog/2400980
- mklink让网盘同步不同文件夹
mklink简介 Linux 下有一个叫符号链接的东东,是 ln 这个链接命令,mklink 和 ln 的功能几乎一样.在xp系统下,junction命令要用微软开发的小程序 junction.exe ...
- Linux 网络协议栈 图解
http://www.cnblogs.com/sammyliu/p/5225623.html
- 《Android学习指南》文件夹
转自:http://android.yaohuiji.com/about Android学习指南的内容分类: 分类 描写叙述 0.学习Android必备的Java基础知识 没有Java基础的朋友,请不 ...