1.Dangerous Permissions
9组25个权限:申请组中任意一个权限对应组中的其他权限都默认被系统授权了(在次申请的时候)。
对于申请权限弹出的Dialog,是不能定制的。
group:android.permission-group.CONTACTS
permission:android.permission.WRITE_CONTACTS
permission:android.permission.GET_ACCOUNTS
permission:android.permission.READ_CONTACTS
group:android.permission-group.PHONE
permission:android.permission.READ_CALL_LOG
permission:android.permission.READ_PHONE_STATE
permission:android.permission.CALL_PHONE
permission:android.permission.WRITE_CALL_LOG
permission:android.permission.USE_SIP
permission:android.permission.PROCESS_OUTGOING_CALLS
permission:com.android.voicemail.permission.ADD_VOICEMAIL
group:android.permission-group.CALENDAR
permission:android.permission.READ_CALENDAR
permission:android.permission.WRITE_CALENDAR
group:android.permission-group.CAMERA
permission:android.permission.CAMERA
group:android.permission-group.SENSORS
permission:android.permission.BODY_SENSORS
group:android.permission-group.LOCATION
permission:android.permission.ACCESS_FINE_LOCATION
permission:android.permission.ACCESS_COARSE_LOCATION
group:android.permission-group.STORAGE
permission:android.permission.READ_EXTERNAL_STORAGE
permission:android.permission.WRITE_EXTERNAL_STORAGE
group:android.permission-group.MICROPHONE
permission:android.permission.RECORD_AUDIO
group:android.permission-group.SMS
permission:android.permission.READ_SMS
permission:android.permission.RECEIVE_WAP_PUSH
permission:android.permission.RECEIVE_MMS
permission:android.permission.RECEIVE_SMS
permission:android.permission.SEND_SMS
permission:android.permission.READ_CELL_BROADCASTS
2. 6.0 代码动态申请
6.0有个权限组 的概念,就是6.0到7.x 之间,如果同意了该权限组中蘑菇权限,那么系统就会默认授权组中其他的权限。
在8.0,Google做出了修改,系统只会授权当前请求的权限,组中的其他权限不会默认授权,但是应用后面请求了同组中其他的权限,会立即授权单不会提示用户。
比如:
假设某个应用在其清单中列出READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE。应用请求READ_EXTERNAL_STORAGE,并且用户授予了该权限。如果该应用针对的是 API 级别 24 或更低级别,系统还会同时授予WRITE_EXTERNAL_STORAGE,因为该权限也属于同一STORAGE权限组并且也在清单中注册过。如果该应用针对的是 Android 8.0,则系统此时仅会授予READ_EXTERNAL_STORAGE;不过,如果该应用后来又请求WRITE_EXTERNAL_STORAGE,则系统会立即授予该权限,而不会提示用户。
//1.在配置文件中 去声明要申请的权限,去申请没有声明的权限会造成程序崩溃
//2. 去检查是否申请权限了,申请了去执行业务逻辑,没有申请去申请,在回调中进行权限的再次判断与逻辑处理
//3. ContextCompat.checkSelfPermission()返回值有两个 PackageManager.PERMISSION_GRANTED(允许了) 和 PackageManager.PERMISSION_DENIED(拒绝了)
//权限没有申请,就去申请权限去
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,Manifest.permission.CALL_PHONE)) {
// 当用户第一次拒绝了,这个分支在下次申请权限的时候,可以弹个dialog来提醒用户。
Toast.makeText(MainActivity.this,"申请吧,不要拒绝了!",Toast.LENGTH_SHORT).show();
} else {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CALL_PHONE}, CALL_PERMISSION_REQUEST_CODE);
}
} else {
//权限申请了,就去执行业务逻辑吧
callPhone();
}
/**
* 打电话
*/
public void callPhone() {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:" + "13478493231"));
startActivity(intent);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
//检查请求码,找到了对应申请权限的请求码 再去判断
switch (requestCode) {
case CALL_PERMISSION_REQUEST_CODE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
callPhone();
} else {
Toast.makeText(MainActivity.this, "权限被拒绝了,就不能正常使用该应用了", Toast.LENGTH_SHORT).show();
}
break;
}
}
3. 权限被拒绝后,勾选了不再提示
当用户勾选了不在提示,我们可以在回调方法(OnRequestPermissionsResult)中引导用户去设置界面
ACtivityCompat.shouShowRequestPermissionsRetionale():默认返回false,当用户拒绝了权限后,返回值为true,用户勾选了不在提示返回false.
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode){
case CALL_PERMISSION_REQUEST_CODE:
if (grantResults.length>0 && grantResults[0]==PackageManager.PERMISSION_GRANTED){
callPhone();
}else{
//用户勾选了不在提示
if (!ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,Manifest.permission.CALL_PHONE)){
//引导用户去设置界面
gotoSetting();
}
}
}
}
/**
* 去往设置界面
*/
public void gotoSetting(){
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getApplicationContext().getPackageName(), null);
intent.setData(uri);
startActivity(intent);
}