谈谈Android 6.0 的动态权限管理
来源:互联网 发布:飞鸟淘宝客教程 编辑:程序博客网 时间:2024/06/05 22:57
转载地址:http://www.2cto.com/kf/201607/530239.html
1.前言
大家都知道Android 6.0的新特性之一就是应用权限的管理。也就是说凡是涉及用户隐私的权限,用户可以自己去设置管理了。然而在6.0以前,我们安装一款APP是默认同意此APP所需的所有权限(比如定位、访问通讯录),不同意就不能安装。当然,国内的一些手机厂商基于Android定制的系统中,可以实现在6.0以前关闭指定的权限。如下图:
2.危险权限列表(Dangerous Permission)
Dangerous Permission一般都是涉及用户隐私的权限。
从上面的图片中可以看到,摄像头、电话、定位等等都是我们平常开发中常用的权限。
3.可以在6.0不适配权限管理吗?
答案是可以,但是不推荐。
首先说怎么不适配,那就是设置targetSdkVersion小于23(Android 6.0系统默认为targetSdkVersion小于23的应用默认授予了所申请的所有权限,所以如果您APP设置的targetSdkVersion低于23,在运行时也不会崩溃。)
有人一看这不是挺好的嘛,解决问题。那么我想告诉你,首先这不是长久之计,早晚都要面对的。你不可能永远targetSdkVersion低于23。其次,它是有一个前提,那就是用户自己不去操作权限。要知道如果用户是6.0以上的手机,他可以自己在设置中关闭权限,那么到时APP因为没有权限获取数据异常,导致空指针的异常时,APP就会崩溃。
4.怎么适配
首先Android Studio:
在build.gradle中声明targetSdkVersion为23及以上。
Eclipse:
在AndroidManifest.xml中声明targetSdkVersion为23及以上。
这里引用高德定位Demo的CheckPermissionsActivity类,代码如下:
/** * 继承了Activity,实现Android6.0的运行时权限检测 * 需要进行运行时权限检测的Activity可以继承这个类 * * @创建时间:2016年5月27日 下午3:01:31 * @项目名称: AMapLocationDemo * @author hongming.wang * @文件名称:PermissionsChecker.java * @类型名称:PermissionsChecker * @since 2.5.0 */public class CheckPermissionsActivity extends Activity implements ActivityCompat.OnRequestPermissionsResultCallback { /** * 需要进行检测的权限数组 */ protected String[] needPermissions = { Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.READ_PHONE_STATE }; private static final int PERMISSON_REQUESTCODE = 0; /** * 判断是否需要检测,防止不停的弹框 */ private boolean isNeedCheck = true; @Override protected void onResume() { super.onResume(); if(isNeedCheck){ checkPermissions(needPermissions); } } /** * * @param needRequestPermissonList * @since 2.5.0 * requestPermissions方法是请求某一权限, */ private void checkPermissions(String... permissions) { List needRequestPermissonList = findDeniedPermissions(permissions); if (null != needRequestPermissonList && needRequestPermissonList.size() > 0) { ActivityCompat.requestPermissions(this, needRequestPermissonList.toArray( new String[needRequestPermissonList.size()]), PERMISSON_REQUESTCODE); } } /** * 获取权限集中需要申请权限的列表 * * @param permissions * @return * @since 2.5.0 * checkSelfPermission方法是在用来判断是否app已经获取到某一个权限 * shouldShowRequestPermissionRationale方法用来判断是否 * 显示申请权限对话框,如果同意了或者不在询问则返回false */ private List findDeniedPermissions(String[] permissions) { List needRequestPermissonList = new ArrayList(); for (String perm : permissions) { if (ContextCompat.checkSelfPermission(this, perm) != PackageManager.PERMISSION_GRANTED) { needRequestPermissonList.add(perm); } else { if (ActivityCompat.shouldShowRequestPermissionRationale( this, perm)) { needRequestPermissonList.add(perm); } } } return needRequestPermissonList; } /** * 检测是否所有的权限都已经授权 * @param grantResults * @return * @since 2.5.0 * */ private boolean verifyPermissions(int[] grantResults) { for (int result : grantResults) { if (result != PackageManager.PERMISSION_GRANTED) { return false; } } return true; } /** * 申请权限结果的回调方法 */ @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] paramArrayOfInt) { if (requestCode == PERMISSON_REQUESTCODE) { if (!verifyPermissions(paramArrayOfInt)) { showMissingPermissionDialog(); isNeedCheck = false; } } } /** * 显示提示信息 * * @since 2.5.0 * */ private void showMissingPermissionDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("提示"); builder.setMessage("当前应用缺少必要权限。请点击\"设置\"-\"权限\"-打开所需权限。"); // 拒绝, 退出应用 builder.setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { finish(); } }); builder.setPositiveButton("设置", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { startAppSettings(); } }); builder.setCancelable(false); builder.show(); } /** * 启动应用的设置 * * @since 2.5.0 * */ private void startAppSettings() { Intent intent = new Intent( Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.setData(Uri.parse("package:" + getPackageName())); startActivity(intent); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if(keyCode == KeyEvent.KEYCODE_BACK){ this.finish(); return true; } return super.onKeyDown(keyCode, event); }}
我在上面的类中,自己加入了一些注释,大家仔细看就可以明白了。
当然不止上面一种实现方法,github上有许多大神开源的封装库,可以很方便的实现权限适配。我推荐两个库,大家根据需求选择:
1. PermissionsDispatcher
2. 鸿洋大神的MPermissions
- 谈谈Android 6.0 的动态权限管理
- 谈谈Android 6.0 的动态权限管理
- Android 6.0: 动态权限管理的解决方案
- Android 6.0: 动态权限管理的解决方案
- Android 6.0: 动态权限管理的解决方案
- Android 6.0: 动态权限管理的解决方案
- Android 6.0 - 动态权限管理的解决方案
- Android 6.0 - 动态权限管理的解决方案
- Android 6.0 - 动态权限管理的解决方案
- Android 6.0: 动态权限管理的解决方案
- Android 6.0: 动态权限管理的解决方案
- Android 6.0: 动态权限管理的处理
- Android 6.0 - 动态权限管理的解决方案
- Android 6.0 - 动态权限管理的解决方案
- Android 6.0 - 动态权限管理的解决方案
- android 6.0 以后的动态权限管理
- Android 6.0 - 动态权限管理的解决方案
- Android 6.0 - 动态权限管理的解决方案
- mysql的日期和时间函数–date_format
- 利用form从Jsp到Servlet传值为NULL问题(enctype="multipart/form-data")(fileupload)
- 交流工具
- MVC框架模式介绍
- Android的切图标准
- 谈谈Android 6.0 的动态权限管理
- Android图片加载框架最全解析(一),Glide的基本用法
- 深入理解Java:注解(Annotation)基本概念
- git ubuntu 16.04 服务器搭建及 git(windows使用)注意
- 【docker 底层知识】安装 cgroup 介绍与原理
- MySQL 判断记录是否存在,不存在则插入存在则更新
- ios 翻书效果
- 阅读收藏
- Ulua热更新提高 <一> Ulua_SimpleFramework框架流程详解