前言

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. bzoj4567 背单词

    Description Lweb 面对如山的英语单词,陷入了深深的沉思,“我怎么样才能快点学完,然后去玩三国杀呢?”.这时候睿智 的凤老师从远处飘来,他送给了 Lweb 一本计划册和一大缸泡椒,他的计 ...

  2. bzoj1123 Blockade

    Description Byteotia城市有n个 towns m条双向roads. 每条 road 连接 两个不同的 towns ,没有重复的road. 所有towns连通. Input 输入n&l ...

  3. 【原】Project configuration is not up-to-date with pom.xml

    导入一个Maven项目之后发现有一个如下的错误: Project configuration is not up-to-date with pom.xml. Run project configura ...

  4. React-Native调用支付宝,微信

    https://www.pingxx.com/docs/downloads Ping++ 是为移动端应用以及 PC 网页量身打造的下一代支付系统,通过一个 SDK 便可以同时支持移动端以及 PC 端网 ...

  5. 介绍:一款Mathematica的替代开源软件Mathetics

    Mathetics软件 1 以Python语言实现该系统 2 软件使用的语法与Mathematica同样 3 下载:http://www.mathics.org/ 4 手冊:http://www.ma ...

  6. java.lang.RuntimeException: java.io.IOException: invalid constant type: 15

    java.lang.RuntimeException: java.io.IOException: invalid constant type: 15 controller通过dubbo调用servic ...

  7. 关于给springboot添加定时器的两种方式

    原文:https://blog.csdn.net/liboyang71/article/details/72781526 首先,搭建好一个springboot项目,可使用maven或者gradle或者 ...

  8. pytest文档8-html报告报错截图+失败重跑

    前言 做web自动化的小伙伴应该都希望在html报告中展示失败后的截图,提升报告的档次,pytest-html也可以生成带截图的报告. conftest.py 1.失败截图可以写到conftest.p ...

  9. pytest文档7-pytest-html生成html报告

    前言 pytest-HTML是一个插件,pytest用于生成测试结果的HTML报告.兼容Python 2.7,3.6 pytest-html 1.github上源码地址[https://github. ...

  10. SharePoint 2013 代码创建应用程序目录(App Catalog)

    众所周知,SharePoint App是2013版本的一大特色,那么,关于App的分发有几种方式呢?SharePoint给我们提供了两种方式,一种是上载到SharePoint应用商店,另一种是在本地S ...