簡(jiǎn)介
Marshmallow (API 23) 引進(jìn)了Runtime Permissions 將權(quán)限大致劃分為敏感權(quán)限和普通權(quán)限: PHONE巡验,SMS 寨蹋,LOCATION 辩涝,CONTACTS 之類的隱私屬于敏感權(quán)限剂府,而NFC慷妙,INTERNET雏逾,BLUETOOTH 之類的屬于普通權(quán)限惕澎。如果app需要獲取敏感權(quán)限時(shí)需要在運(yùn)行時(shí)通過代碼請(qǐng)求權(quán)限杨幼,讓用戶手動(dòng)同意灯蝴。
- 只有設(shè)備 && TargetSdkVersion >= 23 才生效恢口,否則還是是采用安裝時(shí)獲取權(quán)限的方式。
- Manifest 中還是需要定義權(quán)限
例子
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getPermissionToReadUserContacts();
}
private static final int READ_CONTACTS_PERMISSIONS_REQUEST = 1;
private void getPermissionToReadUserContacts() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (PackageManager.PERMISSION_GRANTED !=
ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)) {
if (shouldShowRequestPermissionRationale(Manifest.permission.READ_CONTACTS)) {
Toast.makeText(this, "This permission is necessary", Toast.LENGTH_SHORT).show();
}
requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, READ_CONTACTS_PERMISSIONS_REQUEST);
}
}
}
@TargetApi(Build.VERSION_CODES.M)
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == READ_CONTACTS_PERMISSIONS_REQUEST) {
if (grantResults.length == 1 &&
grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "Read Contacts permission granted", Toast.LENGTH_SHORT).show();
} else {
// showRationale = false if user clicks Never Ask Again, otherwise true
boolean showRationale = shouldShowRequestPermissionRationale(Manifest.permission.READ_CONTACTS);
if (showRationale) {
// do something here to handle degraded mode
} else {
Toast.makeText(this, "permission denied", Toast.LENGTH_SHORT).show();
}
}
}
}
}
關(guān)鍵方法
ContextCompat.checkSelfPermission | 檢查當(dāng)前是否已有權(quán)限 |
shouldShowRequestPermissionRationale | 是否該提示用戶需求權(quán)限的原因 |
requestPermissions | 請(qǐng)求權(quán)限 |
onRequestPermissionsResult | 請(qǐng)求權(quán)限call back |
shouldShowRequestPermissionRationale 是說用戶點(diǎn)了拒絕賦予權(quán)限绽乔,但也沒點(diǎn)‘不再提示’弧蝇,這時(shí)候如果實(shí)在需要權(quán)限就可以給予用戶適當(dāng)?shù)奶崾靖嬖V原因。
權(quán)限的分組
權(quán)限是分組的折砸,如果請(qǐng)求的是組內(nèi)的一個(gè)權(quán)限看疗,Android會(huì)自動(dòng)詢問用戶請(qǐng)求整個(gè)組的權(quán)限來避免大量請(qǐng)求權(quán)限。
可以通過以下命令查看所有敏感權(quán)限的分組情況:
$adb shell pm list permissions -d -g
比如:請(qǐng)求READ_CONTACTS 權(quán)限睦授,提示的給用戶的是要獲取CONTACTS組權(quán)限两芳,用戶同意后WRITE_CONTACTS 也被賦予了。
第三方權(quán)限管理庫
PermissionsDispatcher
注解方式管理權(quán)限去枷,清晰方便
@RuntimePermissions
public class MainActivity extends AppCompatActivity {
@NeedsPermission(Manifest.permission.CAMERA)
void showCamera() {
getSupportFragmentManager().beginTransaction()
.replace(R.id.sample_content_fragment, CameraPreviewFragment.newInstance())
.addToBackStack("camera")
.commitAllowingStateLoss();
}
@OnShowRationale(Manifest.permission.CAMERA)
void showRationaleForCamera(PermissionRequest request) {
new AlertDialog.Builder(this)
.setMessage(R.string.permission_camera_rationale)
.setPositiveButton(R.string.button_allow, (dialog, button) -> request.proceed())
.setNegativeButton(R.string.button_deny, (dialog, button) -> request.cancel())
.show();
}
@OnPermissionDenied(Manifest.permission.CAMERA)
void showDeniedForCamera() {
Toast.makeText(this, R.string.permission_camera_denied, Toast.LENGTH_SHORT).show();
}
@OnNeverAskAgain(Manifest.permission.CAMERA)
void showNeverAskForCamera() {
Toast.makeText(this, R.string.permission_camera_neverask, Toast.LENGTH_SHORT).show();
}
}
RxPermissions
rxjava 體系的權(quán)限管理怖辆,提供鏈?zhǔn)讲僮鳎畲蠛锰幉挥迷俜蛛x權(quán)限的請(qǐng)求與結(jié)果處理了删顶。
//RxPermission
RxPermissions.getInstance(this)
.request(Manifest.permission.READ_CONTACTS)
.subscribe(new Action1<Boolean>() {
@Override
public void call(Boolean grant) {
if (grant) {
Toast.makeText(MainActivity.this, "this permission is necessary", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, "Read Contacts permission granted", Toast.LENGTH_SHORT).show();
}
}
});