简单介绍

关于运行时权限的说法,早在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( )获取需要进行检测的权限数组,检查相关权限是否授权,如果未授权则开始申请权限

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

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

  1. /**
  2. * 权限授权结果回调
  3. *
  4. * @param requestCode
  5. * @param permissions
  6. * @param paramArrayOfInt
  7. */
  8. @Override
  9. public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
  10. @NonNull int[] paramArrayOfInt) {
  11. if (requestCode == REQUEST_CODE_PERMISSON) {
  12. if (!verifyPermissions(paramArrayOfInt)) {
  13. permissionGrantedFail();
  14. showTipsDialog();
  15. isNeedCheckPermission = false;
  16. } else permissionGrantedSuccess();
  17. }
  18. }

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

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

  1. @Override
  2. public String[] getNeedPermissions() {
  3. return new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
  4. }
  5.  
  6. @Override
  7. protected void permissionGrantedSuccess() {
  8.  
  9. }
  10.  
  11. @Override
  12. protected void permissionGrantedFail() {
  13. }

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

封装类的完整代码如下:

  1. /**
  2. * Created by chenyk on 2016/9/28.
  3. * 检查相关权限基类,适用于android 6.0 运行时权限
  4. * 使用方法:需要运行时权限的activity继承此类
  5. */
  6. public abstract class BaseCheckPermissionActivity extends NeedBackActivity
  7. implements OnRequestPermissionsResultCallback {
  8. private static final int REQUEST_CODE_PERMISSON = 2020; //权限请求码
  9.  
  10. private boolean isNeedCheckPermission = true; //判断是否需要检测,防止无限弹框申请权限
  11.  
  12. @Override
  13. protected void onResume() {
  14. super.onResume();
  15. if (isNeedCheckPermission) {
  16. checkAllNeedPermissions();
  17. }
  18. }
  19.  
  20. /**
  21. * 检查所有权限,无权限则开始申请相关权限
  22. */
  23. protected void checkAllNeedPermissions() {
  24. if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return;
  25. List<String> needRequestPermissonList = getDeniedPermissions(getNeedPermissions());
  26. if (null != needRequestPermissonList && needRequestPermissonList.size() > 0) {
  27. ActivityCompat.requestPermissions(this, needRequestPermissonList.toArray(
  28. new String[needRequestPermissonList.size()]), REQUEST_CODE_PERMISSON);
  29. }
  30. }
  31.  
  32. /**
  33. * 获取权限集中需要申请权限的列表
  34. *
  35. * @param permissions
  36. * @return
  37. */
  38. private List<String> getDeniedPermissions(String[] permissions) {
  39. List<String> needRequestPermissonList = new ArrayList<>();
  40. for (String permission : permissions) {
  41. if (ContextCompat.checkSelfPermission(this, permission) !=
  42. PackageManager.PERMISSION_GRANTED ||
  43. ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) {
  44. needRequestPermissonList.add(permission);
  45. }
  46. }
  47. return needRequestPermissonList;
  48. }
  49.  
  50. /**
  51. * 所有权限是否都已授权
  52. *
  53. * @return
  54. */
  55. protected boolean isGrantedAllPermission() {
  56. List<String> needRequestPermissonList = getDeniedPermissions(getNeedPermissions());
  57. return needRequestPermissonList.size() == 0;
  58. }
  59.  
  60. /**
  61. * 权限授权结果回调
  62. *
  63. * @param requestCode
  64. * @param permissions
  65. * @param paramArrayOfInt
  66. */
  67. @Override
  68. public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
  69. @NonNull int[] paramArrayOfInt) {
  70. if (requestCode == REQUEST_CODE_PERMISSON) {
  71. if (!verifyPermissions(paramArrayOfInt)) {
  72. permissionGrantedFail();
  73. showTipsDialog();
  74. isNeedCheckPermission = false;
  75. } else permissionGrantedSuccess();
  76. }
  77. }
  78.  
  79. /**
  80. * 检测所有的权限是否都已授权
  81. *
  82. * @param grantResults
  83. * @return
  84. */
  85. private boolean verifyPermissions(int[] grantResults) {
  86. for (int grantResult : grantResults) {
  87. if (grantResult != PackageManager.PERMISSION_GRANTED) {
  88. return false;
  89. }
  90. }
  91. return true;
  92. }
  93.  
  94. /**
  95. * 显示提示对话框
  96. */
  97. protected void showTipsDialog() {
  98. new AlertDialog.Builder(this).setTitle("提示信息").setMessage("当前应用缺少" + getDialogTipsPart()
  99. + "权限,该功能暂时无法使用。如若需要,请单击【确定】按钮前往设置中心进行权限授权。")
  100. .setNegativeButton("取消", new DialogInterface.OnClickListener() {
  101. @Override
  102. public void onClick(DialogInterface dialog, int which) {
  103. finish();
  104. }
  105. })
  106. .setPositiveButton("确定", new DialogInterface.OnClickListener() {
  107. @Override
  108. public void onClick(DialogInterface dialog, int which) {
  109. startAppSettings();
  110. }
  111. }).show();
  112. }
  113.  
  114. /**
  115. * 启动当前应用设置页面
  116. */
  117. private void startAppSettings() {
  118. Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
  119. intent.setData(Uri.parse("package:" + getPackageName()));
  120. startActivity(intent);
  121. }
  122.  
  123. /**
  124. * 获取弹框提示部分内容
  125. *
  126. * @return
  127. */
  128. protected String getDialogTipsPart() {
  129. return "必要";
  130. }
  131.  
  132. /**
  133. * 获取需要进行检测的权限数组
  134. */
  135. protected abstract String[] getNeedPermissions();
  136.  
  137. /**
  138. * 权限授权成功
  139. */
  140. protected abstract void permissionGrantedSuccess();
  141.  
  142. /**
  143. * 权限授权失败
  144. */
  145. 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. jQuery属性选择器.attr()和.prop()两种方法

    在判断表单单选框是否被选中时,通常会想到使用$('#checkbox').attr('checked')来判断,但在一些情况下,你会发现这种方法并不管用,得到的是undefined. 原来jQuery ...

  2. SQL 分组后获取其中一个字段最大值的整条记录

    --有id,name,createDate的一张表testTable--根据name分组,获取每组中createDate最大的那条记录(整条)查询出来------------------------- ...

  3. VCF (Variant Call Format)格式详解

    文章来源:http://www.cnblogs.com/emanlee/p/4562064.html VCF文件示例(VCFv4.2) ##fileformat=VCFv4.2 ##fileDate= ...

  4. 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 ...

  5. C语言的源程序字符集与执行字符集

    我们程序文件的字符集就是我们写出来的.c扩展名的文件的字符集,这里用的是系统默认的 ANSI 字符集,如下图: 上面的字符集我们不关心,我们关心的是 源程序的字符集 和程序的 执行字符集 ,源程序的字 ...

  6. .Net的要知道的一些事

    1.什么是.NET?什么是CLI?什么是CLR?IL是什么?JIT是什么,它是如何工作的?GC是什么,简述一下GC的工作方式? .Net是微软推出的框架 CLI是公共语言接口(规范) CLR是公共语言 ...

  7. jQuery.extend()介绍

    },{name:"Jerry",sex:"Boy"}) 得到的Result结果是: result={name:"Jerry",age:21, ...

  8. LazyLoad.js及scrollLoading.js

    http://blog.csdn.net/ning109314/article/details/7042829 目前图片延迟加载主要分两大块,一是触发加载(根据滚动条位置加载图片):二是自动预加载(加 ...

  9. 160809225-叶桦汀《C语言程序设计》实验报告

    #include<stdio.h> int main() { int a,b,c,t; printf("请输入三个整数"); scanf("%d%d%d&qu ...

  10. OpenGL基础图形的绘制

    例一:绘制五角星 设五角星5个顶点分别为ABCDE,顶点到坐标轴原点距离为r,ABCDE各点用r表示,分别为 A(0,r); B(-r*sin(2/5*Pi),r*cos(2/5*Pi)); C(-r ...