Android 6.0动态权限

来源:互联网 发布:手机自动切换移动网络 编辑:程序博客网 时间:2024/05/19 23:24

新项目,新苦B开始,

从Android 6.0(API 23)开始,允许用户在应用运行时决定是否允许权限,而不是在应用安装的时候。这种方法简化了应用的安装过程,因为用户在安装或更新应用的时候不需要允许权限。他也让用户对应用的功能有更多的控制;例如,用户可以选择给予相机应用相机的权限但是不允许使用设备位置的权限。用户可进入应用设置随时撤销权限。

系统权限被分为两种类型,正常的(normal)和敏感的(dangerous):

  • 正常的权限不会直接让用户的隐私处于危险中。如果你的应用在清单文件中列入了正常的权限,系统会自动允许这些权限。

  • 敏感权限给予应用方位用户的机密数据。如果你的应用在清单文件中列入危险类权限,会明确地让用户对你的应用允许权限。

在所有的Android版本中,你的应用需要在清单文件中去申明它需要的正常的和危险的权限。然而,声明的影响是不同的,依赖于系统版本和你应用的目标SDK等级:

  • 如果设备运行在Android 5.1或更低,或者你的应用的 target SDK是22或者更低;如果你在清单文件中加入了敏感权限,当他们在安装应用的时候必须同意权限;如果他们不同意权限,系统则不会安装应用。

  • 如果设备运行在Android 6.0或更高的版本,或者你的应用的 target SDK是23或者更高。应用必须在manifest文件中加入权限,而且在应用运行过程中必须在它需要的时候请求每一个危险的权限。用户可以允许或者拒绝每一个权限,即使用户拒绝了一个权限的请求而应用可以在限制功能地继续运行。

注意: 从Android6.0(API 23)开始,用户可以在任何时候撤销任何应用的权限,即使应用目标SDK低于23。你应该测试你的用用验证它正常的表现当它缺少需要的权限,不管你的应用的target SDK等级是多少。


不说了,直接上代码,大家都弄这一行的代码才是实货

这是我下面 PermissionManager类

