前言

android6.0開始,权限的申请发生了改变,申请变的动态化,也就是执行时权限,和iOS相仿,动态化的意思是指,在每次使用须要危急权限的方法的时候。须要检查程序是否获得了该权限的许可。动态化的权限申请能够让用户更加清晰的知道程序须要什么权限。以及程序中哪些地方的操作须要涉及用户安全。

不再是只在程序安装的时候,一次性把所须要的普通的、危急级别的权限一次性列出来。然后展示给用户。

当project项目的target Sdk为23时,因为考虑到用户假设没有进行权限的动态检查,那么在执行到须要权限的代码时,会发生crash。而当你的target Sdk为23下面时,则不强制要求权限的动态监測,此时app不会crash。还是能够正常的使用功能。

Google官网上动态申请权限的方法分了在Activity和Fragment这两种,通过ContextCompat以及子类,ActivityCompat和FragmentCompat去进行权限的申请和权限的检查,而申请的方式是弹出一个系统的不能够改写的对话框。结果是通过Activity和Fragment的onRequestPermissionResult()方法进行返回。

详细能够參考官网

可是这样的代码会促使以前的project进行大改造或者说代码的逻辑会耦合的写在同一个方法里。显的不方便和臃肿。

所以下面的EasyPermissionUtil就是简化权限请求的方式,同一时候能够使代码的逻辑更加清晰。

EasyPermissionUtil:简化权限请求

因为权限的请求和结果的返回须要分开Activity和Fragment两种去进行操作,这样会比較麻烦,所以EasyPermissionUtil中投机取巧,通过开启一个新的activity进行权限申请和检查的操作。这样不用去区分多种情况,同一时候也能够把全部的申请过程和结果统一由EasyPermissionUtil进行处理。

接下来看一下总体的思想:

使用的方法

PermissionUtil.getInstance().request(MainActivity.this, new String[]{Manifest.permission.READ_CALENDAR}, mRequestCode,
new PermissionResultCallBack() {
@Override
public void onPermissionGranted() {
// 当全部权限的申请被用户允许之后,该方法会被调用
} @Override
public void onPermissionDenied(String... permissions) {
// 当权限申请中的某一个或多个权限,被用户以前否定了,并确认了不再提醒时,也就是权限的申请窗体不能再弹出时,该方法将会被调用
} @Override
public void onRationalShow(String... permissions) {
// 当权限申请中的某一个或多个权限,被用户否定了,但没有确认不再提醒时,也就是权限窗体申请时,但被否定了之后,该方法将会被调用.
}
});

项目源代码下载以及介绍。请看github。

项目源代码

在PermissionUtil中,要做的是:

1.进行权限检查

2.没有得到权限许可的进行权限申请

3.返回权限申请的结果

public class PermissionUtil {

