当前位置:   article > 正文

手把手教你Android Gradle Plugin 开发_variant.assemble.dolast

variant.assemble.dolast

开发环境

  1. IntelliJ IDEA 2019.3.4

  2. Oracle JDK1.8

  3. Android Studio 3.6.1

前言

工作中遇到的一个问题,系统开发过程中,系统方提供了.pem+.pk8文件把apk重签名为系统应用,每次需要在Android Studio中先编译出来apk,然后再打开控制台输入重签名的命令将apk重签名,然后再通过adb命令将重签名之后的apk安装进去。很不方便,不能直接使用Android Studio直接run。所以准备写一个gradle的插件,来帮助我做这一部分工作,可以直接在Android Studio中点击run的时候直接将apk重签名然后安装到机器中。

目的

本篇教程有两个目的,阅读完本片教程后你应该可以学会一个Android gradle插件的开发了

  1. plugin task的开发
  2. plugin对android plugin的处理,这里主要说的是对编译出来的apk的后处理

开始制作gradle插件

建议使用IntelliJ IDEA进行gradle插件开发,对groovy的支持比Android Studio好多了

分下面几步

  1. 打开IntelliJ IDEA,创建一个java工程,注意选择gradle项目

在这里插入图片描述

  1. 编辑build.gradle文件,修改下面两个地方,修改之后sync一下,更新一下依赖

添加groovy插件支持

id 'groovy'
  • 1

添加gradle插件依赖

implementation gradleApi()
implementation localGroovy()
  • 1
  • 2

现在你的build.gradle文件长这样

在这里插入图片描述

  1. 编写你的gradle插件类,在main文件夹下面创建一个groovy文件夹

groovy文件夹和java文件夹是同级目录

然后在groovy文件夹中创建一个DemoPlugin.groovy文件,继承自Plugin<Project>,现在你的工程目录结构如下

在这里插入图片描述

注意是DemoPlugin.groovy,不是DemoPlugin.java

然后创建一个文件src/main/resources/META-INF/gradle-plugins/com.bajingxiaozi.demo.properties,这里会配置好即将提供给别人使用的插件的id,文件内容如下,内容是上面的创建的插件的路径,如下

在这里插入图片描述

文件com.bajingxiaozi.demo.properties中的com.bajingxiaozi.demo就是以后提供给别人使用时的插件的id名称,这个不需要和包名一样。

  1. 然后我们现在来给这个插件添加一些功能,重写DemoPluginapply(Project project)方法

  2. 功能1,创建一个名称为hello的gradle task,这个task的功能就是打印出app所有编译出的apk的完整路径

代码如下

