Android 6.0 权限管理

Android 6.0 权限管理

Android

permission

    • 运行时权限(Runtime permission)
    • 旧版兼容
    • 6.0权限弹框的两种模式
    • 6.0之后的权限分类
      • Normal permissions(普通权限)
      • Dangerous permissions(危险权限)
    • 运行时权限请求的基本步骤
    • 权限请求策略

运行时权限(Runtime permission)

android的权限系统一直是首要的安全概念,因为这些权限只在安装的时候被询问一次。一旦安装了,app可以在用户毫不知晓的情况下访问权限内的所有东西。

这是极其危险的事情

所以,在Android M 权限请求设计改版了,有点类似iOS的权限请求

1461651981945.jpg

在android6.0棉花糖,app将不会在安装的时候授予权限。取而代之的是,app不得不在运行时一个一个询问用户授予权限。

注意权限询问对话框不会自己弹出来。开发者不得不自己调用。如果开发者要调用的一些函数需要某权限而用户又拒绝授权的话,函数将抛出异常甚至导致程序崩溃.

旧版兼容

为了与旧版本兼容,比如你的 build.gradle 中的 targetSdkVersion 设置为 23 之前,比如22.

也能在Android6.0 的手机上面跑,并且权限请求机制使用6.0之前的 安装时请求 的模式.

吐槽一下: Excuse Me? 这到底是兼容还是漏洞... targetSdkVersion 设置为23以前,不让跑6.0不是更合理?

可能处于市场应用的API版本考虑,不兼容估计大部分应用都不能跑6.0

