Gradle-动态移除清单文件中的权限
Gradle-动态移除清单文件中的权限
RT, 项目中有这样一个需求,需要将A项目中的界面添加到另一个项目B中,因为A项目中的界面需要用到某些权限,而B项目中也定义了这些权限,B项目中的权限受版本或其它关系,不能被A项目中的权限覆盖,所以希望在对A项目打aar包时,把aar包中的清单文件里的所有关于权限定义的部分删除掉,简单的说,就是这样:
这边想了不少办法,有一种做法是将权限声明成“tools:remove”
, 这是Google新支持的特性,但问题是如果将这些权限都声明成“tools:remove”
,那A项目就用不了这些权限了,所以想了想还是从Gradle入手,翻了不少资料,终于解决了这个需求,这里通过自定义Gradle插件的方式来解决这个问题,具体步骤如下:
-
在当前项目的根目录下新建一个模块,命名为
buildSrc
, 然后添加指定的文件:注意:这个module的名称必须为
buildSrc
.因为我们创建的这个module是AS专门用来写插件的,会自动参与编译.创建好之后删除Android那一堆东西,什么java代码,res,清单文件等.只剩下build.gradle
和.gitignore
把
build.gradle
文件内容改成:repositories { google() jcenter() } apply { plugin 'groovy' plugin 'java-gradle-plugin' } dependencies { implementation gradleApi() implementation localGroovy() implementation "commons-io:commons-io:2.6" }
-
在
main
文件夹下面创建文件夹groovy
, 然后使用Gradle sync一下.没啥问题的话,应该能编译过.然后在groovy
文件夹下面创建包名com.test.xxx
, 包名可以任意指定,然后创建一个空文件,名字叫ManifestFormatPlugin.groovy
package com.test.xxx import org.gradle.api.Plugin import org.gradle.api.Project class ManifestFormatPlugin implements Plugin<Project> { @Override void apply(Project project) { project.afterEvaluate { // 1. Find the specified task def processManifestTask = project.tasks.findByName("processReleaseManifest") if (processManifestTask != null) { // 2. Create a new Gradle task to remove permissions in the "AndroidManifest.xml" def parseDebugTask = project.tasks.create("RemovePermissionTask", RemovePermissionTask.class) // 3. Set to execute immediately after the specified task processManifestTask.finalizedBy(parseDebugTask) } else { println("can not found specified task [processReleaseManifest]") } } } }
这里声明了一个插件,名字叫做:
ManifestFormatPlugin
, 它会在Gradle构建processReleaseManifest
这个任务之后,自动执行我们新定义的Task:RemovePermissionTask
,RemovePermissionTask
这个文件的内容如下:package com.test.xxx import groovy.xml.XmlSlurper import groovy.xml.slurpersupport.NodeChild; import org.gradle.api.DefaultTask; import org.gradle.api.tasks.TaskAction; class RemovePermissionTask extends DefaultTask { @TaskAction void doAction() { // 1. Find the merged manifest file def file = new File(project.buildDir, "/intermediates/merged_manifest/release/AndroidManifest.xml") if (!file.exists()) { println("can not found merged manifest file") return } // 2. Get the content of the manifest file def manifestContent = file.getText() println("prepare to remove all permissions in the merged Manifest...") removePermission(file, manifestContent) } /** * Remove all permissions defined in the manifest file * @param file The "AndroidManifest.xml" file * @param manifestContent Content of the "AndroidManifest.xml" */ static void removePermission(File file, String manifestContent) { def manifestXML = new XmlSlurper(false, false).parseText(manifestContent) manifestXML.'*'.each { node -> if (node.name() == "uses-permission") { node.replaceNode {} } } def serializeContent = groovy.xml.XmlUtil.serialize(manifestXML) file.write(serializeContent) // // use XMLParser to parse the manifest file // def manifestXML = new XmlParser().parseText(manifestContent) // manifestXML.'**'.each { node -> // if (node.name() == "uses-permission") { // node.replaceNode {} // } // } // // new XmlNodePrinter().print(manifestXML) } }
-
然后在你最终想要打aar包的模块上应用该插件,比如我想把项目的
app
模块打成一个aar包,那就在app
模块的build.gradle
上方加入下列语句:import com.test.xxx.ManifestFormatPlugin apply plugin: ManifestFormatPlugin
比如我的加完之后是这个样子:
-
对所在的模块进行aar打包,查看输出结果:
可以看到清单文件中关于 权限声明的部分已经被顺利删除掉了。
参考链接