最近APP里面要添加动态权限,网上找了不少例子并经过一定的测试,基本流程有了一定的认识,需要注意的地方记录下来以备以后查阅。

一 各大手机厂商的适配

依据各大手机Rom的不同表现,可以分为三种不同的模式:标准模式,默认开启模式,特殊权限模式。

1 标准模式:代表华为Mate8,三星S6。

基本流程如下:

用户启动APP后,第一次需要权限的时候,判断用户当前权限,弹出系统默认的系统Snacbarintstate = ActivityCompat.checkSelfPermission(activity,requestPermission);

通过onRequestPermissionsResult判断出来用户选择结果,

用户选择始终允许,则直接获取了权限,APP继续后续流程。

如果用户选择了拒绝,则需要APP自己处理,一般会弹出一个Dialog 提示用户需要该权限,是否去设置里面打开该权限。拒绝也分为两种情况,一种是选择了禁止后不再询问,一种是没有选择。两种的区别在于在标准模式下,用户选择了禁止不再提问后,不会再弹出系统Snacbar,而是直接返回拒绝的结果,如果用户没有选择,则会继续弹出系统Snacbar。

用户启动权限申请后,会有shouldShowRequestPermissionRationale来判断是否需要APP弹出一个提示框,提示用户来同意申请该动态权限。这个在应用首次申请权限时,如果用户点击拒绝,下次再申请权限,Android允许你提示用户,你为什么需要这个权限,更好引导用户是否授权。

本来是添加一个自定义Dialog来提示用户,后产品认为提示过多,则默认还是直接去申请权限。if(ActivityCompat.shouldShowRequestPermissionRationale(activity,requestPermission)) {

//为了优化用户关闭权限后 第一次没有任何提示

if(ConfigUtils.isHtc()) {

openSettingActivity(activity,activity.getString(R.string.permission_setting_head)

+ message +"权限",permissionGrant);

}else{

//TODO 直接进行权限申请 不再先进行自定义提示

ActivityCompat.requestPermissions(activity, newString[]{requestPermission},requestCode);

//                shouldShowRationale(activity, requestCode, requestPermission, permissionGrant);

}

}else{

ActivityCompat.requestPermissions(activity, newString[]{requestPermission},requestCode);

}

2 默认开启模式:代表HTC One。

和标准模式的区别,是调用检查APP权限的代码后,默认会给用户该权限。

所以不会弹出系统Snacbar提示你去进行选择,用户没有感觉到安装了一个动态权限版本的APP。

3 特殊权限模式:代表360手机。

360正常是属于默认开启模式的,但是针对特殊权限里面的部分权限,360认为是危险权限会进行自定义的提示。比如:照相机被认为是危险权限,打开本地存储则不属于。

针对危险权限的权限状态,返回的也是通过,但是360会自动打开自定义的Dialog,这个和系统默认的Snacbar是一个逻辑流程。

二  多权限处理

前提也是通过遍历,获取多个权限当前的状态,依据各自的权限状态再去分别处理。

多权限的返回结果:

比如 申请了三个权限A,B,C。A选择通过,B拒绝,C拒绝并不再提示,则在处理返回值的时候,需要分别处理,正常会弹出一个Dialog提示,B和C没有权限,需要到设置界面去打开。

等用户再次申请这三个权限的时候,肯定返回B和C需要申请,默认标准模式下会弹出系统Snacbar提示B权限的申请,而没有A和C,C已经拒绝提示,A已经通过。如果B通过了,则返回结果里面只有C没有通过,APP依然会弹出需要到设置界面去打开C权限的Dialog。

三 权限状态不准确的处理 代表HTC One

HTC属于默认申请就给权限的手机,但是用户在设置界面关闭了赋予APP的动态权限后,利用intstate = ActivityCompat.checkSelfPermission(activity,requestPermission);

得到的仍在是已经有权限的结果,这样会造成APP的实际没有权限,而后续的使用权限的操作会导致APP崩溃。针对这种情况需要添加AppOps来判断当前的权限状况:intstate = ActivityCompat.checkSelfPermission(activity,requestPermission);

if(state == PackageManager.PERMISSION_GRANTED) {

// 避免此时是已经被拒绝造成的通过

String appPermission =chageToAppOpsManagerC(requestCode);

if(null!= appPermission) {

checkResult =getPermissionState(activity,appPermission);

}

}private static int getPermissionState(Context activity,String  op) {

if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.KITKAT) {

AppOpsManager appOpsManager = (AppOpsManager)                     activity.getSystemService(Context.APP_OPS_SERVICE);

returnappOpsManager.checkOpNoThrow(op,Binder.getCallingUid(),activity.getPackageName());

}

returnAppOpsManager.MODE_ALLOWED;

}

这时的返回值才是正确的状态。

备注:

动态权限优化了流程,原则就是只要有能弹出系统的Snacbar则就先弹Snacbar,不能弹出任何Snacbar之后,依据返回的结果APP给出提示需要什么权限,要跳转到系统设置里面赋予权限。

其他注意点

1 需要判断系统版本是否是6.0以上。低于6.0版本的不需要进行动态权限的判断,如果进入了动态权限的判断逻辑,则各种效果都会出来。

