简单介绍

关于运行时权限的说法,早在Google发布android 6.0的时候,大家也听得蛮多的。从用户的角度来讲,用户是受益方,更好的保护用户的意思,而对于开发者来说,无疑增加了工作量。

对于6.0以下的权限在安装时,会根据权限声明产生一个权限列表,用户只有同意才能完成app的安装。而在6.0以后,不需要先对权限授权就可以安装app,对于权限的授权我们可以选择禁止。

在新的权限机制中,Google将权限分为两类:

Normal Permissions(普通权限):不涉及用户隐私,不需要用户进行授权,比如访问网络等;

Dangerous Permission(危险权限):涉及到用户隐私,需要用户进行授权,比如相机访问、读取SD卡等。

PS:运行时权限只适合APP运行在Android 6.x以上的机器,对于危险权限Google官方也对其进行了分组,只要一组中的某一权限被授权,同组的权限也同样会被授权。

操作步骤

简单的介绍了关于运行时权限的使用方法,操作步骤如下

  1. 在Androidmanifest.xml文件声明相关权限

  2. 通过ContextCompat.checkSelfPermission方法检查某项权限被授予情况

  3. 申请授权

  4. 权限回调处理

封装调用

权限的申请我们一般的做法都在Activity被创建的时候,才开始申请危险权限。而每次都得重复上述的操作,想想都觉得烦。为此,笔者将运行时权限的使用进行了进一步的归纳总结。将权限的检查统一封装在基类中,子类继承并实现抽象方法,传入权限数组等即可。

1)通过抽象方法getNeedPermissions( )获取需要进行检测的权限数组,检查相关权限是否授权,如果未授权则开始申请权限

 /**
* 检查所有权限,无权限则开始申请相关权限
*/
protected void checkAllNeedPermissions() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return;
List<String> needRequestPermissonList = getDeniedPermissions(getNeedPermissions());
if (null != needRequestPermissonList && needRequestPermissonList.size() > 0) {
ActivityCompat.requestPermissions(this, needRequestPermissonList.toArray(
new String[needRequestPermissonList.size()]), REQUEST_CODE_PERMISSON);
}
}

2)权限授权情况回调处理,这里授权失败默认弹框是否前往设置页面授权

 /**
* 权限授权结果回调
*
* @param requestCode
* @param permissions
* @param paramArrayOfInt
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] paramArrayOfInt) {
if (requestCode == REQUEST_CODE_PERMISSON) {
if (!verifyPermissions(paramArrayOfInt)) {
permissionGrantedFail();
showTipsDialog();
isNeedCheckPermission = false;
} else permissionGrantedSuccess();
}
}

PS:其中permissionGrantedSuccess()和permissionGrantedSuccess()为抽象方法,由子类实现。

3)简单调用,子类继承该基类,实现以下抽象方法即可

 @Override
public String[] getNeedPermissions() {
return new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
} @Override
protected void permissionGrantedSuccess() { } @Override
protected void permissionGrantedFail() {
}

有没有觉得酱紫操作清晰了很多,也方便了不少。依然如此,就赶紧mark吧。

封装类的完整代码如下:

 /**
* Created by chenyk on 2016/9/28.
* 检查相关权限基类,适用于android 6.0 运行时权限
* 使用方法:需要运行时权限的activity继承此类
*/
public abstract class BaseCheckPermissionActivity extends NeedBackActivity
implements OnRequestPermissionsResultCallback {
private static final int REQUEST_CODE_PERMISSON = 2020; //权限请求码 private boolean isNeedCheckPermission = true; //判断是否需要检测,防止无限弹框申请权限 @Override
protected void onResume() {
super.onResume();
if (isNeedCheckPermission) {
checkAllNeedPermissions();
}
} /**
* 检查所有权限,无权限则开始申请相关权限
*/
protected void checkAllNeedPermissions() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return;
List<String> needRequestPermissonList = getDeniedPermissions(getNeedPermissions());
if (null != needRequestPermissonList && needRequestPermissonList.size() > 0) {
ActivityCompat.requestPermissions(this, needRequestPermissonList.toArray(
new String[needRequestPermissonList.size()]), REQUEST_CODE_PERMISSON);
}
} /**
* 获取权限集中需要申请权限的列表
*
* @param permissions
* @return
*/
private List<String> getDeniedPermissions(String[] permissions) {
List<String> needRequestPermissonList = new ArrayList<>();
for (String permission : permissions) {
if (ContextCompat.checkSelfPermission(this, permission) !=
PackageManager.PERMISSION_GRANTED ||
ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) {
needRequestPermissonList.add(permission);
}
}
return needRequestPermissonList;
} /**
* 所有权限是否都已授权
*
* @return
*/
protected boolean isGrantedAllPermission() {
List<String> needRequestPermissonList = getDeniedPermissions(getNeedPermissions());
return needRequestPermissonList.size() == 0;
} /**
* 权限授权结果回调
*
* @param requestCode
* @param permissions
* @param paramArrayOfInt
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] paramArrayOfInt) {
if (requestCode == REQUEST_CODE_PERMISSON) {
if (!verifyPermissions(paramArrayOfInt)) {
permissionGrantedFail();
showTipsDialog();
isNeedCheckPermission = false;
} else permissionGrantedSuccess();
}
} /**
* 检测所有的权限是否都已授权
*
* @param grantResults
* @return
*/
private boolean verifyPermissions(int[] grantResults) {
for (int grantResult : grantResults) {
if (grantResult != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
} /**
* 显示提示对话框
*/
protected void showTipsDialog() {
new AlertDialog.Builder(this).setTitle("提示信息").setMessage("当前应用缺少" + getDialogTipsPart()
+ "权限,该功能暂时无法使用。如若需要,请单击【确定】按钮前往设置中心进行权限授权。")
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
})
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
startAppSettings();
}
}).show();
} /**
* 启动当前应用设置页面
*/
private void startAppSettings() {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivity(intent);
} /**
* 获取弹框提示部分内容
*
* @return
*/
protected String getDialogTipsPart() {
return "必要";
} /**
* 获取需要进行检测的权限数组
*/
protected abstract String[] getNeedPermissions(); /**
* 权限授权成功
*/
protected abstract void permissionGrantedSuccess(); /**
* 权限授权失败
*/
protected abstract void permissionGrantedFail();

