前段时间有接到网信办(以下都缩写为 WXB)的红头文件,指出了 APP 内的部分不合理权限,我们积极的进行了处理,去除了一部分确实不合理的权限。
首先 WXB 是如何知道我们使用了哪些权限?很简单,看了 APK 的 AndroidManifest.xml 文件,遍历了 <uses-permission/> 所有声明的权限。这里推荐大家使用 ClassyShark ,可以用它快速查看关于 apk 的一些信息。
因此,我们只要确保 APK 的 AndroidManifest.xml 不要出现 WXB 提到的权限即可,那这些权限又是来自于哪呢?自己写的和你引入的依赖(aar)带进来的。自己写的还好,你可以全局搜索权限关键字,那么搜不到的权限又是由哪个 aar 引入进来的呢?
可以查看 app/build/outputs/logs/manifest-merger-debug-report.txt,我在 demo 的子 module(library)声明了 INTERNET 权限,可以看到下图有显示 INTERNET 权限是从 library 模块加进来的:
![]()
这样你知道了哪个 aar 有问题,你就可以去修改 aar 以不使用对应权限。
然而事情往往不会一帆风顺,aar 有可能是同时给好几个项目共用的,它没法为了你而去掉这个权限,因为其他项目并没有收到 WXB 的文件,不会因为你的项目不需要这个权限,而单独维护一个 aar,这样的话我们该咋办?
打包阶段在生成 AndroidManifest.xml 之后直接删除对应权限。
方案有了,该如何下手,当然先来看看 AndroidManifest.xml 是咋生成的?
![]()
APK 的 AndroidManifest.xml 其实是由各个依赖侧的 AndroidManifest.xml 合并而来的,具体的 task 可以看 com.android.build.gradle.tasks.MergeManifests,整个过程其实很常规,涉及到 xml 的读与写。
那么这个 task 又叫什么呢?我们需要知道他的名称后才方便 hook。
![]()
一会就看到了,叫 "process${variant.name.capitalize()}Manifest”。
知道了 task 的名称后,我们还需要知道最后打进 APK 的 AndroidManifest.xml 在哪?app/build/intermediates/manifests/full/debug/AndroidManifest.xml。就是它了。接下来就可以常规撸码:
![]()
这样就完成了之前所说的“打包阶段在生成 AndroidManifest.xml 之后直接删除对应权限”。
当然,这样去除权限后你还是需要确认 APP 是没问题的,也就是相关依赖方需要做没有该权限的时候的容错处理。
最后,我们好不容易去掉了权限,可不希望日后迭代的时候哪个版本不小心又引入了之前去掉的权限,这样 WXB 大大会很生气,因此需要做一下权限收口的事情。其实也很好做了,基于删除权限的 hook 操作,打 release 包的时候检查 app/build/intermediates/manifests/full/debug/AndroidManifest.xml 有没有 WXB 之前点名的权限,要是有的话就让打包失败,让开发及早发现、尽早解决。
写 Gradle 插件是 Android 开发必须掌握的,不然收到类似红头文件都束手无策就不好办了。