// 功能1,创建一个名称为hello的gradle task
project.task('hello') {
    doLast {
        println 'Hello from the GreetingPlugin'
        project.android.applicationVariants.all { variant ->
            println 'variant: '+variant.name
            variant.outputs.each { output ->
                println 'outputFile: '+output.outputFile
            }
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

其中project.task就是创建task的方法

doLast就是在task执行之后进行的操作

project.android就是引用android插件了,可以通过project.android来进行对android插件的一些操作了

  1. 功能2,对android的编译task,也就是android的assemble task进行修改,一边对编译后的apk再进行进一步的修改,比如重签名啊,重命名啊等等

代码如下

// 功能2,对编译后的apk进行一些后处理操作
ResignPluginExtension extension = project.getExtensions().create("resign", ResignPluginExtension.class)

project.android.applicationVariants.all { variant ->
    variant.assemble.doLast {
        println("resign directory: " + extension.signDirectory)
        if (extension.signDirectory == null) {
            return
        }

        final File signDirectory = new File(extension.signDirectory)
        if (!signDirectory.exists()) {
            return
        }
        if (!signDirectory.isDirectory()) {
            return
        }

//                println 'variant1: '+variant.name
        variant.outputs.each { output ->
//                    println 'outputFile1: '+output.outputFile
            println('resign ' + output.outputFile + " start")
            JavaUtils2.resign(signDirectory, output.outputFile)
            println('resign ' + output.outputFile + " end")
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

project.getExtensions().create可以创建一个gradle插件的配置项,比如配置使用的重签名程序的目录

variant.assemble就是android插件的assemble task

variant.assemble.doLast就可以在assemble task执行完成后进行一些后处理,assemble task执行完成后apk也就编译出来了,这时候就可以对apk进行一些处理了

其中ResignPluginExtension JavaUtils2源码如下,也可以在github上查看

public class ResignPluginExtension {

    public String signDirectory;

}
  • 1
  • 2
  • 3
  • 4
  • 5

JavaUtils2主要是使用java -jar signapk.jar cert.x509.pem private.pk8 unsigned.apk signed.apk命令对apk进行后签名处理

public class JavaUtils2 {

    public static void resign(File signDirectory, File file) throws Exception {
        if (!file.exists()) {
            throw new FileNotFoundException(file + " not exist");
        }
        if (!file.isFile()) {
            throw new FileNotFoundException(file + " not a file");
        }

        File tempFle = new File(file.getParentFile(), "temp.apk");
        tempFle.delete();
        // java -jar signapk/signapk.jar signapk/platform.x509.pem signapk/platform.pk8 1.apk XCThemeManager_signed.apk
        SystemUtils.execute("java", "-jar", new File(signDirectory, "signapk.jar").getAbsolutePath(), new File(signDirectory, "platform.x509.pem").getAbsolutePath(), new File(signDirectory, "platform.pk8").getAbsolutePath(), file.getAbsolutePath(), tempFle.getAbsolutePath());
        file.delete();
        FileUtils.moveFile(tempFle, file);
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
public class SystemUtils {

    public static List<String> execute(List<String> parameters) throws Exception {
        ProcessBuilder processBuilder = new ProcessBuilder(parameters).redirectErrorStream(true);
        Process process = processBuilder.start();
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8))) {
            List<String> messages = new ArrayList<>();
            while (true) {
                String message = reader.readLine();
                if (message == null) {
                    break;
                }

                messages.add(message);
            }

            final int exitValue = process.waitFor();

            return messages;
        }
    }

    public static List<String> execute(String... parameters) throws Exception {
        return execute(Arrays.asList(parameters));
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  1. 到这里我们的插件就写完了,现在我们的工程目录结构如下

在这里插入图片描述

  1. 接下来我们需要把制作的插件提供给Android Studio中的app使用,方式有很多种,这里我使用的通过本地仓库的方式

编辑下build.gradle文件,添加maven plugin,内容如下

// 把jar包上传到本地repo仓库,方便在Android Studio中调试使用
apply plugin: 'maven'

uploadArchives {
    repositories {
        mavenDeployer {
            // 调用方式就是 'com.bajingxiaozi.plugin:plugindemo:1.0-SNAPSHOT'
            pom.groupId = 'com.bajingxiaozi.plugin'
            pom.version = '1.0-SNAPSHOT'
            pom.artifactId = 'plugindemo'
            // repo仓库路径,可以使用相对路径
            repository(url: uri('../../repo'))
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

现在我们的build.gradle长下面这样

在这里插入图片描述

然后找到右侧gradle task找到uploadArchives,点击把制作好的插件上传到本地maven仓库

这里本地maven仓库使用的是相对路径,相对于的是你该工程的根目录,不是相对于工程的src目录

  1. 然后我们来测试刚做好的插件,和使用其他插件一样

首先修改Android Studio工程build.gradle如下

在这里插入图片描述

其中本地maven仓库的地址按照自己的情况修改,这里使用的是相对路径

  1. 然后在app模块目录的build.gradle文件中使用此plugin,并配置好之前提供的gradle plugin配置项,如下

在这里插入图片描述

然后gradle sync一下,在右侧app->Tasks->other->hello,就可以找到插件提供的hello的task,可以双击执行测试功能1了,运行结果如下图

在这里插入图片描述

点击Build APK或者直接run工程,测试功能2,运行结果如下图:

在这里插入图片描述

  1. 如果想要修改插件,插件工程重新uploadArchives,然后Android Studio重新sync一下就可以啦,不需要更新版本号

源码参考

插件工程:https://github.com/bajingxiaozi/PluginDemo

Android Studio工程:https://github.com/bajingxiaozi/AndroidGradlePluginDemo

参考资料

https://docs.gradle.org/current/userguide/custom_plugins.html

https://proandroiddev.com/gradlepluginandroidsdk-8a2494cbd238

其他

虽然通过插件完美解决了apk重签名的问题,但是后面发现可以直接把.pem+.pk8转换成keystore,然后就可以直接在gradle里面配置签名文件了

https://www.cnblogs.com/dirt2/p/6237206.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/269885
推荐阅读
相关标签
  

闽ICP备14008679号