Android踩坑日记:Android动态权限分析和解决方案
来源:互联网 发布:大富豪3.4源码 编辑:程序博客网 时间:2024/06/06 08:29
关于运行时权限
在旧的权限管理系统中,权限仅仅在APP安装时询问一次,用户同意了这些权限App才能安装,APP一旦安装后就可以偷偷做很多不为人知的事情。
我们知道从Android6.0开始,App可以直接安装,在运行时需要用到权限的地方,会一个一个询问用户授予权限,比如照相,写SD卡,读联系人等,系统会弹出一个对话框让用户选择是否授予权限(这个dialog是各个手机厂商定制的,不能由开发者定制),用户可以拒绝,可以在每个APP的权限进行管理
特别注意:这个对话框不是开发者调用某个权限的功能是由系统自动弹出的,而不是由开发者手动调用的。
哪些权限需要动态申请
新的权限策略分为两类:第一类是不涉及用户隐私的,只需要在manifest中声明即可,比如网络,蓝牙,NFC等,第二类是涉及用户隐私信息的,需要用户授权后才可使用的,比如SD卡读写,联系人,短信读写等等
不需要运行时申请的权限:
此类权限都是正常保护的权限,只需要在AndroidManifest.xml中简单声明这些权限即可,安装即授权,不需要每次使用时都检查权限,而且用户不能取消以上授权,除非用户卸载App。
ACCESS_LOCATION_EXTRA_COMMANDSACCESS_NETWORK_STATEACCESS_NOTIFICATION_POLICYACCESS_WIFI_STATEBLUETOOTHBLUETOOTH_ADMINBROADCAST_STICKYCHANGE_NETWORK_STATECHANGE_WIFI_MULTICAST_STATECHANGE_WIFI_STATEDISABLE_KEYGUARDEXPAND_STATUS_BARGET_PACKAGE_SIZEINSTALL_SHORTCUTINTERNETKILL_BACKGROUND_PROCESSESMODIFY_AUDIO_SETTINGSNFCREAD_SYNC_SETTINGSREAD_SYNC_STATSRECEIVE_BOOT_COMPLETEDREORDER_TASKSREQUEST_IGNORE_BATTERY_OPTIMIZATIONSREQUEST_INSTALL_PACKAGESSET_ALARMSET_TIME_ZONESET_WALLPAPERSET_WALLPAPER_HINTSTRANSMIT_IRUNINSTALL_SHORTCUTUSE_FINGERPRINTVIBRATEWAKE_LOCKWRITE_SYNC_SETTINGS
需要运行时申请的权限
所有危险的Android系统权限属于权限组,如果APP运行在Android 6.0 (API level 23)或者更高级别的设备中,而且targetSdkVersion>=23时,系统将会自动采用动态权限管理策略,如果你在涉及到特殊权限操作时没有申请权限权限而直接调用了相关代码,你的App可能就崩溃了,综上所述你需要注意:
- 此类权限也必须在Manifest中申明,否则申请时不提示用户,直接回调开发者权限被拒绝。
- 同一个权限组的任何一个权限被授权了,这个权限组的其他权限也自动被授权。例如一旦WRITE_CONTACTS被授权了,App也有READ_CONTACTS和GET_ACCOUNTS了。
- 申请某一个权限的时候系统弹出的Dialog是对整个权限组的说明,而不是单个权限。例如我申请READ_EXTERNAL_STORAGE,系统会提示"允许xxx访问设备上的照片、媒体内容和文件吗?
如果App运行在Android 5.1 (API level 22)或者更低级别的设备中,或者targetSdkVersion<=22时(此时设备可以是Android 6.0 (API level 23)或者更高),在所有系统中仍将采用旧的权限管理策略,系统会要求用户在安装的时候授予权限。其次,系统就告诉用户App需要什么权限组,而不是个别的某个权限。
CALENDAR(日历) READ_CALENDARWRITE_CALENDARCAMERA(相机) CAMERACONTACTS(联系人) READ_CONTACTSWRITE_CONTACTSGET_ACCOUNTSLOCATION(位置) ACCESS_FINE_LOCATIONACCESS_COARSE_LOCATIONMICROPHONE(麦克风) RECORD_AUDIOPHONE(手机) READ_PHONE_STATECALL_PHONEREAD_CALL_LOGWRITE_CALL_LOGADD_VOICEMAILUSE_SIPPROCESS_OUTGOING_CALLSSENSORS(传感器) BODY_SENSORSSMS(短信) SEND_SMSRECEIVE_SMSREAD_SMSRECEIVE_WAP_PUSHRECEIVE_MMSSTORAGE(存储卡) READ_EXTERNAL_STORAGEWRITE_EXTERNAL_STORAGE
- 防止一次请求太多的权限或请求次数太多,用户可能对你的应用感到厌烦,在应用启动的时候,最好先请求应用必须的一些权限,非必须权限在使用的时候才请求,建议整理并按照上述分类管理自己的权限:
- 普通权限(Normal PNermissions):只需要在Androidmanifest.xml中声明相应的权限,安装即许可
- 需要运行时申请的权限(Dangerous Permissions):
- 必要权限:最好在应用启动的时候,进行请求许可的一些权限(主要是应用中主要功能需要的权限)。
- 附带权限:不是应用主要功能需要的权限(如:选择图片时,需要读取SD卡权限)。
- 解释你的应用为什么需要这些权限:在你调用requestPermissions()之前,你为什么需要这个权限
- 例如,一个摄影的App可能需要使用定位服务,因为它需要用位置标记照片。一般的用户可能会不理解,他们会困惑为什么他们的App想要知道他的位置。所以在这种情况下,所以你需要在requestpermissions()之前告诉用户你为什么需要这个权限。
- 使用兼容库support-v4中的方法
ContextCompat.checkSelfPermission()ActivityCompat.requestPermissions()ActivityCompat.shouldShowRequestPermissionRationale()
几个重要的方法与常量解释
- PackageManager中的两个常量:
- PackageManager.PERMISSION_DENIED:该权限是被拒绝的。
- PackageManager.PERMISSION_GRANTED:该权限是被授权的。
- Activity中或者Fragment都会有以下几个方法:
int checkSelfPermission(String)void requestPermissions(int, String...)boolean shouldShowRequestPermissionRationale(String)void onRequestPermissionsResult()checkSelfPermission() 检查权限
- 检查某一个权限的当前状态,你应该在请求某个权限时检查这个权限是否已经被用户授权,已经授权的权限重复申请可能会让用户产生厌烦。
- 该方法有一个参数是权限名称,有一个int的返回值,用这个值与上面提到的两个常量做比较可判断检查的权限当前的状态。
if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { // 没有权限,申请权限。}else{ // 有权限了,去放肆吧。}requestPermissions() 申请权限
- 请求用户授权几个权限,调用后系统会显示一个请求用户授权的提示对话框,App不能配置和修改这个对话框,如果需要提示用户这个权限相关的信息或说明,需要在调用 requestPermissions() 之前处理,该方法有两个参数:
- int requestCode,会在回调onRequestPermissionsResult()时返回,用来判断是哪个授权申请的回调。
- String[] permissions,权限数组,你需要申请的的权限的数组。
- 由于该方法是异步的,所以无返回值,当用户处理完授权操作时,会回调Activity或者Fragment的onRequestPermissionsResult()方法。
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.READ_CONTACTS}, MMM);
- 该方法在Activity/Fragment中应该被重写,当用户处理完授权操作时,系统会自动回调该方法,该方法有三个参数:
- int requestCode,在调用requestPermissions()时的第一个参数。
- String[] permissions,权限数组,在调用requestPermissions()时的第二个参数。
- int[] grantResults,授权结果数组,对应permissions,具体值和上方提到的PackageManager中的两个常量做比较。
@Overridepublic void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case MMM: { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 权限被用户同意,可以去放肆了。 } else { // 权限被用户拒绝了,洗洗睡吧。 } return; } }}shouldShowRequestPermissionRationale()
- 望文生义,是否应该显示请求权限的说明。
- 第一次请求权限时,用户拒绝了,调用shouldShowRequestPermissionRationale()后返回true,应该显示一些为什么需要这个权限的说明。
- 用户在第一次拒绝某个权限后,下次再次申请时,授权的dialog中将会出现“不再提醒”选项,一旦选中勾选了,那么下次申请将不会提示用户。
- 第二次请求权限时,用户拒绝了,并选择了“不再提醒”的选项,调用shouldShowRequestPermissionRationale()后返回false。
- 设备的策略禁止当前应用获取这个权限的授权:shouldShowRequestPermissionRationale()返回false 。
- 加这个提醒的好处在于,用户拒绝过一次权限后我们再次申请时可以提醒该权限的重要性,免得再次申请时用户勾选“不再提醒”并决绝,导致下次申请权限直接失败。
f (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { // 没有权限。 if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_CONTACTS)) { // 用户拒绝过这个权限了,应该提示用户,为什么需要这个权限。 } else { // 申请授权。 ActivityCompat.requestPermissions(thisActivity, new String[]{Manifest.permission.READ_CONTACTS}, MMM); }}...@Overridepublic void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case MMM: { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 权限被用户同意,可以去放肆了。 } else { // 权限被用户拒绝了,洗洗睡吧。 } return; } }}
从上面来看,判断很多,逻辑也很多,这样就加重了我们开发的负担,加上很多人反馈说国产手机有各种各样的bug,这样兼容起来就更加麻烦了,那么下面我就为大家介绍一个开源内裤来解决这一系列问题。
compile 'com.yanzhenjie:permission:1.0.6'使用介绍
我建议看官去Github下载Demo并阅读本文会帮助你理解
- Android踩坑日记:Android动态权限分析和解决方案
- Android-动态权限-解决方案
- Android踩坑日记:android7.0动态相机权限
- android 6.0 动态权限解决方案
- android 6.0权限全面详细分析和解决方案
- android 6.0权限全面详细分析和解决方案
- android 6.0权限全面详细分析和解决方案
- android 6.0 新权限系统详细分析和解决方案总结
- android 6.0权限全面详细分析和解决方案
- android 6.0权限全面详细分析和解决方案
- Android PermissionChecker 权限全面详细分析和解决方案
- android 6.0权限全面详细分析和解决方案
- android 6.0权限全面详细分析和解决方案
- android 6.0权限全面详细分析和解决方案
- Android 6.0权限全面详细分析和解决方案
- Android 6.0权限全面详细分析和解决方案
- android 6.0权限全面详细分析和解决方案
- android 6.0权限全面详细分析和解决方案
- java集合类知识
- linux 添加用户后ssh publickey登录 仍然需要密码debug
- 网络连接方式为NAT,系统无法上网或IP设置成静态后无法上网
- 《银翼杀手2049》杂感
- NOIP2017 Day1_T3 逛公园
- Android踩坑日记:Android动态权限分析和解决方案
- windows下php eclipse 和xampp安装总结
- Unicode、UTF-8 和 ISO8859-1等编码方式
- Xshell5 评估过期,需要采购,不能使用
- 有向无环图求最长路
- bfs dfs
- 在linux中减小和增大LV的过程与思考
- android开发使用组件个人心得!!!
- TCP连接的建立与终止