优雅的动态删除第三方 SDK 的权限

4,908 阅读1分钟

某一天查看 App 的权限列表发现多了很多没声明过的权限,现在开发 App 都不可避免引入各种 SDK,很显然就是他们的锅,在背后干着不可告人的事情.. 怎么删除这些权限呢?

方法1:利用 xml 的 "remove" 节点删除

<uses-permission
      android:name="android.permission.CHANGE_NETWORK_STATE"
      tools:node="remove"
      />

这样 Android 处理 AndroidManifest.xml 文件时会自动删除这个权限。


有时我们在 debug 需要这个权限,但是在 release 正式版不想有这个权限。比如我在测试包的时候写了点测试功能,需要引入一个 android:name="android.permission.SYSTEM_ALERT_WINDOW" 权限,但是正式环境并不需要。

一个做法是,将这个测试功能单独做成一个 lib 引入,正式版引用一个 lib-noop 版本,常见的第三方库如滴滴的多啦爱梦就是这么做的。

如果我们自己处理可以利用 gradle 直接对 xml 文件进行操作:

方法2:利用 gradle 编辑 xml 文件

gradle 处理 Manifest 任务之后会有一个回调,我们在系统处理完之后再进行二次处理,通过 XmlParser 解析 xml 来修改文件。 以下是一个 删除 android.permission.SYSTEM_ALERT_WINDOW 的例子:

// 发布正式版时 将 manifest 中不必要的权限删除
android.applicationVariants.all { variant ->
  if (variant.buildType.name == "release") {
        def output = variant.outputs[0]
        output.getProcessManifestProvider().get().doLast {
          println("start process manifest")
          def manifestFilePath = "${manifestOutputDirectory.asFile.get()}/AndroidManifest.xml"
          def xmlParser = new XmlParser()
          Node manifest = xmlParser.parse(file(manifestFilePath))
          def android = new Namespace('http://schemas.android.com/apk/res/android', 'android')
          def tools = new Namespace('http://schemas.android.com/tools', 'tools')
          Node systemAlertWindow = manifest.get("uses-permission").find {
            def name = it.attributes().get(android.name)
            def remove = it.attributes().get(tools.remove)
            name == "android.permission.SYSTEM_ALERT_WINDOW"
          }
          def remove = manifest.remove(systemAlertWindow)

          // write xml to file
          file(manifestFilePath).withPrintWriter { out ->
            def printer = new XmlNodePrinter(out)
            printer.preserveWhitespace = true
            printer.print(manifest)
          }
          println("end process manifest, delete systemAlertWindow permission success?  $remove")
        }
      }
}