Android 6.0 permission

简介

Marshmallow (API 23) 引进了Runtime Permissions 将权限大致划分为敏感权限和普通权限: PHONE,SMS ,LOCATION ,CONTACTS 之类的隐私属于敏感权限,而NFC,INTERNET,BLUETOOTH 之类的属于普通权限。如果app需要获取敏感权限时需要在运行时通过代码请求权限,让用户手动同意。

  1. 只有设备 && TargetSdkVersion >= 23 才生效,否则还是是采用安装时获取权限的方式。
  2. Manifest 中还是需要定义权限
Android 6.0 permission_第1张图片
屏幕快照

例子

 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();
                }
            }
        }
    }
}

关键方法

ContextCompat.checkSelfPermission 检查当前是否已有权限
shouldShowRequestPermissionRationale 是否该提示用户需求权限的原因
requestPermissions 请求权限
onRequestPermissionsResult 请求权限call back

shouldShowRequestPermissionRationale 是说用户点了拒绝赋予权限,但也没点‘不再提示’,这时候如果实在需要权限就可以给予用户适当的提示告诉原因。

权限的分组

权限是分组的,如果请求的是组内的一个权限,Android会自动询问用户请求整个组的权限来避免大量请求权限。

可以通过以下命令查看所有敏感权限的分组情况:
$adb shell pm list permissions -d -g

比如:请求READ_CONTACTS 权限,提示的给用户的是要获取CONTACTS组权限,用户同意后WRITE_CONTACTS 也被赋予了。


Android 6.0 permission_第2张图片
codepath
Android 6.0 permission_第3张图片
屏幕快照

第三方权限管理库

PermissionsDispatcher

注解方式管理权限,清晰方便

@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 体系的权限管理,提供链式操作,最大好处不用再分离权限的请求与结果处理了。

//RxPermission
       RxPermissions.getInstance(this)
                .request(Manifest.permission.READ_CONTACTS)
                .subscribe(new Action1() {
                    @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();
                        }
                    }
                });

你可能感兴趣的:(Android 6.0 permission)