简单介绍

关于运行时权限的说法,早在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. 来聊聊apply和call

    今天在群里讨论的时候,看到有人问apply怎么使用,突然想起自己刚接触这个方法的时候,也是一样的摸不着头脑. 记得当时上网看了很多讲解,可实际用的时候还是感觉有些蒙蒙哒orz.... 后来想一想,也许 ...

  2. HDOJ 4497 GCD and LCM

    组合数学 GCD and LCM Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) ...

  3. Java中将unix时间戳转化为正常显示时间

    在unix中时间戳是一串数字表示的,使用起来非常不方便,转化方式如下: //Convert Unix timestamp to normal date style public String Time ...

  4. Mac OS 中的 Python(和 NumPy)开发环境设置

    http://www.python()tab.com/html/2013/pythonjichu_1010/582.html ()需要删除

  5. 【C语言入门教程】4.2 二维数组

    C 语言允许使用多维数组,即使用多组小标的数组,二维数组是最常用的多维数组.多维数组在内存中存放数据的顺序与一维数组相同,使用连续的存储单元. 4.2.1 二维数组的一般形式 二维数组的一般声明形式为 ...

  6. JS中的prototype(原文地址:http://www.cnblogs.com/yjf512/archive/2011/06/03/2071914.html)

    JS中的phototype是JS中比较难理解的一个部分 本文基于下面几个知识点: 1 原型法设计模式 在.Net中可以使用clone()来实现原型法 原型法的主要思想是,现在有1个类A,我想要创建一个 ...

  7. leetcode 82. Remove Duplicates from Sorted List II

    Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numb ...

  8. [BZOJ3611][Heoi2014]大工程

    [BZOJ3611][Heoi2014]大工程 试题描述 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道.  我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上.  在 ...

  9. js 判断鼠标进去方向

    function fx(id){ var obj= document.getElementById(id); var fun=function(e){ var w=obj.offsetWidth; v ...

  10. Android菜单Menu的创建

    在res目录下的menu文件夹下创建一个main.xml文件,内容如下: <?xml version="1.0" encoding="utf-8"?> ...