文章最早发布于我的微信公众号 Android开发者家园 中,欢迎大家扫描下面二维码关注微信公众获取更多知识内容。
本文为sydMobile原创文章,可以随意转载,但请务必注明出处!
Android 6.0 权限行为变更
运行时权限说明
Android 6.0 引入了一种新的权限模式,使得用户可以在运行 APP 的时候对一些比较敏感的权限进行管理。这种新的模式可以让用户更好的了解和控制权限,同时为应用精简了安装和自动更新过程。
对于以 Android 6.0 或者更高版本为目标平台的应用,务必在运行的时候检查和请求权限(针对一些危险权限)否则,如果直接调用相关需要特殊权限的方法的话,会导致 APP 的崩溃。检查是否已经拥有权限了可以使用方法 checkSelfPerssion()
如果要请求权限使用方法 requestPermissions
方法。这两个方法都是在 API 23 后引入的,也就是说在之前的 API 中是没有这俩方法的。如果你的 minSdkVersion 设置的值是在 23 以下的话,直接调用上面的方法会有这种提示 Call requires API level 23 (current min is 21):........
提示说的很清除了,调用这种方法是需要 API 23 的,而当前 min 是 21,也就说明你的 APP 是可以运行在 Android 5.0 系统的手机上面的,然而 checkSelfPermission
方法是在 Android 6.0 才引进的,所以会有这种错误的提示。那么毕竟现在 Android 5.0 的系统还是有很多用户量的,这个时候我们应该怎么办呢?这个时候 ActivityCompat
和 ContextComapt
就派上用途的,这个两个类是 Android API 特意为了考虑软件向前兼容考虑的。
什么样的权限需要请求用户授权呢?
对于一些敏感的用户数据,比如一些牵扯到读写功能的权限是需要向用户请求权限的。对于一些无关紧要的权限,可以在安装的时候系统自动将这些权限授予了我们的应用。
普通权限,如果应用程序在其清单中声明了,则系统会在安装时自动授予应用程序该权限,系统不会提示用户授权普通权限,用户也无法撤销
ACCESS_LOCATION_EXTRA_COMMANDS
ACCESS_NETWORK_STATE
ACCESS_NOTIFICATION_POLICY
ACCESS_WIFI_STATE
BLUETOOTH
BLUETOOTH_ADMIN
BROADCAST_STICKY
CHANGE_NETWORK_STATE
CHANGE_WIFI_MULTICAST_STATE
CHANGE_WIFI_STATE
DISABLE_KEYGUARD
EXPAND_STATUS_BAR
FOREGROUND_SERVICE
GET_PACKAGE_SIZE
INSTALL_SHORTCUT
INTERNET
KILL_BACKGROUND_PROCESSES
MANAGE_OWN_CALLS
MODIFY_AUDIO_SETTINGS
NFC
READ_SYNC_SETTINGS
READ_SYNC_STATS
RECEIVE_BOOT_COMPLETED
REORDER_TASKS
REQUEST_COMPANION_RUN_IN_BACKGROUND
REQUEST_COMPANION_USE_DATA_IN_BACKGROUND
REQUEST_DELETE_PACKAGES
REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
SET_ALARM
SET_WALLPAPER
SET_WALLPAPER_HINTS
TRANSMIT_IR
USE_FINGERPRINT
VIBRATE
WAKE_LOCK
WRITE_SYNC_SETTINGS
危险权限:危险权限涵盖应用程序需要涉及用户私人信息的数据或资源的区域,或者可能会影响用户存储数据或其他应用程序的操作。这种权限就需要动态申请了
许可组 | 权限 |
---|---|
CALENDAR |
READ_CALENDAR``WRITE_CALENDAR |
CALL_LOG |
READ_CALL_LOG WRITE_CALL_LOG PROCESS_OUTGOING_CALLS |
CAMERA |
CAMERA |
CONTACTS |
READ_CONTACTS``WRITE_CONTACTS``GET_ACCOUNTS |
LOCATION |
ACCESS_FINE_LOCATION``ACCESS_COARSE_LOCATION |
MICROPHONE |
RECORD_AUDIO |
PHONE |
READ_PHONE_STATE``READ_PHONE_NUMBERS``CALL_PHONE``ANSWER_PHONE_CALLS``ADD_VOICEMAIL``USE_SIP |
SENSORS |
BODY_SENSORS |
SMS |
SEND_SMS``RECEIVE_SMS``READ_SMS``RECEIVE_WAP_PUSH``RECEIVE_MMS |
STORAGE |
READ_EXTERNAL_STORAGE``WRITE_EXTERNAL_STORAGE |
如何获取权限
应用必须通过 <users-permission>
在应用清单中标志来声明 APP 所需要的权限。例如,需要发送 SMS 消息的应用程序需要在清单文件中声明下面的权限:
<uses-permission android:name = “android.permission.SEND_SMS” />
如果在清单中列出的权限,不会对用户的隐形或者设备造成太大的风险,这个时候系统会自动给你的应用授权。如果在应用清单中列出了危险权限(可能影响用户隐私或者设备正常运行的权限)这个时候就需要在代码中调用向对应的 API 动态请求获取权限了。
请求提示危险权限
只有危险权限才需要我们在代码中动态向用户请求,Android 要求用户授予危险权限的方式是和用户设备上运行的 Android 系统的版本以及我们的应用所针对的系统版本有关的。
运行时请求(Android 6.0以及更高版本)
由于国内 Android 系统都是在正宗 Android 系统的基础上二次开发的,所以在这种特性的问题上会和正宗的 Android 系统有不同。
举个例子 :比如你将你开发的 APP 的 targetSDKVersion 设置为 23 以下的话,如果在原生的 Android 系统上,运行的时候是不需要运行时请求危险权限的,因为这个特性是在 API 23 才加入的。但是如果你这样设置的话,在国内的手机上运行还是有问题的(比如小米手机)如果你没有动态申请危险权限,会导致你的 APP 崩溃,也就是说 targetSDKVersion 这个属性对国内的非原生 Android 手机不是那么管用。针对国内的手机建议是:最好 targetSDKVersion 的版本是是最新的,代码里面的 API 也要对应 targetSDKVersion 版本的 API 这样才能保证最大程度的兼容 这句话可能有点不好理解,我再举个例子:比如,在小米手机 8.0 系统上,你设置了 targetSDKVersion 为 22,这个时候如果是原生 Android 系统的话是不需要再动态申请权限了,但是在小米上还是需要的的,这个时候你调用 checkSelfPermission
等等动态调用权限的方法,你会发现还是会出现各种问题,当你把 targetSDKVersion 调整为 23 就可以了。这就是上面那句话的意思。
在需要一些危险权限的时候,必须要向用户动态请求,用户会看到一个系统的对话框,告诉用户这个应用程序需要访问那个权限,让用户选择 拒绝 或者 允许,如果用户拒绝权限请求,则下次应用请求权限的时候,弹出的对话框会增加一个 不再提醒 选择框,如果用户选择 不再询问 并点击 拒绝 ,则系统不会再弹出权限请求框
注意这个对话框,不同的定制系统是不一样,是不能更改的
实际运用
上面讲了那么多概念性的内容,现在来进行实际运用
比如,我的下一步操作需要读写内存卡权限,那么代码如何书写
- 首先应该检查应用有没有获取此权限
- 判断是否需要展示解释
- 请求权限
- 处理回调
下面就一步一步的来详细说明
// 判断应用有没有获取此权限
if(ContextCompat.checkSelfPermission(Activity.this,Manifest.permission.READ_CONTACTS)!= PackageManager.PERMISSION_GRANTED){
// 没有获得权限
// 判断是否需要展示解释
if(ActivityCompat.shouldShowRequestPermissionRationale(Activity.this,"权限名字")){
// 说明用户之前已经拒绝过了,这个时候再发起权限请求,最好
// 向用户解释一下为什么要获取这个权限
}else{
// 正式发出权限请求
ActivityCompat.requestPermissions(Activity.this,"权限名数组");
}
}else{
// 已经取得权限了
do.......
}
// 处理结果回调
public void onRequestPermissionResult(int requestCode,@NonNull String[] permissions,@NonNull int [] grantResults){
// 根据 grantResults 的结果来判断是否取得权限
}
好了,以上就是最基本的运用方法,其他的一些框架都在这个基础上封装的。
注意: 一定要按照上面的顺序来进行(缺少任何步骤都不行),否则在有些系统的手机上会有各种问题。
个人创建了一个微信群,里面有行业的大佬,会不断的分享一些优质文章,交流技术,谈天说地。想要加入的可以添加我好友,拉你进群。早点找到组织,困惑会在交流中消失!