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


    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多请求的权限
  • 相关阅读:
    十月二十七学习报告
    十月二十六学习报告
    十月二十五学习报告
    十月二十四学习报告
    十月二十三学习报告
    十月二十二学习报告
    十月二十一学习报告
    十月十九学习报告
    十月十七学习报告
    十月十六学习报告
  • 原文地址:https://www.cnblogs.com/yongdaimi/p/16848580.html
Copyright © 2020-2023  润新知