简单介绍

关于运行时权限的说法,早在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. 终端下使用cocopods

    http://blog.csdn.net/showhilllee/article/details/38398119

  2. StarWind的安装配置

    将安装包拷贝到本地后,执行以下exe文件,默认下一步,直到安装完成. 需汉化版本则将language_chinese.xml文件拷贝到以下路径: C:\Program Files\StarWind S ...

  3. 利用PHP读取文件

    $fp=fopen("D:\\phpStudy\\www\\date\\file\\2.txt","r");if($fp){    while(!feof($f ...

  4. Maven工程中报 Missing artifact jdk.tools:jdk.tools:

    jdk.tools:jdk.tools是与JDK一起分发的一个JAR文件,可以如下方式加入到Maven项目中:<dependency>    <groupId>jdk.tool ...

  5. Spark之命令

    Spark之命令 1.spark运行模式有4种: a.local 多有用测试, b. standalone:spark 集群模式,使用spark自己的调度方式. c. Yarn: 对Mapreduce ...

  6. Hadoop 之Impala

    impala 是基于hive的大数据实时分析查询引擎,直接使用Hive的元数据库metadata意味着impala元数据都存储在hive的metadstore中并且impala兼容hive的 sql解 ...

  7. ajax 请求多张图片数据

    需求分析: 实现对网页上的图片进行显示.由于读取图片名称相同,而图片内容已发生改变.采用网上所用的要求浏览器不缓存的操作不生效 <META http-equiv="Pragma&quo ...

  8. grunt 使用

    grunt 服务端, grunt-cli 客户端 1.grunt 插件安装: package.json, 存放grunt所需插件 { "name": "demo" ...

  9. linux运维人员必会开源运维工具体系

    http://oldboy.blog.51cto.com/2561410/775056

  10. HTTP及状态码汇总

    什么是HTTP: HTTP(HyperText Transfer Protocol超文本传输协议)是互联网上应用最为广泛的一种网络协议.所有的WWW文件都必须遵守这个标准,为了提供一种发布和接收HTM ...