Android 开发技巧 - Android 6.0 以上权限大坑和权限检查基类封装的更多相关文章

  1. Android开发技巧——实现可复用的ActionSheet菜单

    在上一篇<Android开发技巧--使用Dialog实现仿QQ的ActionSheet菜单>中,讲了这种菜单的实现过程,接下来将把它改成一个可复用的控件库. 本文原创,转载请注明出处: h ...

  2. Android开发技巧——大图裁剪

    本篇内容是接上篇<Android开发技巧--定制仿微信图片裁剪控件> 的,先简单介绍对上篇所封装的裁剪控件的使用,再详细说明如何使用它进行大图裁剪,包括对旋转图片的裁剪. 裁剪控件的简单使 ...

  3. Android开发技巧——使用PopupWindow实现弹出菜单

    在本文当中,我将会与大家分享一个封装了PopupWindow实现弹出菜单的类,并说明它的实现与使用. 因对界面的需求,android原生的弹出菜单已不能满足我们的需求,自定义菜单成了我们的唯一选择,在 ...

  4. Android开发技巧——高亮的用户操作指南

    Android开发技巧--高亮的用户操作指南 2015-12-15补记: 发现使用PopupWindow进行遮罩层的显示,在华为P7上会有问题.具体表现为:画出来的高亮部分会偏下.原因为:通过view ...

  5. Android开发技巧——自定义控件之增加状态

    Android开发技巧--自定义控件之增加状态 题外话 这篇本该是上周四或上周五写的,无奈太久没写博客,前几段把我的兴头都用完了,就一拖再拖,直到今天.不想把这篇拖到下个月,所以还是先硬着头皮写了. ...

  6. Android开发技巧——自定义控件之使用style

    Android开发技巧--自定义控件之使用style 回顾 在上一篇<Android开发技巧--自定义控件之自定义属性>中,我讲到了如何定义属性以及在自定义控件中获取这些属性的值,也提到了 ...

  7. Android开发技巧——自定义控件之自定义属性

    Android开发技巧--自定义控件之自定义属性 掌握自定义控件是很重要的,因为通过自定义控件,能够:解决UI问题,优化布局性能,简化布局代码. 上一篇讲了如何通过xml把几个控件组织起来,并继承某个 ...

  8. Android开发技巧——自定义控件之组合控件

    Android开发技巧--自定义控件之组合控件 我准备在接下来一段时间,写一系列有关Android自定义控件的博客,包括如何进行各种自定义,并分享一下我所知道的其中的技巧,注意点等. 还是那句老话,尽 ...

  9. Android开发技巧——写一个StepView

    在我们的应用开发中,有些业务流程会涉及到多个步骤,或者是多个状态的转化,因此,会需要有相关的设计来展示该业务流程.比如<停车王>应用里的添加车牌的步骤. 通常,我们会把这类控件称为&quo ...

随机推荐

  1. [译]Profile and debug your ASP.NET MVC app with Glimpse

    原文:http://www.asp.net/mvc/overview/performance/profile-and-debug-your-aspnet-mvc-app-with-glimpse Gl ...

  2. C#深入浅出 修饰符(二)

    1.函数参数前的修饰符 params ,ref ,out params修饰的数据类型只能数组,用于参数不固定时:且此参数位于所有形式参数的最后: public static int GetMax(pa ...

  3. padding/margin/border 理解

  4. 2015baidu复赛2 连接的管道(mst && 优先队列prim)

    连接的管道 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submi ...

  5. OpenCV imread读取图片,imshow展示图片,出现cv:Exception at memory location异常

    问题如上.环境:VS2013. 代码如下: #include "stdafx.h" #include "opencv2\opencv.hpp" using na ...

  6. Android开源项目(二)

    第二部分 工具库 主要包括那些不错的开发库,包括依赖注入框架.图片缓存.网络相关.数据库ORM建模.Android公共库.Android 高版本向低版本兼容.多媒体相关及其他. 一.依赖注入DI 通过 ...

  7. 如何获取到Android控件的高度

    问题 如何获取一个控件的长和高,相信很多朋友第一眼看见这个问题都会觉得很简单,直接在onCreate里面调用getWidth.getMeasuredWidth不就可以获得了吗,但是,事实上是并没有简单 ...

  8. RHEL/CentOS 7最小化安装后需做的30件事情

    导读 CentOS是一个工业标准的Linux发行版,是红帽企业版 Linux 的衍生版本.你安装完后马上就可以使用,但是为了更好地使用你的系统,你需要进行一些升级.安装新的软件包.配置特定服务和应用程 ...

  9. 谈谈jQuery之绑定事件

    http://www.jiangweishan.com/article/jQuery-bind-on.html $.extend({ hook:function(hookName){ var sele ...

  10. Java常见的几种排序算法-插入、选择、冒泡、快排、堆排等

    本文就是介绍一些常见的排序算法.排序是一个非常常见的应用场景,很多时候,我们需要根据自己需要排序的数据类型,来自定义排序算法,但是,在这里,我们只介绍这些基础排序算法,包括:插入排序.选择排序.冒泡排 ...