Android适配系列:

  • Android 6.0 的动态权限管理

  • Android 7.0脱坑指南

  • Android 8.0适配指北

  • Android 9.0 适配指南

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以上的手机或是国内部分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 {/*** 需要进行检测的权限数组*/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;@Overrideprotected void onResume() {super.onResume();if (Build.VERSION.SDK_INT >= 23&& getApplicationInfo().targetSdkVersion >= 23) {if (isNeedCheck) {checkPermissions(needPermissions);}}}/*** * @param permissions* @since 2.5.0* requestPermissions方法是请求某一权限,*/private void checkPermissions(String... permissions) {try {if (Build.VERSION.SDK_INT >= 23&& getApplicationInfo().targetSdkVersion >= 23) {List<String> needRequestPermissonList = findDeniedPermissions(permissions);if (null != needRequestPermissonList&& needRequestPermissonList.size() > 0) {String[] array = needRequestPermissonList.toArray(new String[needRequestPermissonList.size()]);Method method = getClass().getMethod("requestPermissions", new Class[]{String[].class,int.class});method.invoke(this, array, PERMISSON_REQUESTCODE);}}} catch (Throwable e) {}}/*** 获取权限集中需要申请权限的列表* * @param permissions* @return* @since 2.5.0* checkSelfPermission方法是在用来判断是否app已经获取到某一个权限* shouldShowRequestPermissionRationale方法用来判断是否* 显示申请权限对话框,如果同意了或者不在询问则返回false*/private List<String> findDeniedPermissions(String[] permissions) {List<String> needRequestPermissonList = new ArrayList<String>();if (Build.VERSION.SDK_INT >= 23&& getApplicationInfo().targetSdkVersion >= 23){try {for (String perm : permissions) {Method checkSelfMethod = getClass().getMethod("checkSelfPermission", String.class);Method shouldShowRequestPermissionRationaleMethod = getClass().getMethod("shouldShowRequestPermissionRationale",String.class);if ((Integer)checkSelfMethod.invoke(this, perm) != PackageManager.PERMISSION_GRANTED|| (Boolean)shouldShowRequestPermissionRationaleMethod.invoke(this, perm)) {needRequestPermissonList.add(perm);}}} catch (Throwable e) {}}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;}/*** 申请权限结果的回调方法*/@TargetApi(23)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(R.string.notifyTitle);builder.setMessage(R.string.notifyMsg);// 拒绝, 退出应用builder.setNegativeButton(R.string.cancel,new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {finish();}});builder.setPositiveButton(R.string.setting,new DialogInterface.OnClickListener() {@Overridepublic 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);}@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) {if(keyCode == KeyEvent.KEYCODE_BACK){this.finish();return true;}return super.onKeyDown(keyCode, event);}}

我在上面的类中,自己加入了一些注释,大家仔细看就可以明白了。

补充:小米手机在动态权限这里还需要一些兼容,我们需要注意一下。当然对于国内部分6.0以前手机,只能在需要权限去去捕获异常来处理了。

当然不止上面一种实现方法,github上有许多大神开源的封装库,可以很方便的实现权限适配。我推荐两个库,大家根据需求选择:

1. PermissionsDispatcher

2. 鸿洋大神的MPermissions

5.参考

1. Android M 新的运行时权限开发者需要知道的一切

2. 高德地图定位API

谈谈Android 6.0 的动态权限管理相关推荐

  1. 【Android 应用开发】动态权限管理示例 ( 使用原生代码实现 | 申请权限 | 判定权限申请结果 | 判定 “ 不再询问 “ 情况 )

    文章目录 一.申请权限 二.判定权限申请结果 三.判定 " 不再询问 " 情况 四.完整代码示例 1.权限管理代码 2.主界面代码 3.执行结果 五.博客资源 一.申请权限 首先 ...

  2. Android 6.0运行时权限管理

    运行时权限管理 定义: 之前我们的App需要权限,只需在manifest中申明,用户安装后,一切申明的权限都可使用. 但是Android 6.0以后Android M把权限管理做了加强处理,除了需要在 ...

  3. 谈谈Android 6.0运行时权限理解

    前言 谷歌在2015年8月份时候,发布了Android 6.0版本,代号叫做"棉花糖"(Marshmallow ),其中的很大的一部分变化,是在用户权限授权上,或许是感觉之前默认授 ...

  4. Android动态权限管理模型(4.3-6.0)

    Google从4.3开始就试图引入AppOpsManager动态权限管理模型,但是,由于感觉技术不太成熟,在Release版本中,这个功能都是被隐藏掉的,所以官方Rom一直没有动态权限管理机制.直到A ...

  5. Android 8.0 运行时权限策略变化和适配方案

    Android8.0也就是Android O即将要发布了,有很多新特性,目前我们可以通过AndroidStudio3.0 Canary版本下载Android O最新的系统映像的Developer Pr ...

  6. Android 系统(80)---Android 8.0 7.0 6.0 动态权限管理

    Android 8.0 7.0 6.0 动态权限管理 1.Android6.0之后运行时权限策略变化 从Android6.0(API23)开始,对系统权限做了很大的改变,在之前用户安装app前,只是把 ...

  7. Android 6.0: 动态权限管理的解决方案

    Android 6.0版本(Api 23)推出了很多新的特性, 大幅提升了用户体验, 同时也为程序员带来新的负担. 动态权限管理就是这样, 一方面让用户更加容易的控制自己的隐私, 一方面需要重新适配应 ...

  8. Andorid6.0 动态权限管理

    Github地址 我的博客地址 前言:动态权限管理是Android6.0(B>uild.VERSION_CODES.M =Api23)推出的,提醒用户当前APP所需>要的权限,防止滥用.这 ...

  9. Android 9.0模拟器root权限获取

    Android 9.0在获取权限时报如下错误 remount of the / superblock failed: Permission denied remount failed 解决方法为: 1 ...

最新文章

  1. 矩形内接任意多边形抠图(可以羽化边缘)
  2. mysql数据库utf-8编码
  3. 剧透LiveVideoStackCon 2020:除了干货,还有更多优惠的年度通票
  4. Linux恢复win分区,找到了linux分区顺序错乱修复方法
  5. 移动端设置html的字体尺寸,移动端开发元素及字体尺寸适配基础知识
  6. QMake Automatic Dependencies
  7. Riot Blockchain再次购入1.5万台比特大陆S19系列矿机
  8. 通过system用户操作oracle数据库相关
  9. BZOJ-1050-[HAOI2006]旅行comf(并查集)
  10. 组建一个局域网一般会用到哪些设备_朋友私信一个简单的问题:端口和网关到底有什么区别?...
  11. 《关于促进大数据发展的行动纲要》提出三大指导意见
  12. 「建站指南」小白搭建网站一共分几步?
  13. 滤镜之瓷砖TileReflect
  14. 200行Python实现的qq连连看辅助,用于学习,请不要拿去伤害玩家
  15. 一名软件测试工程师的一天24小时(每天在忙什么)
  16. python之路_面向对象
  17. 计算机学院考研动员大会,计算机科学学院召开考研动员大会暨经验分享会
  18. 谷歌浏览器和火狐浏览器的12px字体显示大小不一样
  19. java心得!--很好的java学习历程(转自张国宝)
  20. JAVA 攻城狮 第三天

热门文章

  1. 计算机usb端口没反应,电脑usb接口没反应怎么解决
  2. 服务器渠道销售和终端销售,终端销售与渠道销售相比哪个更有优势?
  3. JS生成 UUID的四种方法
  4. 设置img标签的默认图片
  5. 分布式飞机机电综合系统半实物验证环境ETest
  6. python selenium移动端网页下拉刷新
  7. OpenCV中视频操作及人脸识别案例
  8. Upload上传@20210412
  9. 【Go-Lua】Golang嵌入Lua代码——gopher-lua
  10. 【CSRF漏洞-01】跨站请求伪造漏洞靶场实战