所以,如果你觉得运行时弹出权限框让用户勾选很不友好,那么就取巧使用targetSdkVersion <23 吧,但这绝对不是长久之计...(丑陋...)

  1. android {


  2. compileSdkVersion 23 

  3. buildToolsVersion "23.0.2" 


  4. defaultConfig { 

  5. minSdkVersion 8 

  6. targetSdkVersion 22 

  7. versionCode 1 

  8. versionName "1.0" 



  9. buildTypes { 

  10. release { 

  11. minifyEnabled false 

  12. proguardFiles getDefaultProguardFile(‘proguard-android.txt‘), ‘proguard-rules.pro‘ 







1461662965441.jpg

6.0权限弹框的两种模式

1.初次请求,弹出对话框叫你勾选

1461654947945.jpg

2,第二次请求之后,弹出对话框,出现不再提醒字样

1461655014689.jpg

当用户点击了不再提醒,你再次请求权限的时候,就不会弹出对话框,所以这时,你需要根据需求另做处理

下面会如何处理

6.0之后的权限分类

分为两类 Normal permissions 和 Dangerous permissions

Normal permissions(普通权限)

只需要在xml中申请就可以了,与6.0之前没什么区别

包括的权限有

  1. android.permission.ACCESS_LOCATION_EXTRA_COMMANDS


  2. android.permission.ACCESS_NETWORK_STATE 

  3. android.permission.ACCESS_NOTIFICATION_POLICY 

  4. android.permission.ACCESS_WIFI_STATE 

  5. android.permission.ACCESS_WIMAX_STATE 

  6. android.permission.BLUETOOTH 

  7. android.permission.BLUETOOTH_ADMIN 

  8. android.permission.BROADCAST_STICKY 

  9. android.permission.CHANGE_NETWORK_STATE 

  10. android.permission.CHANGE_WIFI_MULTICAST_STATE 

  11. android.permission.CHANGE_WIFI_STATE 

  12. android.permission.CHANGE_WIMAX_STATE 

  13. android.permission.DISABLE_KEYGUARD 

  14. android.permission.EXPAND_STATUS_BAR 

  15. android.permission.FLASHLIGHT 

  16. android.permission.GET_ACCOUNTS 

  17. android.permission.GET_PACKAGE_SIZE 

  18. android.permission.INTERNET 

  19. android.permission.KILL_BACKGROUND_PROCESSES 

  20. android.permission.MODIFY_AUDIO_SETTINGS 

  21. android.permission.NFC 

  22. android.permission.READ_SYNC_SETTINGS 

  23. android.permission.READ_SYNC_STATS 

  24. android.permission.RECEIVE_BOOT_COMPLETED 

  25. android.permission.REORDER_TASKS 

  26. android.permission.REQUEST_INSTALL_PACKAGES 

  27. android.permission.SET_TIME_ZONE 

  28. android.permission.SET_WALLPAPER 

  29. android.permission.SET_WALLPAPER_HINTS 

  30. android.permission.SUBSCRIBED_FEEDS_READ 

  31. android.permission.TRANSMIT_IR 

  32. android.permission.USE_FINGERPRINT 

  33. android.permission.VIBRATE 

  34. android.permission.WAKE_LOCK 

  35. android.permission.WRITE_SYNC_SETTINGS 

  36. com.android.alarm.permission.SET_ALARM 

  37. com.android.launcher.permission.INSTALL_SHORTCUT 

  38. com.android.launcher.permission.UNINSTALL_SHORTCUT 

其实不需要记,记住哪些是危险权限就是了

Dangerous permissions(危险权限)

危险权限,需要在运行时请求.

注意: 危险权限是按组来分的,所以,当你申请了多个同组的危险权限时,运行时只需要申请一个就行

例如:

  1. <!-- 电话 -->


  2. <uses-permission android:name="android.permission.READ_CALL_LOG" /> 

  3. <uses-permission android:name="android.permission.READ_PHONE_STATE" /> 

  4. <uses-permission android:name="android.permission.CALL_PHONE" /> 

  5. <uses-permission android:name="android.permission.WRITE_CALL_LOG" /> 

  6. <uses-permission android:name="android.permission.USE_SIP" /> 

  7. <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" /> 

  8. <uses-permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL" /> 

你申请了关于电话的那么多权限,在动态申请的时候,它只会弹出

1461654947945.jpg

这一个权限框

所以,这是一个权限组的概念,运行时选择你申请的同组权限的一个就行

目前所有的危险权限组集合

  1. <!-- Dangerous Permissions. -->


  2. <!-- 联系人 --> 

  3. <uses-permission android:name="android.permission.WRITE_CONTACTS" /> 

  4. <uses-permission android:name="android.permission.GET_ACCOUNTS" /> 

  5. <uses-permission android:name="android.permission.READ_CONTACTS" /> 


  6. <!-- 录音 --> 

  7. <uses-permission android:name="android.permission.RECORD_AUDIO" /> 


  8. <!-- 电话 --> 

  9. <uses-permission android:name="android.permission.READ_CALL_LOG" /> 

  10. <uses-permission android:name="android.permission.READ_PHONE_STATE" /> 

  11. <uses-permission android:name="android.permission.CALL_PHONE" /> 

  12. <uses-permission android:name="android.permission.WRITE_CALL_LOG" /> 

  13. <uses-permission android:name="android.permission.USE_SIP" /> 

  14. <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" /> 

  15. <uses-permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL" /> 


  16. <!-- 日历 --> 

  17. <uses-permission android:name="android.permission.READ_CALENDAR" /> 

  18. <uses-permission android:name="android.permission.WRITE_CALENDAR" /> 


  19. <!-- 相机 --> 

  20. <uses-permission android:name="android.permission.CAMERA" /> 


  21. <!-- 传感器 --> 

  22. <uses-permission android:name="android.permission.BODY_SENSORS" /> 


  23. <!-- 定位 --> 

  24. <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> 

  25. <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> 


  26. <!-- 存储 --> 

  27. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 

  28. <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> 


  29. <!-- 短信 --> 

  30. <uses-permission android:name="android.permission.READ_SMS" /> 

  31. <uses-permission android:name="android.permission.RECEIVE_WAP_PUSH" /> 

  32. <uses-permission android:name="android.permission.RECEIVE_MMS" /> 

  33. <uses-permission android:name="android.permission.RECEIVE_SMS" /> 

  34. <uses-permission android:name="android.permission.SEND_SMS" /> 

对应的java code

  1. // 联系人


  2. Manifest.permission.WRITE_CONTACTS, 

  3. Manifest.permission.GET_ACCOUNTS, 

  4. Manifest.permission.READ_CONTACTS, 


  5. // 电话 

  6. Manifest.permission.READ_CALL_LOG, 

  7. Manifest.permission.READ_PHONE_STATE, 

  8. Manifest.permission.CALL_PHONE, 

  9. Manifest.permission.WRITE_CALL_LOG, 

  10. Manifest.permission.USE_SIP, 

  11. Manifest.permission.PROCESS_OUTGOING_CALLS, 

  12. Manifest.permission.ADD_VOICEMAIL, 


  13. // 日历 

  14. Manifest.permission.READ_CALENDAR, 

  15. Manifest.permission.WRITE_CALENDAR, 


  16. // 相机 

  17. Manifest.permission.CAMERA, 


  18. // 传感器 

  19. Manifest.permission.BODY_SENSORS, 


  20. // 定位 

  21. Manifest.permission.ACCESS_FINE_LOCATION, 

  22. Manifest.permission.ACCESS_COARSE_LOCATION, 


  23. // 存储 

  24. Manifest.permission.READ_EXTERNAL_STORAGE, 

  25. Manifest.permission.WRITE_EXTERNAL_STORAGE, 


  26. // 录音 

  27. Manifest.permission.RECORD_AUDIO, 


  28. // 短信 

  29. Manifest.permission.READ_SMS, 

  30. Manifest.permission.RECEIVE_WAP_PUSH, 

  31. Manifest.permission.RECEIVE_MMS, 

  32. Manifest.permission.RECEIVE_SMS, 

  33. Manifest.permission.SEND_SMS, 

运行时权限请求的基本步骤

1.在xml中注册

2. 运行时请求权限

以下是权限检查的帮助类

  1. /**


  2. * 检查权限是否已请求到 (6.0) 

  3. */ 

  4. public void checkPermissions(String... permissions) { 

  5. // 版本兼容 

  6. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M 

  7. // 判断缺失哪些必要权限 

  8. && lacksPermissions(permissions)) { 

  9. // 如果缺失,则申请 

  10. requestPermissions(permissions); 






  11. /** 

  12. * 判断是否缺失权限集合中的权限 

  13. */ 

  14. private boolean lacksPermissions(String... permissions) { 

  15. for (String permission : permissions) { 

  16. if (lacksPermission(permission)) { 

  17. return true; 





  18. return false; 




  19. /** 

  20. * 判断是否缺少某个权限 

  21. */ 

  22. private boolean lacksPermission(String permission) { 

  23. return ContextCompat.checkSelfPermission(context, permission) == 

  24. PackageManager.PERMISSION_DENIED; 




  25. /** 

  26. * 请求权限 

  27. */ 

  28. private void requestPermissions(String... permissions) { 

  29. ActivityCompat.requestPermissions(context, permissions, PERMISSION_REQUEST_CODE); 




  30. /** 

  31. * 启动应用的设置,进入手动配置权限页面 

  32. */ 

  33. private void startAppSettings() { 

  34. Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); 

  35. Uri uri = Uri.fromParts("package", context.getPackageName(), null); 

  36. intent.setData(uri); 

  37. context.startActivity(intent); 



注意: 其中的 requestPermissions 方法,它会弹出权限提示框( 没有点击不再提醒的话 ),然后调用 public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) 方法,该方法在Activity或者Fragment中回调

3.在onRequestPermissionsResult回调中处理

在 public void onRequestPermissionsResult() 方法中,你可以捕获到用于是点击了 不再提醒 还是 拒绝 ,然后做出不同的操作..

  1. @Override


  2. public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 

  3. // 版本兼容 

  4. if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M || 

  5. requestCode != PermissionsChecker.PERMISSION_REQUEST_CODE) 

  6. return; 


  7. for (int i = 0, len = permissions.length; i < len; i++) { 

  8. String permission = permissions[i]; 

  9. // 缺失的权限 

  10. if (grantResults[i] == PackageManager.PERMISSION_DENIED) { 

  11. boolean showRationale = shouldShowRequestPermissionRationale(permission); 

  12. if (!showRationale) { 

  13. // 用户点击不再提醒 

  14. // TODO 

  15. break; 

  16. } else {  

  17. // 用户点击了取消... 

  18. // possibly check more permissions...  









权限请求策略

下面提供一种我认为还不错的策略

在需要某权限的Activity的 onStrart() 中去请求权限

在 onRequestPermissionsResult 回调中,如果用户点击了拒绝,则继续请求权限

如果用户点击了不再提醒,则弹出自定义对话框,引导用户手动去开启权限,如果用户不授权,则退出当前页面

注意:适用于没有权限就无法使用该功能的情况

1461661615410.jpg

Activity代码

  1. public class BaseActivity extends AppCompatActivity {


  2. private static final String TAG = "BaseActivity"; 

  3. private PermissionsChecker checker; 


  4. @Override 

  5. protected void onCreate(@Nullable Bundle savedInstanceState) { 

  6. super.onCreate(savedInstanceState); 

  7. checker = new PermissionsChecker(this); 




  8. public PermissionsChecker getChecker() { 

  9. return checker; 




  10. /** 

  11. * 在该声明周期,检查权限申请情况 

  12. */ 

  13. @Override 

  14. protected void onStart() { 

  15. super.onStart(); 

  16. checker.checkPermissions(PermissionsChecker.PERMISSIONS); 




  17. /** 

  18. * 请求权限检查完后回调的结果 



  19. * @param requestCode . 

  20. * @param permissions 所请求的权限 

  21. * @param grantResults . 

  22. */ 

  23. @TargetApi(Build.VERSION_CODES.M) 

  24. @Override 

  25. public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 

  26. if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M || 

  27. requestCode != PermissionsChecker.PERMISSION_REQUEST_CODE) 

  28. return; 



  29. for (int i = 0, len = permissions.length; i < len; i++) { 

  30. String permission = permissions[i]; 

  31. if (grantResults[i] == PackageManager.PERMISSION_DENIED) { 

  32. boolean showRationale = shouldShowRequestPermissionRationale(permission); 

  33. if (!showRationale) { 

  34. // 用户点击不再提醒,弹出权限框,引导其手动开启权限 

  35. checker.showMissingPermissionDialog(); 

  36. break; 

  37. } else { 

  38. // 用户点击取消,继续提示 

  39. checker.checkPermissions(PermissionsChecker.PERMISSIONS); 

  40. break; 












时间: 2024-12-10 18:17:30

Android 6.0 权限管理的相关文章

Android开发——Android 6.0权限管理机制详解

0.前言 最近在研究所实习,我负责维护Android手机取证项目的Android客户端,有客户反映我们的APP在Android6.0无响应,经过调试发现SD卡读写权限权限被拒绝.但明明是在AndroidManifest.xml文件中声明过的.查了很多资料才知道Android6.0的很多权限申请机制发生了改变,可以说是Android6.0在安全机制上更进了一步吧,因此写下这篇文章以记录. 注:在运行程序时,对于某些权限向用户询问申请(后面会详细地讲)时因为我们知道客户在我们APP中不会点"拒绝&q

Android 6.0权限管理的解析与实战

一.引言 随着Android6.0发布,系统增加了一些新的特性和功能.这次的发布介绍了一种新的权限机制.用户可以在运行时直接管理应用程序的权限.这个功能提升了权限控制的可见性和可控性.同时简化了安装和自动升级过程,用户可以单独撤销或者授予应用程序某项权限,对应用拥有更多的控制权. 二.Android 6.0权限机制 当你应用程序target是Android 6.0及以上(API level 23),确保在运行时检查和请求权限.为了确定你的app是否授予某个权限,通过checkSelfPermis

项目中处理android 6.0权限管理问题

android 6.0对于权限管理比较收紧,因此在适配android 6.0的时候就很有必要考虑一些权限管理的问题. 如果你没适配6.0的设备并且权限没给的话,就会出现类似如下的问题: java.lang.SecurityException: Permission Denial: starting Intent { act=android.intent.action.CALL dat=tel:xxxxxxxxxxx cmp=com.android.server.telecom/.componen

Android_设备隐私获取,忽略6.0权限管理

1.前言 (1).由于MIUI等部分国产定制系统也有权限管理,没有相关api,故无法判断用户是否允许获取联系人等隐私.在Android 6.0之后,新增权限管理可以通过官方api判断用户的运行状态: (2).我们指定targetSdkVersion为23或者之后我们还需要在运行时请求这些所需的权限.这很重要,因为已经出现了很多开发者把targetSdkVersion飙到了最新,然后发现自己的app疯狂的崩溃,这是由于他们没有实现执行运行时权限请求的代码.当你已经把一个targeting API

Android中的权限管理(基于uid gid gids setUid)

我们首先来说一下传统的Linux基于uid,gid的权限管理机制: 1.用户的uid gid gids: Ubuntu操作系统当前登陆的用户是jltxgcy,那么该用户的uid为jltxgcy,gid也是jltxgcy,那么gids怎么查看呢? 答案是使用命令:cat /etc/group | grep jltxgcy.如下图: 用户的gids的名字为adm,dialout,cdrom,plugdev,lpadmin,admin,sambashare.此本分请参考linux用户组./etc/gr

Android中的权限管理(基于Permission ProtectionLevel)

1.什么是protectionlevel呢? 我们经常在AndroidManifest中使用权限,如果我们想让应用程序可以发短信,那么应该这样写: <uses-permission android:name="android.permission.SEND_SMS" /> 那么这个权限的定义是在哪里定义的呢?如下: frameworks/base/core/res/AndroidManifest.xml <permission android:name="a

Android获取设备隐私 忽略6.0权限管理

1.前言 (1).由于MIUI等部分国产定制系统也有权限管理,没有相关api,故无法判断用户是否允许获取联系人等隐私.在Android 6.0之后,新增权限管理可以通过官方api判断用户的运行状态: (2).我们指定targetSdkVersion为23或者之后我们还需要在运行时请求这些所需的权限.这很重要,因为已经出现了很多开发者把targetSdkVersion飙到了最新,然后发现自己的app疯狂的崩溃,这是由于他们没有实现执行运行时权限请求的代码.当你已经把一个targeting API

Android拍照,相册选择图片以及Android6.0权限管理

概述 在android开发过程中,拍照或者从相册中选择图片是很常见的功能.下面要说得这个案例比较简单,用户点击按钮选择拍照或者打开相册选择图片,然后将选中的图片显示在手机上.android6.0后,推出了动态权限管理.以往我们将涉及到的权限全部写在清单文件中,只要用户安装了该程序,程序在运行过程中都会获得相应权限.android6.0后,对于一些特别敏感的权限,开发者必须在程序中进行声明.拍照和从相册选择图片都是涉及到用户隐私的敏感权限,必须在程序中进行声明. 大概的流程 创建布局文件,这里不多

Android6.0权限管理以及使用权限该注意的地方

Android 6.0 Marshmallow首次增加了执行时权限管理,这对用户来说,能够更好的了解.控 制 app 涉及到的权限.然而对开发人员来说却是一件比較蛋疼的事情.须要兼容适配,并保证程序功能的正常执行. 什么叫执行时权限管理呢?在Android 6.0以下的系统中,当我们在安装应用的时候,该应用就会提示我们这个应用所须要的权限,假设你要安装.那就必须允许赋予全部权限,可是假设不允许,那就仅仅能取消安装了,有点流氓.并且安装完后,你不能够收回这个权限. 而6.0就做到了执行时权限管理.