当前位置:   article > 正文

Android 运行时权限处理解析_android.permission-group.storage

android.permission-group.storage

一.Android6.0权限改变

1. Android6.0版本之前的权限是写在配置文件AndroidManifest.xml中的,Android app在安装的时候Android系统检测配置文件的权限给用户提示app需要的权限,用户可以点击接受和拒绝。但是这种方式用户在Androidapp的时候并不知道这个权限用在哪里有啥危害。于是Android6.0开始改变权限申请的方式,出现了权限组和动态申请权限。

2.从设计来看我们可以想象设计一套这样的功能。一般需要定义一套权限规则,二设计一套权限检测的方法把用户定义的权限解析以及用户申请权限的方法,三设计一个用户操作权限的授权的功能,第四设计一套权限存储更新的功能。这样想就和服务器一样的功能用户需要什么功能通过协议去请求检测这样的功能是不是满足需要功能的权限。

3.从系统底层来看。我们看源码的地址是:http://androidxref.com/9.0.0_r3/xref/frameworks/

从系统源码来看我们可以从上面的功能分析设计上来找对应的模块。权限定义模块,权限检测模块,用户授权模块,权限存储。

1.权限定义模块

http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/res/AndroidManifest.xml

  1. 687 <!-- Allows an application to send SMS messages.
  2. 688 <p>Protection level: dangerous
  3. 689 -->
  4. 690 <permission android:name="android.permission.SEND_SMS"
  5. 691 android:permissionGroup="android.permission-group.SMS"
  6. 692 android:label="@string/permlab_sendSms"
  7. 693 android:description="@string/permdesc_sendSms"
  8. 694 android:permissionFlags="costsMoney"
  9. 695 android:protectionLevel="dangerous" />
  10. 696
  11. 697 <!-- Allows an application to receive SMS messages.
  12. 698 <p>Protection level: dangerous
  13. 699 -->
  14. 700 <permission android:name="android.permission.RECEIVE_SMS"
  15. 701 android:permissionGroup="android.permission-group.SMS"
  16. 702 android:label="@string/permlab_receiveSms"
  17. 703 android:description="@string/permdesc_receiveSms"
  18. 704 android:protectionLevel="dangerous"/>
  19. 705
  20. 706 <!-- Allows an application to read SMS messages.
  21. 707 <p>Protection level: dangerous
  22. 708 -->
  23. 709 <permission android:name="android.permission.READ_SMS"
  24. 710 android:permissionGroup="android.permission-group.SMS"
  25. 711 android:label="@string/permlab_readSms"
  26. 712 android:description="@string/permdesc_readSms"
  27. 713 android:protectionLevel="dangerous" />

protectionLevel共有5个选项值分别为signature,system,dangerous,normal,development,简单介绍下这5个值 
System permissions: 表示如果想获取该权限必须为系统应用 

Normal permissions:只需要在AndroidManifest.xml 中声明,如INTERNET,WAKE_LOCK等

Signature permissions:申请该权限的应用和定义该权限的应用有相同签名时,这个权限才会被授予,一些Signature permissions不能被三方应用使用

Dangerous permissions:需要申请运行时权限

Special permissions:如SYSTEM_ALERT_WINDOW需要应用发送Settings.ACTION_MANAGE_OVERLAY_PERMISSION intent去提示用户是否开启该权限

任何一个权限都有自己的所属的权限组。同一组的任何一个权限被授权了,其他权限也自动被授权。

如:android.permission.READ_EXTERNAL_STORAGE和android.permission.WRITE_EXTERNAL_STORAGE都在android.permission-group.STORAGE这个权限组里面,申请权限时同意了组中的一个另一个同时也同意了。

2.权限检测功能模块pms ,用户动态权限检测

 

3.用户权限授权模块GrantPermissionsActivity

https://www.androidos.net.cn/android/6.0.1_r16/xref/packages/apps/PackageInstaller/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java

1.系统中定义。

2.调用流程

3.全透明GrantPermissionsActivity源码解析

 

4.权限更新模块

 

5.权限adb命令调试查看:

adb shell dumpsys package + 包名

6.特殊的需求处理。

比如hook住权限调用过程,更改弹窗显示或者拦截显示。

 

二.封装方案

1.通过fragment中带有权限请求和回调的方法进行请求工具封装

1.传入参数

1.上下文  activity 或者fragment

2.请求的权限的列表

3.结果返回后的接口

2.工具封装

