Gradle-动态移除清单文件中的权限

RT, 项目中有这样一个需求,需要将A项目中的界面添加到另一个项目B中,因为A项目中的界面需要用到某些权限,而B项目中也定义了这些权限,B项目中的权限受版本或其它关系,不能被A项目中的权限覆盖,所以希望在对A项目打aar包时,把aar包中的清单文件里的所有关于权限定义的部分删除掉,简单的说,就是这样:

image-20221101171356626

这边想了不少办法,有一种做法是将权限声明成“tools:remove”, 这是Google新支持的特性,但问题是如果将这些权限都声明成“tools:remove”,那A项目就用不了这些权限了,所以想了想还是从Gradle入手,翻了不少资料,终于解决了这个需求,这里通过自定义Gradle插件的方式来解决这个问题,具体步骤如下:

  1. 在当前项目的根目录下新建一个模块,命名为 buildSrc, 然后添加指定的文件:

    image-20221101172205197

    注意:这个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"
    }
    
  2. 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)
        }
    
    }
    
  3. 然后在你最终想要打aar包的模块上应用该插件,比如我想把项目的app模块打成一个aar包,那就在 app 模块的 build.gradle上方加入下列语句:

    import com.test.xxx.ManifestFormatPlugin
    apply plugin: ManifestFormatPlugin
    

    比如我的加完之后是这个样子:

    image-20221101173505479

  4. 对所在的模块进行aar打包,查看输出结果:

    image-20221101173636230

    可以看到清单文件中关于 权限声明的部分已经被顺利删除掉了。

参考链接

  1. Gradle系列(四) Gradle插件
  2. Gradle 插件练习-动态移除权限
  3. Android Gradle 插件开发入门指南
  4. StackOverFlow: How to dynamically edit Android Manifest …
  5. Groovy: Get XML Tag first level
  6. 简书:1.5_任务依赖关系和排序
  7. 删除第三方AAR多请求的权限

原文地址:http://www.cnblogs.com/yongdaimi/p/16848580.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性