从Android6.0开始(Api 23)增加了运行时权限特性,这个特性是这一版本中影响比较大的一个变化。几个需要记住的关键点:
运行时需要申请的权限必须先在manifest中用
<uses-permission>
声明。如果targetApi设置为23以下,那么新特性不起作用,系统会沿用旧的逻辑在安装时询问并赋予权限。
PROTECTION_NORMAL级别的permission仍然是在安装时系统就自动授予,与之对应的是PROTECTION_DANGEROUS级别的permission需要运行时申请。
每一个permission都属于一个permission Group,系统提示也是以permission Group为单位提示用户并授权的,例如app首先申请了Read Contacts的permission,用户允许,当app再次申请同一permission Group的write Contacts的permission时,系统自动允许,而不是再次弹出对话框提示用户。
运行时申请权限:
简化版本:
private void showContacts() {
if (checkSelfPermission(Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.READ_CONTACTS},
PERMISSIONS_REQUEST_READ_CONTACTS);
} else {
doShowContacts();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults) {
if (requestCode == PERMISSIONS_REQUEST_READ_CONTACTS
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
showContacts();
}
}
复杂版本:
用shouldShowRequestPermissionRationale方法判断否需要向用户解释为什么需要此权限:(如果之前用户拒绝了此权限,再次申请时最好提示一下,此方法会返回true,表示最好向用户解释一下)
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
// 是否需要给用户解释?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.READ_CONTACTS)) {
// 此处的方法最好做成异步的,而不要阻塞住当前进程,当用户看到解释作出反应后,再次申请权限
} else {
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
}
}
//回调中处理权限是否申请成功
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
showContacts();
} else {
//权限未被用户允许
}
return;
}
}
}
注意:如果用户在之前禁止了某个权限并且在对话框中勾选了Don’t ask again选项,那么shouldShowRequestPermissionRationale方法会反回false。
附表: Dangerous permissions 以及对应的 permission groups.
CALENDAR 组:
READ_CALENDAR
WRITE_CALENDAR
CAMERA组:
CAMERA
CONTACTS组:
READ_CONTACTS
WRITE_CONTACTS
GET_ACCOUNTS
LOCATION组:
ACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION
MICROPHONE组:
RECORD_AUDIO
PHONE组:
READ_PHONE_STATE
CALL_PHONE
READ_CALL_LOG
WRITE_CALL_LOG
ADD_VOICEMAIL
USE_SIP
PROCESS_OUTGOING_CALLS
SENSORS组:
BODY_SENSORS
SMS组:
SEND_SMS
RECEIVE_SMS
READ_SMS
RECEIVE_WAP_PUSH
RECEIVE_MMS
STORAGE组:
READ_EXTERNAL_STORAGE
WRITE_EXTERNAL_STORAGE