什么时候需要考虑运行时权限
运行时权限是Android6.0推出的安全机制,当你的app运行在 Android 6.0 及以上设备上,使用危险权限(下面介绍)的时候。
既targetSdkVersion >= 23(关于targetSdkVersion可以看看http://blog.youkuaiyun.com/qq_27280457/article/details/53541033)
如果你的app应用到运行时权限且targetSdkVersion >= 23在6.0以上手机上面就会闪退
Android 6.0系统默认为targetSdkVersion小于23的应用默认授予了所申请的所有权限,所以如果您APP设置的targetSdkVersion低于23,
在运行时也不会崩溃。(运行在6.0手机上面还是可以在设置里面禁止权限,然后相关功能不能使用;运行在6.0以下手机只有把程序卸掉才能禁止
相关权限)
正常权限和危险权限、权限组
正常权限涵盖应用需要访问其沙盒外部数据或资源,但对用户隐私或其他应用操作风险很小的区域。
危险权限涵盖应用需要涉及用户隐私信息的数据或资源,或者可能对用户存储的数据或其他应用的操作产生影响的区域。
所有危险的 Android 系统权限都属于权限组(系统只告诉用户应用需要的权限组,而不告知具体权限。)
1.正常权限:
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
GET_PACKAGE_SIZE
INSTALL_SHORTCUT
INTERNET
KILL_BACKGROUND_PROCESSES
MODIFY_AUDIO_SETTINGS
NFC
READ_SYNC_SETTINGS
READ_SYNC_STATS
RECEIVE_BOOT_COMPLETED
REORDER_TASKS
REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
REQUEST_INSTALL_PACKAGES
SET_ALARM
SET_TIME_ZONE
SET_WALLPAPER
SET_WALLPAPER_HINTS
TRANSMIT_IR
UNINSTALL_SHORTCUT
USE_FINGERPRINT
VIBRATE
WAKE_LOCK
WRITE_SYNC_SETTINGS
2.危险权限和权限组
关于权限组的说明:如果app运行在Android 6.x的机器上,对于授权机制是这样的。如果你申请某个危险的权限,假设你的app早已被用户授权了同一组的某个危险权限,那么系统会立即授权,而不需要用户去点击授权。比如你的app对READ_CONTACTS
已经授权了,当你的app申请WRITE_CONTACTS
时,系统会直接授权通过。(也就是说,不再弹出来权限对话框,但是相应的权限你还是需要在清单文件里面配置,不然app就会崩溃)
相关API介绍以及权限的实现步骤:
1.在AndroidManifest文件中添加需要的权限。
步骤和我们之前的开发并没有什么变化,试图去申请一个没有声明的权限可能会导致程序崩溃。
2.检查权限
ContextCompat.checkSelfPermission
,主要用于检测某个权限是否已经被授予,方法返回值为PackageManager.PERMISSION_DENIED
或者PackageManager.PERMISSION_GRANTED
。当返回DENIED就需要进行申请授权了
3.申请授权
ActivityCompat.requestPermissions(this Activity,new String[]{Manifest.permission.READ_CONTACTS},MY_PERMISSIONS_REQUEST_READ_CONTACTS);
该方法是异步的,第一个参数是Context;第二个参数是需要申请的权限的字符串数组;第三个参数为requestCode,主要用于回调的时候检测。可以从方法名
requestPermissions
以及第二个参数看出,是支持一次性申请多个权限的,系统会通过对话框
逐一
询问用户是否授权。
4.处理权限申请回调
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
}
}
一些说明:
对于Intent的一些方式方式,很多情况下是不需要授权的甚至权限都不需要的,比如:你是到拨号界面而不是直接拨打电话,就不需要去申请权限;打开系统图库去选择照片;调用系统相机app去拍照等,一般情况下,你是通过Intent打开另一个app,让用户通过该app去做一些事情,你只关注结果(onActivityResult),那么权限是不需要你处理的,而是由打开的app去处理。所以你不需要动态去申请权限也不会崩溃。