简单介绍

关于运行时权限的说法,早在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. JAVA访问权限控制[zhuan]

    Java的访问权限控制修饰符,从最大权限到最小权限依次是:public.protected.包访问权限(默认,没有关键字)和private.对于类的访问权限只能是:public和包访问权限(但内部类可 ...

  2. 学习(主题或切入点)checklist1

    业务+技术+架构+运维+管理 技术学习:http://www.runoob.com/mongodb/mongodb-query.html 一.技术篇​补充学习列表 1,mongodb(o) 2,red ...

  3. IGV软件

    它支持各种各样的数据类型,包括基于芯片测序.二代测序数据和基因组注释数据等.整合基因组浏览器(IGV,Integrative Genomics Viewer)进行可视化浏览,它支持各种各式的数据类型, ...

  4. HDOJ 3853 LOOPS

    水概率DP.... LOOPS Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 125536/65536 K (Java/Others ...

  5. 真机调试 —— An unknown error occurred.

    iOS开发中,总会遇见各种各样的问题.今天我就在真机调试的时候出现 An unknown error occurred. 不知道什么鬼,百度一下,各种胡说八道. 解决办法: 1.退出Xcode,重新运 ...

  6. Spark之scala

    一.什么是scala scala 是基于JVMde 编程语言.JAVA是运行在jvm上的编程语言,java 源代码通过jvm被编译成class 文件,然后在os上运行class 文件.scala是运行 ...

  7. 移动端rem切图

    1.为什么用rem 根据屏幕大小,自动调整大小 2.如何使用rem 分以下几步 a.用ps把设置稿弄成640px或者750px的(记得等比例缩放) b.调试时记得把浏览器默认最小字体设置为最小.手机端 ...

  8. Unable to add window -- token null is not for an application

    导致报这个错是在于new AlertDialog.Builder(mcontext),虽然这里的参数是AlertDialog.Builder(Context context)但我们不能使用getApp ...

  9. ADB连不上,ADB server didn't ACK问题,的解决

    adb连接不上虚拟机,即便执行了adb kill-server命令也没用? 如果你的错误信息是,ADB server didn't ACK这样的话,说明5037端口被占用了. 只要找出占用此端口的进程 ...

  10. Python 学习笔记二

    笔记二 :print 以及基本文件操作 笔记一已取消置顶链接地址 http://www.cnblogs.com/dzzy/p/5140899.html 暑假只是快速过了一遍python ,现在起开始仔 ...