Android 开发技巧 - Android 6.0 以上权限大坑和权限检查基类封装
简单介绍
关于运行时权限的说法,早在Google发布android 6.0的时候,大家也听得蛮多的。从用户的角度来讲,用户是受益方,更好的保护用户的意思,而对于开发者来说,无疑增加了工作量。
对于6.0以下的权限在安装时,会根据权限声明产生一个权限列表,用户只有同意才能完成app的安装。而在6.0以后,不需要先对权限授权就可以安装app,对于权限的授权我们可以选择禁止。
在新的权限机制中,Google将权限分为两类:
Normal Permissions(普通权限):不涉及用户隐私,不需要用户进行授权,比如访问网络等;
Dangerous Permission(危险权限):涉及到用户隐私,需要用户进行授权,比如相机访问、读取SD卡等。
PS:运行时权限只适合APP运行在Android 6.x以上的机器,对于危险权限Google官方也对其进行了分组,只要一组中的某一权限被授权,同组的权限也同样会被授权。
操作步骤
简单的介绍了关于运行时权限的使用方法,操作步骤如下
在Androidmanifest.xml文件声明相关权限
通过ContextCompat.checkSelfPermission方法检查某项权限被授予情况
申请授权
权限回调处理
封装调用
权限的申请我们一般的做法都在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 以上权限大坑和权限检查基类封装的更多相关文章
- Android开发技巧——实现可复用的ActionSheet菜单
在上一篇<Android开发技巧--使用Dialog实现仿QQ的ActionSheet菜单>中,讲了这种菜单的实现过程,接下来将把它改成一个可复用的控件库. 本文原创,转载请注明出处: h ...
- Android开发技巧——大图裁剪
本篇内容是接上篇<Android开发技巧--定制仿微信图片裁剪控件> 的,先简单介绍对上篇所封装的裁剪控件的使用,再详细说明如何使用它进行大图裁剪,包括对旋转图片的裁剪. 裁剪控件的简单使 ...
- Android开发技巧——使用PopupWindow实现弹出菜单
在本文当中,我将会与大家分享一个封装了PopupWindow实现弹出菜单的类,并说明它的实现与使用. 因对界面的需求,android原生的弹出菜单已不能满足我们的需求,自定义菜单成了我们的唯一选择,在 ...
- Android开发技巧——高亮的用户操作指南
Android开发技巧--高亮的用户操作指南 2015-12-15补记: 发现使用PopupWindow进行遮罩层的显示,在华为P7上会有问题.具体表现为:画出来的高亮部分会偏下.原因为:通过view ...
- Android开发技巧——自定义控件之增加状态
Android开发技巧--自定义控件之增加状态 题外话 这篇本该是上周四或上周五写的,无奈太久没写博客,前几段把我的兴头都用完了,就一拖再拖,直到今天.不想把这篇拖到下个月,所以还是先硬着头皮写了. ...
- Android开发技巧——自定义控件之使用style
Android开发技巧--自定义控件之使用style 回顾 在上一篇<Android开发技巧--自定义控件之自定义属性>中,我讲到了如何定义属性以及在自定义控件中获取这些属性的值,也提到了 ...
- Android开发技巧——自定义控件之自定义属性
Android开发技巧--自定义控件之自定义属性 掌握自定义控件是很重要的,因为通过自定义控件,能够:解决UI问题,优化布局性能,简化布局代码. 上一篇讲了如何通过xml把几个控件组织起来,并继承某个 ...
- Android开发技巧——自定义控件之组合控件
Android开发技巧--自定义控件之组合控件 我准备在接下来一段时间,写一系列有关Android自定义控件的博客,包括如何进行各种自定义,并分享一下我所知道的其中的技巧,注意点等. 还是那句老话,尽 ...
- Android开发技巧——写一个StepView
在我们的应用开发中,有些业务流程会涉及到多个步骤,或者是多个状态的转化,因此,会需要有相关的设计来展示该业务流程.比如<停车王>应用里的添加车牌的步骤. 通常,我们会把这类控件称为&quo ...
随机推荐
- jQuery属性选择器.attr()和.prop()两种方法
在判断表单单选框是否被选中时,通常会想到使用$('#checkbox').attr('checked')来判断,但在一些情况下,你会发现这种方法并不管用,得到的是undefined. 原来jQuery ...
- SQL 分组后获取其中一个字段最大值的整条记录
--有id,name,createDate的一张表testTable--根据name分组,获取每组中createDate最大的那条记录(整条)查询出来------------------------- ...
- VCF (Variant Call Format)格式详解
文章来源:http://www.cnblogs.com/emanlee/p/4562064.html VCF文件示例(VCFv4.2) ##fileformat=VCFv4.2 ##fileDate= ...
- Codeforces #270 D. Design Tutorial: Inverse the Problem
http://codeforces.com/contest/472/problem/D D. Design Tutorial: Inverse the Problem time limit per t ...
- C语言的源程序字符集与执行字符集
我们程序文件的字符集就是我们写出来的.c扩展名的文件的字符集,这里用的是系统默认的 ANSI 字符集,如下图: 上面的字符集我们不关心,我们关心的是 源程序的字符集 和程序的 执行字符集 ,源程序的字 ...
- .Net的要知道的一些事
1.什么是.NET?什么是CLI?什么是CLR?IL是什么?JIT是什么,它是如何工作的?GC是什么,简述一下GC的工作方式? .Net是微软推出的框架 CLI是公共语言接口(规范) CLR是公共语言 ...
- jQuery.extend()介绍
},{name:"Jerry",sex:"Boy"}) 得到的Result结果是: result={name:"Jerry",age:21, ...
- LazyLoad.js及scrollLoading.js
http://blog.csdn.net/ning109314/article/details/7042829 目前图片延迟加载主要分两大块,一是触发加载(根据滚动条位置加载图片):二是自动预加载(加 ...
- 160809225-叶桦汀《C语言程序设计》实验报告
#include<stdio.h> int main() { int a,b,c,t; printf("请输入三个整数"); scanf("%d%d%d&qu ...
- OpenGL基础图形的绘制
例一:绘制五角星 设五角星5个顶点分别为ABCDE,顶点到坐标轴原点距离为r,ABCDE各点用r表示,分别为 A(0,r); B(-r*sin(2/5*Pi),r*cos(2/5*Pi)); C(-r ...