/** * Created by hy * 2017/10/24 15:06 * Note : */public class PermissionManager {    static List<Permission> permissions;    public static List<Permission> getPermissions() {        if (permissions==null){            permissions=new ArrayList<>();            permissions.add(new Permission(Manifest.permission.ACCESS_FINE_LOCATION, "使用设备位置信息", false));            permissions.add(new Permission(Manifest.permission.WRITE_EXTERNAL_STORAGE, "访问设备存储空间", false));//读取文件不需要申请权限            permissions.add(new Permission(Manifest.permission.READ_CALENDAR, "访问日历信息", false));            permissions.add(new Permission(Manifest.permission.CALL_PHONE, "拨打电话和管理通话", false));//调用拨号界面不需要申请权限            permissions.add(new Permission(Manifest.permission.CAMERA, "拍摄照片和录制视频", false));            permissions.add(new Permission(Manifest.permission.SEND_SMS, "发送和查看短信", false));            permissions.add(new Permission(Manifest.permission.BODY_SENSORS, "访问传感器数据", false));            permissions.add(new Permission(Manifest.permission.WRITE_CONTACTS, "使用通讯录", false));            permissions.add(new Permission(Manifest.permission.RECORD_AUDIO, "录制音频", false));        }        return permissions;    }    /**     * 授权回调     */    public interface CheckInitPermissionCallback{        /**         * 权限授权完成         */         void checkOverPass();        /**         * 权限申请未授权且点击提示框取消按钮         */        void checkOverCancel();    }    /**     * 授权回调 可选     */    public interface CheckNeedlessPermissionCallback{        /**         * 权限授权完成         */        void checkOverPass();        /**         * 权限申请未授权且点击提示框取消按钮         */        void checkOverCancel();    }    public static String getCName(String permissionName) {        if (permissions==null){            getPermissions();        }        for (Permission permission :permissions)        {            if (permission.getPermissionName().equals(permissionName))            {                return permission.getcName();            }        }        return "NotFound";    }    public static class Permission {        /**         * 权限名         */        private String permissionName;        /**         * 权限中文名         */        private String cName;        /**         * 是否时必要的         *  必要权限启动时检测 拒绝时退出应用程序         * 非必要权限使用时检测         */        private boolean isNeedful;        public Permission(String permissionName, String cName, boolean isNeedful ) {            this.permissionName = permissionName;            this.cName = cName;            this.isNeedful = isNeedful;        }        public String getPermissionName() {            return permissionName;        }        public String getcName() {            return cName;        }        public boolean isNeedful() {            return isNeedful;        }    }}

这上面主要是讲了,权限检测,权限授权回调,这些主要是看代码,理解思路,

1.getPermissions这个方法里面主要一个权限组,要用到的权限放进去,便于后面检测。

2.CheckInitPermissionCallback,CheckNeedlessPermissionCallback  一看就知道是权限回调

再看我的BaseActivity基类如何实现6.0权限的




/** * 设置界面返回 */private final int SET_REQUEST_CODE = 122;/** * 设置界面(NeedLess) */private final int SET_REQUEST_CODE_NEEDLESS = 123;/** * 必要权限授权界面返回 */private final int NEEDFUL_PERMISSIONS_RESULT = 101;/** * 非必要权限授权界面返回 */private final int NEEDLESS_PERMISSIONS_RESULT = 102;private PermissionManager.CheckInitPermissionCallback checkInitPermissionCallback;PermissionManager.CheckNeedlessPermissionCallback checkNeedlessPermissionCallback;/** * 必要权限集中验证 * (应用程序启动时调用 如loading界面) * * @param checkInitPermissionCallback */protected void checkInitPermission(PermissionManager.CheckInitPermissionCallback checkInitPermissionCallback) {    this.checkInitPermissionCallback = checkInitPermissionCallback;    List<PermissionManager.Permission> permissionList = PermissionManager.getPermissions();    List<PermissionManager.Permission> temp = new ArrayList<>();    for (PermissionManager.Permission permission : permissionList) {        if (permission.isNeedful() && ContextCompat.checkSelfPermission(mContext, permission.getPermissionName())                != PackageManager.PERMISSION_GRANTED) {//启动时检测是否时必要权限且没有授权            temp.add(permission);        }    }    if (temp.size() > 0) {        String[] permissions = new String[temp.size()];        for (int i = 0; i < temp.size(); i++) {            permissions[i] = temp.get(i).getPermissionName();        }        ActivityCompat.requestPermissions((Activity) mContext, permissions, NEEDFUL_PERMISSIONS_RESULT);    } else {        checkInitPermissionCallback.checkOverPass();    }}/** * 非必要权限验证 * (在打开指定界面或使用特定功能时调用) * * @param permission                      Manifest.permission.ACCESS_FINE_LOCATION * @param checkNeedlessPermissionCallback */public void checkNeedlessPermission(String permission, PermissionManager.CheckNeedlessPermissionCallback checkNeedlessPermissionCallback) {    this.checkNeedlessPermissionCallback = checkNeedlessPermissionCallback;    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {        if (mContext.checkSelfPermission(permission)                == PackageManager.PERMISSION_GRANTED) {            checkNeedlessPermissionCallback.checkOverPass();        } else {            checkNeedlessPermissionCallback.checkOverCancel();        }    } else {        checkNeedlessPermissionCallback.checkOverPass();    }}public void showPremissionDialog(String cName, String cancelText) {    new BaseDialog(mContext)            .setTitleText("提示")            .setContentText("应用程序 需要 " + cName + " 权限,请将权限开启\n设置路径:设置 ->应用管理 ->" + LiPackageUtil.getApplicationName(mContext) + " ->权限")            .setCancelButtonText(cancelText)            .setConfirmButtonText("设置").setTypeMode(BaseDialog.WARN_TYPE)            .setOnClickDialogButtonListener(new BaseDialog.DialogButtonListener() {                @Override                public void onCancelButtonClicked(int requestCode) {                    checkInitPermissionCallback.checkOverCancel();                }                @Override                public void onConfirmeButtonClicked(int requestCode) {                    try {                        Intent intent = new Intent(Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS);                        startActivityForResult(intent, SET_REQUEST_CODE);                    } catch (Exception e) {                        Intent intent = new Intent(Settings.ACTION_SETTINGS);                        startActivityForResult(intent, SET_REQUEST_CODE);                    }                }            }).show();}public void showNeedlessPremissionDialog(String contentStr, String cancelText) {    new BaseDialog(mContext)            .setTitleText("提示")            .setContentText(contentStr + "\n设置路径:设置 ->应用管理 ->" + LiPackageUtil.getApplicationName(mContext) + " ->权限")            .setCancelButtonText(cancelText)            .setConfirmButtonText("设置")            .setTypeMode(BaseDialog.WARN_TYPE)            .setOnClickDialogButtonListener(new BaseDialog.DialogButtonListener() {                @Override                public void onCancelButtonClicked(int requestCode) {                }                @Override                public void onConfirmeButtonClicked(int requestCode) {                    Intent intent = new Intent(Settings.ACTION_SETTINGS);                    startActivityForResult(intent, SET_REQUEST_CODE_NEEDLESS);                }            }).show();}@Overridepublic void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {    super.onRequestPermissionsResult(requestCode, permissions, grantResults);    if (requestCode == NEEDFUL_PERMISSIONS_RESULT) {        for (int g : grantResults) {            if (g == PackageManager.PERMISSION_GRANTED) {                checkInitPermission(checkInitPermissionCallback);                return;            }        }        showPremissionDialog(PermissionManager.getCName(permissions[0]), "退出");    } else {        if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {            checkInitPermission(checkInitPermissionCallback);            return;        }        showPremissionDialog(PermissionManager.getCName(permissions[0]), "取消");    }}
@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {    super.onActivityResult(requestCode, resultCode, data);    if (SET_REQUEST_CODE == requestCode) {       checkInitPermission(checkInitPermissionCallback);    }}

这下面这一块主要弄些常量做啥,你们懂的

/** * 设置界面返回 */private final int SET_REQUEST_CODE = 122;/** * 设置界面(NeedLess) */private final int SET_REQUEST_CODE_NEEDLESS = 123;/** * 必要权限授权界面返回 */private final int NEEDFUL_PERMISSIONS_RESULT = 101;/** * 非必要权限授权界面返回 */private final int NEEDLESS_PERMISSIONS_RESULT = 102;

checkInitPermission这个方法里面主要 是必要权限集中验证比如应用程序启动时调用 如loading界面

checkNeedlessPermission 而这个主要是非必要权限验证,比如  Manifest.permission.ACCESS_FINE_LOCATION

这两个主要是利用接口回调进行验证。

showPremissionDialog  自定义的弹框

顺便把这贴出来,主要是得到

tApplicationName  名子

public static String getApplicationName(Context context) {    PackageManager packageManager = null;    ApplicationInfo applicationInfo = null;    try {        packageManager = context.getApplicationContext().getPackageManager();        applicationInfo = packageManager.getApplicationInfo(getPackageName(context), 0);    } catch (PackageManager.NameNotFoundException e) {        applicationInfo = null;    }    String applicationName =            (String) packageManager.getApplicationLabel(applicationInfo);    return applicationName;}
主要是让大家去理解他,代码已测试可以用,除了自定义对话框大兄弟们得要自己定。