2 升级到6.0以上的版本编译之后,一些操作有了限制。比如,7.0之后对文件共享进行来限制,打开照相机,获取相机图片需要使用FileProvider进行操作。if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.N) {//7.0及以上

Uri contentUri =getUriForFile(mContext,"包名.fileProvider",

newFile(FileUtils.getSDCardRoot() + ConfigFile.CACHE_AVATAR_DIR,ConfigFile.CACHE_AVATAR_CAMERA_NAME));

intentFromCapture.putExtra(MediaStore.EXTRA_OUTPUT,contentUri);

intentFromCapture.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION

| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

}else{

intentFromCapture.putExtra(MediaStore.EXTRA_OUTPUT,Uri

.fromFile(newFile(FileUtils.getSDCardRoot() + ConfigFile.CACHE_AVATAR_DIR,ConfigFile.CACHE_AVATAR_CAMERA_NAME)));

}

android权限适配 简书,Android动态权限适配相关推荐

  1. android 开启gps 简书,Android蓝牙第三方库FastBle使用注意事项(需开启GPS定位)

    纯手打,不喜勿喷 long may the sun shine 由于项目需要,今天打开了一个旧项目,想看看其中的搜索附近的蓝牙这个功能.但是尝试了很多次之后,发现仍然搜索不到任何蓝牙设备.这个项目蓝牙 ...

  2. android 读写文件 简书,Android 中的文件操作

    Android 文件操作 概述 Android 中的文件操作主要涉及到两个部分,一个是内部存储的读写,一个是外部存储的读写两者的主要区别如下表: 内部存储 外部存储 始终可用 它并非始终可用,因为用户 ...

  3. android 截屏 简书,Android 内置应用截屏方法

    Android 中,内置应用如何更好的截屏 在开发系统应用的时候,有时候需要用到截屏,因为 View.getDrawingCache() 截不到状态栏,所以这个方案不理想 这有一个更好的方案,就是用 ...

  4. android自动登录简书,Android开发之简单登录界面

    用户界面基础 Android系统的四大组件分别是活动(Activity).服务(Service).广播接收器(Broadcast Receiver).内容提供器(Content Provider). ...

  5. android 读写文件 简书,Android10 文件操作适配

    最近Android10的手机不断上市,在对其就进行适配过程中发现对文件操作发生错误,问题如下: java.lang.SecurityException: getSubscriberId: The us ...

  6. android运行过程简书,Android系统的启动流程

    Android系统有哪些进程 在Linux系统启动时,会读取init.rc,里面配置了一些需要启动的进程.注意:SystemServer进程不在init.rc里,因为SystemServer进程是由z ...

  7. android 开发环境简书,Android Studio 开发环境快速搭建

    目录 - 1.下载JDK.AS - 1.1 JDK下载 - 1.2 AS下载 - 1.3 百度云资源统一下载 - 2.安装JDK - 3.配置JDK及JAVA的环境 - 3.1 打开系统环境 - 3. ...

  8. android 辅助服务 简书,Android AccessibilityService使用

    测试demo主要使用了Android 的无障碍辅助服务(AccessibilityService),主要注意是 1. 开启服务,绑定目标app的监听(demo中根据包命绑定了体积计算的app),需要在 ...

  9. android四大组件 简书,android四大组件

    android有四大组件,分别是Activity, Service(服务),Content Provider(内容提供者),BoadcastReceiver广播接收器. Activity 一个Acti ...

最新文章

  1. 算法72----最大正方形
  2. python怎么重新开始_人人都是数据科学家从新开始用Python学习数据科学的完整教程P3...
  3. JS垃圾回收——和其他语言一样,JavaScript 的 GC 策略也无法避免一个问题:GC 时,停止响应其他操作,这是为了安全考虑...
  4. 超线程技术——超线程技术让(P4)处理器增加5%的裸晶面积,就可以换来15%~30%的效能提升,本质单核模拟双核!和异步编程的思想无异。...
  5. 【错误记录】Ubuntu 修改 hosts 文件 ( 使用 gedit /etc/hosts 命令打开并修改 hosts 文件 )
  6. 谈谈Hybird3D中的光栅化优化
  7. SSM 框架整合 spring 发送邮件功能实现!
  8. CCTV2《今日观察》:谷歌事件美国早有预谋
  9. 默认优先级值是多少 ospf_OSPF是什么?网工必备技能——OSPF详解
  10. Python升级后ssl模块不可用问题解决和浅析
  11. linux path_lookup,Linux虚拟文件系统(4)-- 路径名查找
  12. 数据结构实验二---单链表的实现
  13. 项目集锦 | 易基因近期m6A甲基化(MeRIP-seq)研究成果
  14. 小米MIUI线刷包cust.img、system.img精简教程(二)
  15. 详细写出拆卸计算机的步骤和过程,CPU风扇(INTEL)的详细拆卸和安装方法_计算机软件和应用程序_IT / computer_special...
  16. 小蜜蜂吉他谱 高八度和低八度
  17. 【系统架构师】软件架构设计——2需求与质量属性
  18. iframe 的使用理解
  19. 创新型中小企业评价标准
  20. 候选码主属性非主属性

热门文章

  1. C#开发笔记之13-如何用C#分隔字符串并返回字符串数组?
  2. C#LeetCode刷题-排序
  3. nmap查看开放端口以及使用的协议
  4. JavaScript变量作用域如何像多个级别的政府一样
  5. 山东大学有人陪!真的吗?_10,000小时! 您真的需要那么多吗?
  6. des加密的c语言程序,C++中四种加密算法之DES源代码
  7. docker上传镜像到仓库
  8. 如何借助 Python 俘获女孩子芳心?
  9. Mac下iTerm2的ls输出如何显示文件件颜色呢?
  10. Python数据库编程pymysql