美文网首页6.0Android手机移动程序开发
Android6.0权限处理不再复杂

Android6.0权限处理不再复杂

作者: 街头客 | 来源:发表于2017-04-13 17:48 被阅读791次

    前言

    谷歌在2015年8月份时候,发布了Android 6.0版本,代号叫做“棉花糖”(Marshmallow ),其中的很大的一部分变化,是在用户权限授权上,或许是感觉之前默认授权的不合理,现在6.0出来,使得用户权限授权变得合理。

    Android 6.0版本之前

    在此版本之前,只要在清单文件(AndroidManifest)中申请需要用到的权限,安装之后,所申请的权限将会被允许。

    Android 6.0版本之后

    从Android6.0开始,APP可以直接安装,但所需的权限则需要动态申请。App在运行时询问用户授予权限,弹出Dialog窗口进行询问是否允许,【拒绝】之后,也可以引导用户前往设置界面。

    权限分类

    Google将权限分为两类:
    一类是Normal Permissions,这类权限一般不涉及用户隐私,是不需要用户进行授权的,比如手机震动、访问网络等,所以开发者直接在清单文件中申请即可;

    另一类是Dangerous Permission,一般是涉及到用户隐私的,需要用户进行授权,比如读取sdcard、访问通讯录等;

    但在Dangerous Permission中,其实还有比较特殊的两个权限存在,分别是SYSTEM_ALERT_WINDOW(允许一个程序打开窗口,显示在其他所有程序的顶层)WRITE_SETTINGS(允许应用程序更改主屏幕中的设置和快捷方式)

    这两个权限也属于Dangerous Permission,但是在申请上却有点特殊。这两个权限是不能自动授权,也不能运行时请求授权,只能引导用户去应用的设置页手动开启

    PS:Dangerous Permission的权限9大类别

    Dangerous Permission的权限9大类别

    只要授权某一个类别中的其中某一个权限,则该类别的权限默认全部授权,不需要针对该类别再次询问用户是否允许。

    常用的权限申请

    从Android6.0后,我们常用的权限申请,例如相机权限的申请,代码如下:

    // 相机权限 2017/3/8 11:45
    public static final int REQUEST_CAMERA = 4;
    private static String[] PERMISSIONS_CAMERA = {
            Manifest.permission.CAMERA};
    
    /**
     * 申请相机权限 2017/3/8 11:48
     * @param activity
     */
    public static void cameraPermissions(Activity activity) {
        logger.debug("Camera permissions.");
        int permission = ActivityCompat.checkSelfPermission(activity,
                Manifest.permission.CAMERA);
    
        if (permission != PackageManager.PERMISSION_GRANTED) {
            logger.debug("Not have camera permissions.");
            ActivityCompat.requestPermissions(activity, PERMISSIONS_CAMERA,
                    REQUEST_CAMERA);
        }
    }
    

    上面是申请相机权限的代码,那么在调用的Activity类中,重写如下方法:

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        if (requestCode == RequestPermissions.REQUEST_CAMERA) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
    
            } else {
                Toast.makeText(this, "请授予相机权限", Toast.LENGTH_SHORT).show();
                finish();
            }
    
            return;
        }
    
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
    

    以上就是我们常用的权限申请。

    PermissionsDispatcher

    权限调度者

    使用

    在module.build.gradle中配置,如下:

    compile 'com.github.hotchemi:permissionsdispatcher:2.3.2'
    annotationProcessor 'com.github.hotchemi:permissionsdispatcher-processor:2.3.2'
    

    PS

    旧版需要在top.build.gradle中配置如下信息:

    buildscript {
        dependencies {
            classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
        }
    }
    

    在module.build.gradle中配置,如下:

    apply plugin: 'android-apt'
    

    我在最新的版本2.3.2已经不需要以上的配置了,不然会生成失败。等会在下面会讲。

    Activity中的使用

    package com.example.chenchubin.mypermission;
    
    import android.Manifest;
    import android.app.Activity;
    import android.app.AlertDialog;
    import android.content.DialogInterface;
    import android.content.Intent;
    import android.os.Bundle;
    import android.provider.Settings;
    import android.support.annotation.NonNull;
    
    import permissions.dispatcher.NeedsPermission;
    import permissions.dispatcher.OnNeverAskAgain;
    import permissions.dispatcher.OnPermissionDenied;
    import permissions.dispatcher.OnShowRationale;
    import permissions.dispatcher.PermissionRequest;
    import permissions.dispatcher.RuntimePermissions;
    
    @RuntimePermissions
    public class ScanQRActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_scan);
    
            // 检查权限 2017/4/13 17:22
            ScanQRActivityPermissionsDispatcher.getCameraWithCheck(this);
        }
    
        @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[]
                grantResults) {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    
            // 回调代理进行处理 2017/4/13 17:22
            ScanQRActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
        }
    
        /**
         * 已授权时,进入Activity会调用该方法 2017/4/13 17:22
         */
        @NeedsPermission(Manifest.permission.CAMERA)
        public void getCamera() {
    
        }
    
        /**
         * 授权申请提示,回调 2017/4/13 17:22
         * @param request
         */
        @OnShowRationale(Manifest.permission.CAMERA)
        public void showRationaleForCamera(final PermissionRequest request) {
            new AlertDialog.Builder(this)
                    .setCancelable(false)
                    .setTitle("权限申请")
                    .setMessage("应用需要使用相机权限,您是否确定要使用")
                    .setNegativeButton("拒绝", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            request.cancel();
                        }
                    })
                    .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            request.proceed();
                        }
                    })
                    .setOnDismissListener(new DialogInterface.OnDismissListener() {
                        @Override
                        public void onDismiss(DialogInterface dialog) {
    
                        }
                    })
                    .show();
        }
    
        /**
         * 拒绝时,回调 2017/4/13 17:22
         */
        @OnPermissionDenied(Manifest.permission.CAMERA)
        public void showDeniedForCamera() {
            new AlertDialog.Builder(this)
                    .setCancelable(false)
                    .setTitle("权限申请")
                    .setMessage("在设置-应用-当前应用权限中开启相机权限,以正常使用拍照")
                    .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                            finish();
                        }
                    })
                    .setPositiveButton("去设置", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            //开启设置页
                            startActivity(new Intent(Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS));
                            dialog.dismiss();
                        }
                    })
                    .show();
        }
    
        /**
         * 不再询问时,回调 2017/4/13 17:23
         */
        @OnNeverAskAgain(Manifest.permission.CAMERA)
        public void showNeverAskForCamera() {
            new AlertDialog.Builder(this)
                    .setCancelable(false)
                    .setTitle("权限申请")
                    .setMessage("您已禁止不再询问,请前往设置-应用-当前应用权限中开启相机权限,以正常使用拍照")
                    .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                            finish();
                        }
                    })
                    .setPositiveButton("去设置", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            //开启设置页
                            startActivity(new Intent(Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS));
                            dialog.dismiss();
                        }
                    })
                    .show();
        }
    }
    
    

    注解的意思

    @RuntimePermissions
    (必选)运行时,需要检查权限的类。

    @NeedsPermission
    (必选)当进入Activity类时,如果已授权,会直接调用该注解的方法。

    @OnShowRationale
    (可选)授权申请时,调用。

    @OnPermissionDenied
    (可选)授权申请被拒绝时,调用。

    @OnNeverAskAgain
    (可选)授权申请被勾选不再提示时,调用。

    PS:

    1,执行request.proceed()调用系统申请权限的弹窗;
    如果在系统申请弹窗中勾选了不在提示并且拒绝,会调用@OnNeverAskAgain的方法;

    2,执行request.cancel()会调用@OnPermissionDenied的方法。

    Make Project

    Make Project后,编译器会在app\build\intermediates\classes\debug目录下与被注解的Activity同一个包下生成一个辅助类,名称为被注解的Activity名称+PermissionsDispatcher.class,如图所示:

    ScanQRActivityPermissionsDispatcher

    PS:

    这里需要注意,因为我在这里遇到了一个大坑

    就是上面提到的,新版中已不需要在top.build.gradle中配置android-apt插件,要不上面的ScanQRActivityPermissionsDispatcher一直没有生成出来,找了我半个小时。。。

    生成代理类后,检查调用,代码如下:

    // 检查权限 2017/4/13 17:22
    ScanQRActivityPermissionsDispatcher.getCameraWithCheck(this);
    

    运行效果

    进入检查提示 确定时,提示 拒绝时,提示

    这样使用后,Android权限请求这一块的逻辑就变得比较友好。

    以上的所有内容就是今天要讲的关于Android6.0权限处理的内容。

    我自己在写这文章时,也有所收获,同时希望能对大家有所帮助。

    谢谢支持~~~

    相关文章

      网友评论

      • _love_me:按照你的步骤 ScanQRActivityPermissionsDispatcher 没有该类
        _love_me:@街头客 项目clean 了
        街头客:@_love_me 有先build一下吗?

      本文标题:Android6.0权限处理不再复杂

      本文链接:https://www.haomeiwen.com/subject/beubattx.html