Android6.0运行时权限

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_32199531/article/details/73380577

一、运行时权限

所谓运行时权限,指的是在Android6.0及以上版本中,在app运行时才请求相关权限,从而让每项权限都在用户知情的情况下被授权(当然用户可以拒绝)。而不同于Android6.0之前在安装app时告知用户获取全部权限。
关于权限,分为正常权限(一般和设备相关)、危险权限(用户数据相关)和特殊权限。具体可见https://developer.android.com/guide/topics/security/permissions.html?hl=zh-cn#normal-dangerous,其中特殊权限(悬浮窗权限和系统设置)。

二、检查是否具有权限API

 private boolean checkPermissions(){
        if (Build.VERSION.SDK_INT < 23) {//一般android6以下会在安装时自动获取权限,但在小米机上,可能通过用户权限管理更改权限
            return true;
        }else {

            if (getApplicationInfo().targetSdkVersion < 23) {
                //targetSdkVersion<23时 即便运行在android6及以上设备 ContextWrapper.checkSelfPermission和Context.checkSelfPermission失效
                //返回值始终为PERMISSION_GRANTED
                //此时必须使用PermissionChecker.checkSelfPermission

                if (PermissionChecker.checkPermission(this, Manifest.permission.CAMERA, Binder.getCallingPid(), Binder.getCallingUid(), getPackageName()) == PackageManager.PERMISSION_GRANTED) {
                    return true;
                } else {
                    return false;
                }

            } else {

                if (checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
                    return true;
                } else {
                    return false;

                }
            }
        }

    }

检查是否具有权限主要涉及3个方法:
1、ContextWrapper.checkSelfPermission和Context.checkSelfPermission
只有Build.VERSION.SDK_INT>=23才能调用,且targetSdkVersion>=23结果才有效。因此在targetSdkVersion<23时要用PermissionChecker.checkSelfPermission。
2、PermissionChecker.checkPermission
当在小米4.4上用户手动改变权限后,再次检查权限返回结果有误。适用于Android6.0以上的权限判断。小米4.4需要使用AppOpsManager的权限检验方法。
综上:以上两种,优先选择PermissionChecker.checkPermission。
3、AppOpsManager
为了兼容小米4.4用户可以改变权限的情况,只能使用AppOpsManager。(其实PermissionChecker.checkPermission底层用了Context.checkPermission和AppOpsManager)用法如下:

private boolean checkPermissionForXiaomi(){
        AppOpsManager manager = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE);

        try {

            Method method = manager.getClass().getDeclaredMethod("checkOp", int.class, int.class, String.class);
            int property = (Integer) method.invoke(manager, 26,
                    Binder.getCallingUid(), getPackageName());

            if (AppOpsManager.MODE_ALLOWED == property) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return false;
    }

三、请求权限API

请求权限主要涉及shouldShowRequestPermissionRationale和requestPermissions方法,用法如下:

if (checkPermissions()) {
                Toast.makeText(this,"已经获取权限",Toast.LENGTH_SHORT).show();
            } else {
                Log.d("haha", "no permission.");
                //请求权限
                if (Build.VERSION.SDK_INT < 23) return;
                if (shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) {//上次请求权限被拒绝
                    //这里一般自定义一个界面告知用户为何需要此权限
                    //一般手机还是会弹出用户授权界面,但小米4.4对此作了处理  需通过intent跳转到对应的权限管理界面
                    //requestPermissions(new String[]{Manifest.permission.CAMERA}, 1);
                } else {
                    requestPermissions(new String[]{Manifest.permission.CAMERA}, 1);
                }

            }

1、shouldShowRequestPermissionRationale
上一次请求被拒绝则返回true,此时开发者应该有一个页面说明请求权限的原因。
2、requestPermissions
会直接到用户授权界面,注意小米4.4有自己的权限管理设置,这里不会弹出权限界面,需要作特殊处理直接跳转到对应的设置界面。如下:

/**
     * 打开权限设置界面
     */
    public void openXiaomiSetting() {
        try {
            Intent localIntent = new Intent(
                    "miui.intent.action.APP_PERM_EDITOR");
            localIntent.setClassName("com.miui.securitycenter",
                    "com.miui.permcenter.permissions.AppPermissionsEditorActivity");
            localIntent.putExtra("extra_pkgname", getPackageName());
            startActivityForResult(localIntent, 2);
        } catch (ActivityNotFoundException localActivityNotFoundException) {
            Intent intent1 = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
            Uri uri = Uri.fromParts("package", getPackageName(), null);
            intent1.setData(uri);
            startActivityForResult(intent1, 2);
        }

    }

3、用户授权结果的回调是onRequestPermissionsResult,覆写该方法进行相应处理即可。

 @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        //权限处理结果的回调
        switch (requestCode){
            case 1:
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED){
                    Log.d("haha",permissions[0]+" granted.");
                    Toast.makeText(this,"获取权限成功!",Toast.LENGTH_SHORT).show();
                }
                break;
            case 2:
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED){
                    Log.d("haha",permissions[0]+" granted.");
                    Toast.makeText(this,"小米获取权限成功!",Toast.LENGTH_SHORT).show();
                }
                break;
            default:
                break;
        }
    }

注:经测试特殊权限只能用AppOpsManager

阅读更多
换一批

没有更多推荐了,返回首页