1.封装一个请求权限Fragment在fragment中请求

  1. public class PermissionFragment extends Fragment {
  2. //requestCode
  3. private static final int PERMISSIONS_REQUEST_CODE = 1;
  4. private PermissionListener listener;
  5. public void setListener(PermissionListener listener) {
  6. this.listener = listener;
  7. }
  8. @Override
  9. public void onCreate(@Nullable Bundle savedInstanceState) {
  10. super.onCreate(savedInstanceState);
  11. setRetainInstance(true);
  12. }
  13. @TargetApi(Build.VERSION_CODES.M)
  14. public void requestPermissions(@NonNull String[] permissions) {
  15. List<String> requestPermissionList = new ArrayList<>();
  16. //找出所有未授权的权限
  17. for (String permission : permissions) {
  18. if (ContextCompat.checkSelfPermission(getContext(), permission) != PackageManager.PERMISSION_GRANTED) {
  19. requestPermissionList.add(permission);
  20. }
  21. }
  22. if (requestPermissionList.isEmpty()) {
  23. //已经全部授权
  24. permissionAllGranted();
  25. } else {
  26. //申请授权
  27. requestPermissions(requestPermissionList.toArray(new String[requestPermissionList.size()]), PERMISSIONS_REQUEST_CODE);
  28. }
  29. }
  30. @Override
  31. public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
  32. super.onRequestPermissionsResult(requestCode, permissions, grantResults);
  33. if (requestCode != PERMISSIONS_REQUEST_CODE) {
  34. return;
  35. }
  36. if (grantResults.length > 0) {
  37. List<String> deniedPermissionList = new ArrayList<>();
  38. for (int i = 0; i < grantResults.length; i++) {
  39. if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
  40. deniedPermissionList.add(permissions[i]);
  41. }
  42. }
  43. if (deniedPermissionList.isEmpty()) {
  44. //已经全部授权
  45. permissionAllGranted();
  46. } else {
  47. //勾选了对话框中”Don’t ask again”的选项, 返回false
  48. for (String deniedPermission : deniedPermissionList) {
  49. boolean flag = shouldShowRequestPermissionRationale(deniedPermission);
  50. if (!flag) {
  51. //拒绝授权
  52. permissionShouldShowRationale(deniedPermissionList);
  53. return;
  54. }
  55. }
  56. //拒绝授权
  57. permissionHasDenied(deniedPermissionList);
  58. }
  59. }
  60. }
  61. /**
  62. * 权限全部已经授权
  63. */
  64. private void permissionAllGranted() {
  65. if (listener != null) {
  66. listener.onGranted();
  67. }
  68. }
  69. /**
  70. * 权限被拒绝
  71. *
  72. * @param deniedList 被拒绝的权限List
  73. */
  74. private void permissionHasDenied(List<String> deniedList) {
  75. if (listener != null) {
  76. listener.onDenied(deniedList);
  77. }
  78. }
  79. /**
  80. * 权限被拒绝并且勾选了不在询问
  81. *
  82. * @param deniedList 勾选了不在询问的权限List
  83. */
  84. private void permissionShouldShowRationale(List<String> deniedList) {
  85. if (listener != null) {
  86. listener.onShouldShowRationale(deniedList);
  87. }
  88. }
  89. }

2.通过传进来的activity或者fragment上下文生成工具fragment

  1. public class PermissionUtil {
  2. private static final String TAG = PermissionUtil.class.getSimpleName();
  3. private PermissionFragment permissionFragment;
  4. public PermissionUtil(@NonNull FragmentActivity activity) {
  5. permissionFragment = getRxPermissionsActivity(activity);
  6. }
  7. public PermissionUtil(@NonNull Fragment fragment) {
  8. permissionFragment = getRxPermissionsFragment(fragment);
  9. }
  10. private PermissionFragment getRxPermissionsActivity(FragmentActivity activity) {
  11. PermissionFragment fragment = (PermissionFragment) activity.getSupportFragmentManager().findFragmentByTag(TAG);
  12. boolean isNewInstance = fragment == null;
  13. if (isNewInstance) {
  14. fragment = new PermissionFragment();
  15. FragmentManager fragmentManager = activity.getSupportFragmentManager();
  16. fragmentManager.beginTransaction().add(fragment, TAG).commit();
  17. fragmentManager.executePendingTransactions();
  18. }
  19. return fragment;
  20. }
  21. private PermissionFragment getRxPermissionsFragment(Fragment activity) {
  22. PermissionFragment fragment = (PermissionFragment) activity.getChildFragmentManager().findFragmentByTag(TAG);
  23. boolean isNewInstance = fragment == null;
  24. if (isNewInstance) {
  25. fragment = new PermissionFragment();
  26. FragmentManager fragmentManager = activity.getChildFragmentManager();
  27. fragmentManager.beginTransaction().add(fragment, TAG).commit();
  28. fragmentManager.executePendingTransactions();
  29. }
  30. return fragment;
  31. }
  32. /**
  33. * 外部使用 申请权限
  34. *
  35. * @param permissions 申请授权的权限
  36. * @param listener 授权回调的监听
  37. */
  38. public void requestPermissions(String[] permissions, PermissionListener listener) {
  39. permissionFragment.setListener(listener);
  40. permissionFragment.requestPermissions(permissions);
  41. }
  42. }

3.结果返回

请求结果通过接口设计

  1. public interface PermissionListener {
  2. void onGranted();
  3. void onDenied(List<String> deniedPermission);
  4. void onShouldShowRationale(List<String> deniedPermission);
  5. }

4.demo下载地址

github:https://github.com/MatrixSpring/AndroidPermission

 

5.更新支持AndroidX地址:

github:https://github.com/MatrixSpring/AppPermission

 

2.通过activity中带有的权限请求和回调的方法

1.传入参数

2.工具封装

3.结果返回

4.demo下载地址

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/283778
推荐阅读
相关标签
  

闽ICP备14008679号