修改日期 | 修改人 | 备注 |
2017-07-03 08:52:17[当前版本] | 裴俊绍 | 格式调整 |
2017-07-03 08:47:34 | 裴俊绍 | 样式调整 |
2017-06-23 17:41:43 | 裴俊绍 | 加了点注释 |
2017-06-23 14:57:04 | 裴俊绍 | 调整顺序 |
android6.0开始,权限的申请发生了改变,申请变的动态化,也就是运行时权限,和iOS相仿,动态化的意思是指,在每次使用需要危险权限的方法的时候,需要检查程序是否获得了该权限的许可。动态化的权限申请能够让用户更加清晰的知道程序需要什么权限,以及程序中哪些地方的操作需要涉及用户安全。不再是仅仅在程序安装的时候,一次性把所需要的普通的、危险级别的权限一次性列出来,然后展示给用户。
当工程项目的target Sdk为23时,由于考虑到用户如果没有进行权限的动态检查,那么在运行到需要权限的代码时,会发生crash,而当你的target Sdk为23以下时,则不强制要求权限的动态监测,此时app不会crash,还是可以正常的使用功能。
Google官网上动态申请权限的方法分了在Activity和Fragment这两种,通过ContextCompat以及子类,ActivityCompat和FragmentCompat去进行权限的申请和权限的检查,而申请的方式是弹出一个系统的不可以改写的对话框,结果是通过Activity和Fragment的onRequestPermissionResult()方法进行返回。
具体可以参考官网
但是这种代码会促使以前的工程进行大改造或者说代码的逻辑会耦合的写在同一个方法里,显的不方便和臃肿。所以以下的EasyPermissionUtil就是简化权限请求的方式,同时可以使代码的逻辑更加清晰。
由于权限的请求和结果的返回需要分开Activity和Fragment两种去进行操作,这样会比较麻烦,所以EasyPermissionUtil中投机取巧,通过开启一个新的activity进行权限申请和检查的操作,这样不用去区分多种情况,同时也能够把所有的申请过程和结果统一由EasyPermissionUtil进行处理。
接下来看一下整体的思想:
用法:
1.在项目的root build.gradle中
allprojects {
repositories {
maven { url "https://jitpack.io" } // 加入这句话 }
}
2.在lib工程下的build.gradle中
compile 'com.github.yxping:EasyPermissionUtil:v0.1.0'
/**
* 检查单个权限是否被允许,不会进行权限的申请.(注意:当应用第一次安装的时候,不会有rational的值,此时返回均是denied)
* 注:对于返回结果的测试:询问是3拒绝是3,允许是1
*/
public int checkSinglePermission(String permission);
/**
* 检查多个权限的状态,不会进行权限的申请.(注意:当应用第一次安装的时候,不会有rational的值,此时返回均是denied)
* 注:对于返回结果的测试:6.0版本以下的返回值map好像都是null(测了两个是null)
* 对于6.0以上的版本:
* 1.假如有2个权限,一个询问(或禁止),一个允许,则返回值map的键值对有两个,
* key为“denied”对应value的list.size()为1,key为“accept”对应value的list.size()为1;
* 2.两个都是询问(或禁止),则map的键值对有一个,key为“denied”对应value的list.size()为2
* 3.两个都是允许,则map的键值对有一个,key为“accept”对应value的list.size()为2
*/
public Map<String, List<PermissionInfo>> checkMultiPermissions(String... permissions);
//申请单个权限的调用
PermissionUtil.getInstance().request(MainActivity.this, new String[]{Manifest.permission.READ_CALENDAR},
new PermissionOriginResultCallBack() {
@Override
public void onResult(List<PermissionInfo> acceptList, List<PermissionInfo> rationalList, List<PermissionInfo> deniedList) {
if (!acceptList.isEmpty()) {
//当权限的申请被用户同意之后,该方法会被调用
Toast.makeText(MainActivity.this, acceptList.get(0).getName() + " is accepted", Toast.LENGTH_SHORT).show();
}
if (!rationalList.isEmpty()) {
//当权限的申请被用户拒绝之后,但没有确认不再提醒时,该方法会被调用
Toast.makeText(MainActivity.this, rationalList.get(0).getName() + " is rational", Toast.LENGTH_SHORT).show();
}
if (!deniedList.isEmpty()) {
//当权限的申请被用户拒绝之后,并确认了不再提醒时,该方法会被调用
Toast.makeText(MainActivity.this, deniedList.get(0).getName() + " is denied", Toast.LENGTH_SHORT).show();
}
}
});
//申请多个权限的调用
PermissionUtil.getInstance().request(MainActivity.this, new String[]{Manifest.permission.CAMERA,
Manifest.permission.READ_CONTACTS, Manifest.permission.READ_SMS},
new PermissionResultCallBack() {
@Override
public void onPermissionGranted() {
// 当所有权限的申请被用户同意之后,该方法会被调用
Toast.makeText(MainActivity.this, "all granted", Toast.LENGTH_SHORT).show();
}
@Override
public void onPermissionGranted(String... permissions) {
/**
* 当权限申请中的某一个或多个权限,被用户曾经允许了,该方法将会被调用
* 感觉没啥用
*/
StringBuilder builder = new StringBuilder();
for (String permission : permissions) {
builder.append(permission.substring(permission.lastIndexOf(".") + 1) + " ");
}
Toast.makeText(MainActivity.this, builder.toString() + " is granted", Toast.LENGTH_SHORT).show();
}
@Override
public void onPermissionDenied(String... permissions) {
/**
* 当权限申请中的某一个或多个权限,被用户曾经否定了,并确认了不再提醒时,
* 也就是权限的申请窗口不能再弹出时,该方法将会被调用
*/
StringBuilder builder = new StringBuilder();
for (String permission : permissions) {
builder.append(permission.substring(permission.lastIndexOf(".") + 1) + " ");
}
Toast.makeText(MainActivity.this, builder.toString() + " is denied", Toast.LENGTH_SHORT).show();
}
@Override
public void onRationalShow(String... permissions) {
/**
* 当权限申请中的某一个或多个权限,被用户否定了,但没有确认不再提醒时,
* 也就是权限窗口申请时,但被否定了之后,该方法将会被调用.
*/
StringBuilder builder = new StringBuilder();
for (String permission : permissions) {
builder.append(permission.substring(permission.lastIndexOf(".") + 1) + " ");
}
Toast.makeText(MainActivity.this, builder.toString() + " show Rational", Toast.LENGTH_SHORT).show();
}
});
可以通过PermissionResultCallBack获得回调的结果,也可以通过PermissionResultAdapter获得回调的结果,区别是 PermissionResultAdapter支持任意重写方法,而无需重写所有的方法.
如下例用的是PermissionResultAdapter回调
PermissionUtil.getInstance().request(UserCenter_Information.this, PERMISSIONS,
new PermissionResultAdapter() {
@Override
public void onPermissionGranted() {
// 当所有权限的申请被用户同意之后,该方法会被调用
Toast.makeText(MainActivity.this, "所有权限都被用户同意了", Toast.LENGTH_SHORT).show();
}
@Override
public void onPermissionDenied(String... permissions) {
/**
* 当权限申请中的某一个或多个权限,被用户曾经否定了,并确认了不再提醒时,
* 也就是权限的申请窗口不能再弹出时,该方法将会被调用
*/
Toast.makeText(MainActivity.this, "有权限被禁止了", Toast.LENGTH_SHORT).show();
}
@Override
public void onRationalShow(String... permissions) {
/**
* 当权限申请中的某一个或多个权限,被用户否定了,但没有确认不再提醒时,
* 也就是权限窗口申请时,但被否定了之后,该方法将会被调用.
*/
Toast.makeText(MainActivity.this, "继续申请权限", Toast.LENGTH_SHORT).show();
}
});
详情见https://github.com/yxping/EasyPermissionUtil