Android6.0运行时权限

本文详细介绍了Android 6.0引入的运行时权限机制,包括正常权限与危险权限的区别,以及如何检查和请求权限。重点讨论了检查权限的API,如ContextWrapper.checkSelfPermission和PermissionChecker.checkPermission,并指出在处理小米4.4设备时的特殊考虑。同时,阐述了请求权限的API使用,如shouldShowRequestPermissionRationale和requestPermissions,以及如何处理用户授权结果。
摘要由CSDN通过智能技术生成

一、运行时权限

所谓运行时权限,指的是在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

Anroid6.0权限问题 apk22之后Android把一些涉及用户个人信息的权限都做了默认没有权限处理,需要用户确认才可以: 用户不需要在安装软件的时候一次性授权所有申请的权限,而是可以在软件的使用过程中再对某一项权限申请进行授权。举例说明:一款相机应用在运行时申请了地理位置定位权限,就算我拒绝了这个权限,我仍然可以使用这款应用的其他功能,不用像6.0之前无法安装它。 解决办法: ● 投机取巧 如果我们不想使用6.0或者7.0的新特性,那么我们把targetSdkVersion设置22,就可以很好的避开动态配置运行时权限。而targetSdkVersion设置为22,并不影响其在Android 6.0或7.机制上使用,因为高版本兼容低版本。 解决办法:(简单到没朋友) AndroidAcp ● Acp 为 Android check permission 缩写,此库简化Android 6.0 系统复杂的权限操作而编写。 特点 ● 支持批量权限申请,不需要重写 onRequestPermissionsResult 方法,Activity 与 Fragment 中用法一致,一句话搞定。 ● 处理权限拒绝,或勾选不再询问,导致不能正常使用功能的提示框,支持跳转设置权限界面开启权限,所有提示框文字可自定义。 ● #使用Gradle构建时添加一下依赖即可: compile 'com.mylhyl:acp:1.1.7' 怎麽用? Acp.getInstance(this).request(new AcpOptions.Builder() .setPermissions(Manifest.permission.WRITE_EXTERNAL_STORAGE , Manifest.permission.READ_PHONE_STATE , Manifest.permission.SEND_SMS) /*以下为自定义提示语、按钮文字 .setDeniedMessage() .setDeniedCloseBtn() .setDeniedSettingBtn() .setRationalMessage() .setRationalBtn()*/ .build(), new AcpListener() { @Override public void onGranted() { writeSD(); getIMEI(); } @Override public void onDenied(List permissions) { makeText(permissions.toString() + "权限拒绝"); } }); ***************************** 二維碼的使用: ZXING ● 可打开默认二维码扫描页面 ● 支持对图片Bitmap的扫描功能 ● 支持对UI的定制化操作 ● 支持对条形码的扫描功能 ● 支持生成二维码操作 ● 支持控制闪光灯开关 ● 集成默认的二维码扫描页面 在具体介绍该扫描库之前我们先看一下其具体的使用方式,看看是不是几行代码就可以集成二维码扫描的功能。 ● 在module的build.gradle中执行compile操作 compile 'cn.yipianfengye.android:zxing-library:2.1' ● 1 ● 1 ● 在Application中执行初始化操作 @Override public void onCreate() { super.onCreate(); ZXingLibrary.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值