    private PermissionResultCallBack mPermissionResultCallBack;
private volatile static PermissionUtil instance;
private int mRequestCode;
private Context mContext;
private Fragment mFragment;
private List<PermissionInfo> mPermissionListNeedReq;
private String[] mPermissions; public static PermissionUtil getInstance() {
if (instance == null) {
synchronized (PermissionUtil.class) {
if (instance == null) {
instance = new PermissionUtil();
}
}
}
return instance;
} /**
* 用于fragment中请求权限
* @param fragment
* @param permissions
* @param requestCode
* @param callBack
*/
public void request(@NonNull Fragment fragment,@NonNull String[] permissions,@NonNull int requestCode, PermissionResultCallBack callBack) {
this.mFragment = fragment;
this.request(fragment.getActivity(), permissions, requestCode, callBack);
} /**
* 用于activity中请求权限
* @param context
* @param permissions
* @param requestCode
* @param callBack
*/
public void request(@NonNull Context context,@NonNull String[] permissions,@NonNull int requestCode, PermissionResultCallBack callBack) { if (Looper.myLooper() != Looper.getMainLooper()) {
throw new RuntimeException("request permission only can run in MainThread!");
} if (permissions.length == 0) {
return;
} if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
onGranted();
return;
} this.mContext = context;
this.mPermissions = permissions;
this.mRequestCode = requestCode;
this.mPermissionResultCallBack = callBack;
this.mPermissionListNeedReq = new ArrayList<PermissionInfo>(); if (needToRequest()) {
requestPermissions();
} else {
onGranted();
}
} /**
* 通过开启一个新的activity作为申请权限的媒介
*/
private void requestPermissions() { Intent intent = new Intent(mContext, HelpActivity.class);
intent.putExtra("permissions", mPermissions);
intent.putExtra("requestCode", mRequestCode);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);
} /**
* 检查是否须要申请权限
* @return
*/
private boolean needToRequest() {
for (String permission : mPermissions) {
int checkRes = ContextCompat.checkSelfPermission(mContext, permission);
if (checkRes != PackageManager.PERMISSION_GRANTED) {
PermissionInfo info = new PermissionInfo(permission);
if (mContext instanceof Activity &&
ActivityCompat.shouldShowRequestPermissionRationale((Activity) mContext, permission)) {
info.setRationalNeed(true);
}
mPermissionListNeedReq.add(info);
}
} if (mPermissionListNeedReq.size() > 0) {
mPermissions = new String[mPermissionListNeedReq.size()];
for (int i = 0; i < mPermissionListNeedReq.size(); i++) {
mPermissions[i] = mPermissionListNeedReq.get(i).getName();
}
return true;
} return false;
} /**
* 申请权限结果返回
* @param requestCode
* @param permissions
* @param grantResults
*/
@TargetApi(Build.VERSION_CODES.M)
protected void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults) { if (requestCode == mRequestCode) { if (mContext != null && mContext instanceof Activity) {
((Activity) mContext).onRequestPermissionsResult(requestCode, permissions, grantResults);
} if (mFragment != null) {
mFragment.onRequestPermissionsResult(requestCode, permissions, grantResults);
} boolean isAllGranted = true;
List<PermissionInfo> needRationalPermissionList = new ArrayList<PermissionInfo>();
List<PermissionInfo> deniedPermissionList = new ArrayList<PermissionInfo>();
for (int i = 0; i < permissions.length; i++) {
if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
if (mPermissionListNeedReq.get(i).isRationalNeed()) {
needRationalPermissionList.add(mPermissionListNeedReq.get(i));
} else {
deniedPermissionList.add(mPermissionListNeedReq.get(i));
}
isAllGranted = false;
}
} if (needRationalPermissionList.size() != 0) {
showRational(needRationalPermissionList);
} if (deniedPermissionList.size() != 0) {
onDenied(deniedPermissionList);
} if (isAllGranted) {
onGranted();
} }
} /**
* 权限被用户许可之后回调的方法
*/
private void onGranted() {
if (mPermissionResultCallBack != null) {
mPermissionResultCallBack.onPermissionGranted();
}
} /**
* 权限申请被用户否定之后的回调方法,这个主要是当用户点击否定的同一时候点击了不在弹出,
* 那么当再次申请权限,此方法会被调用
* @param list
*/
private void onDenied(List<PermissionInfo> list) {
if(list == null || list.size() == 0) return; String[] permissions = new String[list.size()];
for (int i = 0; i < list.size(); i++) {
permissions[i] = list.get(i).getName();
} if (mPermissionResultCallBack != null) {
mPermissionResultCallBack.onPermissionDenied(permissions);
}
} /**
* 权限申请被用户否定后的回调方法,这个主要场景是当用户点击了否定,但未点击不在弹出,
* 那么当再次申请权限的时候,此方法会被调用
* @param list
*/
private void showRational(List<PermissionInfo> list) {
if(list == null || list.size() == 0) return; String[] permissions = new String[list.size()];
for (int i = 0; i < list.size(); i++) {
permissions[i] = list.get(i).getName();
} if (mPermissionResultCallBack != null) {
mPermissionResultCallBack.onRationalShow(permissions);
}
} }

在PermissionResutCallBack中,要做的是:

1.返回相应的结果

public interface PermissionResultCallBack {

    /**
* 当全部权限的申请被用户允许之后,该方法会被调用
*/
void onPermissionGranted(); /**
* 当权限申请中的某一个或多个权限,被用户以前否定了,并确认了不再提醒时,也就是权限的申请窗体不能再弹出时,
* 该方法将会被调用
* @param permissions
*/
void onPermissionDenied(String... permissions); /**
* 当权限申请中的某一个或多个权限,被用户否定了,但没有确认不再提醒时,也就是权限窗体申请时,但被否定了之后,
* 该方法将会被调用.
* @param permissions
*/
void onRationalShow(String... permissions);
}

在HelpActivity中。要做的就是:

1.申请权限

2.通过onRequestPermissionUtil返回结果给PermissionUtil

当然这个activity必须是透明的,并且是没有不论什么的view的。这样看起来才不像是开了一个新的activity。

public class HelpActivity extends Activity {

    @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
handleIntent(getIntent());
}
} @Override
protected void onNewIntent(Intent intent) {
handleIntent(intent);
} // 权限申请
@TargetApi(Build.VERSION_CODES.M)
private void handleIntent(Intent intent) {
String[] permissions = intent.getStringArrayExtra("permissions");
int requestCode = intent.getIntExtra("requestCode", 42);
ActivityCompat.requestPermissions(this, permissions, requestCode);
} @Override
protected void onDestroy() {
super.onDestroy();
} // 返回结果
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
PermissionUtil.getInstance().onRequestPermissionResult(requestCode, permissions, grantResults);
finish();
}
}

项目源代码下载以及介绍。请看github。

