6.0 以后,Android 权限分为正常权限和危险权限,危险权限有以下几种:
- calendar
- Camera
- Location
- Phone-拨打电话
- SMS -短信相关
- Storage -读取存储相关的权限
权限是一组一组的,如果你申请了 读取 存储的权限,那么写存储的权限可以不用,因为它们是同一组的。
权限申请整体代码过程如下图所示:
在 Activity 的 requestPermissions 的方法里面,最终会调用 startActivityForResult 启动授权 Activity ,这也是为什么我们能收到 onRequestPermissionsResult 的原因:
1 | public final void requestPermissions(int requestCode) String[] permissions, { |
这里面有个小的知识点,Intent 是通过 build 创建出来的,这里是启动隐式的 App:
1 | public Intent buildRequestPermissionsIntent( String[] permissions){ |
直接使用 new Intent(ACTION_REQUEST_PERMISSIONS) 的方式,这是通过隐式意图来激活某个 Activity ,根据常量 ACTION_REQUEST_PERMISSIONS 可以在源码找到(肯定是在 AndroidManifest.xml 中)这个 Activity 就是 GrantPermissionsActivity 。这种隐藏的 App (比如apk安装器)我们直接启动是启动不了的。
用户点击确认授权,会通过进程间通信交给PermissionManagerService 去处理,当然,过程还需要 PKMS 去查询这个 App 。
当授权通过后,会通过 Settings.writeRuntimePermissionxxx 方法将这个记录保留到 xml (system/users/0/runtime-permissions.xml 文件)中永久保存,此后会一直存在,如果卸载 App ,就将这个记录删除掉。
权限申请源码流程总结:
第一步:MainActivity 调用 requestPermissions 进行动态权限申请;
第二步:requestPermissions函数通过隐式意图,激活PackageInstaller的GrantPermissionsActivity界面,让用户选择是否授权;
第三步:经过PKMS把相关信息传递给PermissionManagerService处理;
第四步:PermissionManagerService处理结束后回调给—->PKMS中的onPermissionGranted方法把处理结果返回;
第五步:PKMS通知过程中权限变化,并调用writeRuntimePermissionsForUserLPr函数让PackageManager的settings记录下相关授权信息;
手写无侵入式框架
为什么要写?我短短一个 Activity 代码,申请权限却要写很长很长的权限申请代码。
权限申请
权限被取消
权限被取消,还勾选不再提示
可以用到 AspectJ ,这个后台用到,可以控制注解方法的执行不执行,满足条件执行 A 方法,不满足不执行。这个框架很复杂,是 javac 的二次封装。
这个框架的设计图如下:
以后的框架,应该都需要是 ,无侵入式的(由框架劫持用户的行为) AspectJ 劫持函数的执行
AspectJ 为什么可以无侵入式的 监听+劫持 我们的任何注解
javac Test.java Test.class (JVM只认识class) (我们看不懂字节码,JVM看得懂)
AspectJ(Javac) Test.java 注入代码 Test.class (JVM只认识class) (我们看不懂字节码,JVM看得懂)空白的Activity(申请权限 申请成功 申请失败 用户拒绝申请 回调给外界 告诉AspectJ)
任何一个框架,都有三种方式实现:
1.无侵入式的 由框架监听用户 劫持用户的行为,用户是没有能力调用框架的(依赖AspectJ)
2.APT 注解处理器 侵入式的框架,编译期 Dagger2 Room ARouter DataBinding
3.传统 xUtils 反射无侵入式:用户没有能力调用我们的框架,它连看都看不到我们的框架,
是由我们的框架,全局监听用户的行为,劫持用户,控制用户,执行用户我们框架特点:
我只需要使用三个注解就行了用户没有能力调用框架的API
用户也不需要传递this
由我们的框架 来 监听用户的 注解的
面试题
动态申请权限的流程?
有 15 步,应用进程跨系统服务进程 PKMS 通过 PermissionManagerService 检查权限情况,回调回来给 PKMS ,并且通过 Settings 通过 io 操作将权限结果写入 xml 文件中永久保存,除非卸载,才删除这个记录