android6.0权限管理工具EasyPermissionUtil的更多相关文章

  1. Android6.0权限管理以及使用权限该注意的地方

    Android 6.0 Marshmallow首次增加了执行时权限管理,这对用户来说,能够更好的了解.控 制 app 涉及到的权限.然而对开发人员来说却是一件比較蛋疼的事情.须要兼容适配,并保证程序功 ...

  2. Android6.0权限大全和权限分类

    本文转载至: https://blog.csdn.net/qq_26440221/article/details/53097868 自从出了Android6.0权限管理之后,再也不能像以前那样粘贴复制 ...

  3. Android开发——Android 6.0权限管理机制详解

    .Android 6.0运行时主动请求权限 3.1  检测和申请权限 下面的例子介绍上面列出的读写SD卡的使用例子,可以使用以下的方式解决: public boolean isGrantExterna ...

  4. Android 6.0权限管理

    Android 6.0权限管理 关于权限管理 Android6.0 发布之后,Android 的权限系统被重新设计.在 23 之前 App 的权限只会在用户安装的时候询问一次,App一旦安装后就可以使 ...

  5. Android_设备隐私获取,忽略6.0权限管理

    1.前言 (1).由于MIUI等部分国产定制系统也有权限管理,没有相关api,故无法判断用户是否允许获取联系人等隐私.在Android 6.0之后,新增权限管理可以通过官方api判断用户的运行状态: ...

  6. Android教程 -05 Android6.0权限的管理

    视频为本篇博客知识的讲解,建议采用超清模式观看, 欢迎点击订阅我的优酷 上篇文章我们讲解了通过隐式意图拨打电话,在AndroidManifest.xml文件中添加了权限 <uses-permis ...

  7. Android获取设备隐私 忽略6.0权限管理

    1.前言 (1).由于MIUI等部分国产定制系统也有权限管理,没有相关api,故无法判断用户是否允许获取联系人等隐私.在Android 6.0之后,新增权限管理可以通过官方api判断用户的运行状态: ...

  8. Android 6.0 权限管理最佳实践

    博客: Android 6.0 运行时权限管理最佳实践 github: https://github.com/yanzhenjie/AndPermission

  9. Android 6.0 权限管理

    google官方例子: https://github.com/googlesamples/android-RuntimePermissions Android 6.0在我们原有的AndroidMani ...

随机推荐

  1. [NC13C]形态形成场/[Gym100430B]Divisible Substrings

    [NC13C]形态形成场/[Gym100430B]Divisible Substrings 题目大意: 有\(m(m\le26)\)个字符串替换式\(S_i(|S_i\le100|)\),表示某个大写 ...

  2. 洛谷P1462 通往奥格瑞玛的道路

    题目背景 在艾泽拉斯大陆上有一位名叫歪嘴哦的神奇术士,他是部落的中坚力量 有一天他醒来后发现自己居然到了联盟的主城暴风城 在被众多联盟的士兵攻击后,他决定逃回自己的家乡奥格瑞玛 题目描述 在艾泽拉斯, ...

  3. 使用OData快速构建REST服务

    OData是微软支持的一种查询标准,它的第四版使用了REST规范,看起来简洁多了.它的最大的特点是可以在客户端自行配制查询条件,使用它构建REST服务时再也不用担心查询的扩展性问题了. 如下是几个简单 ...

  4. Appium+python自动化9-SDK Manager

    前言 SDK Manager到有哪些东西是必须安装的呢? 一.SDK Manager 1.双击打开SDK Manager界面

  5. [Android Memory] 使用 Eclipse Memory Analyzer 进行堆转储文件分析

    转载地址:http://www.ibm.com/developerworks/cn/opensource/os-cn-ecl-ma/index.html Eclipse Memory Analyzer ...

  6. django:MySQL Strict Mode is not set for database connection 'default'

    ?: (mysql.W002) MySQL Strict Mode is not set for database connection 'default'        HINT: MySQL's ...

  7. (Inside Out) Web地图坐标系——TDT的奇妙

    一个GIS科班出生的研究生.把已还到课本的基础GIS知识,准备又一次学习,并结合这几年下来自身在行业中GIS的应用.总结一些有用的GIS知识点.一备不时之需,二为积累沉淀,三则是年龄越大.记性越差,加 ...

  8. iOS: NSURLConnection详解

    摘要: NSURLConnection是iOS网络编程中一个比较旧的类,在需要兼容低版本的系统时,NSURLConnection也是一个不错的选择. 一.引言 在iOS7后,NSURLSession基 ...

  9. ZZY的宠物(矩阵运算+快速幂)

    E :ZZY的宠物 描述 ZZY领养了一对刚刚出生的不知名小宠物..巨萌巨可爱!!...小宠物的生命为5个单位时间并且不会在中间出意外翘辫子(如: 从0出生能活到5但活不到6)..小宠物经过2个单位时 ...

  10. Android studio如何导出.so库(NDK开发入门)

    转自:http://blog.csdn.net/ssy_neo/article/details/51758687 项目中用到了硬件调试,google一下拿到了硬件调试的源码,可惜握草so库根本加载不进 ...