赞
踩
IntelliJ IDEA 2019.3.4
Oracle JDK1.8
Android Studio 3.6.1
工作中遇到的一个问题,系统开发过程中,系统方提供了.pem
+.pk8
文件把apk重签名为系统应用,每次需要在Android Studio中先编译出来apk,然后再打开控制台输入重签名的命令将apk重签名,然后再通过adb命令将重签名之后的apk安装进去。很不方便,不能直接使用Android Studio直接run。所以准备写一个gradle的插件,来帮助我做这一部分工作,可以直接在Android Studio中点击run的时候直接将apk重签名然后安装到机器中。
本篇教程有两个目的,阅读完本片教程后你应该可以学会一个Android gradle插件的开发了
建议使用
IntelliJ IDEA
进行gradle插件开发,对groovy
的支持比Android Studio
好多了
分下面几步
build.gradle
文件,修改下面两个地方,修改之后sync一下,更新一下依赖添加groovy插件支持
id 'groovy'
添加gradle插件依赖
implementation gradleApi()
implementation localGroovy()
现在你的build.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名称,这个不需要和包名一样。
然后我们现在来给这个插件添加一些功能,重写DemoPlugin
的apply(Project project)
方法
功能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
}
}
}
}
其中project.task
就是创建task的方法
doLast
就是在task执行之后进行的操作
project.android
就是引用android
插件了,可以通过project.android
来进行对android
插件的一些操作了
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") } } }
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;
}
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); } }
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)); } }
编辑下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'))
}
}
}
现在我们的build.gradle
长下面这样
然后找到右侧gradle task找到uploadArchives
,点击把制作好的插件上传到本地maven仓库
。
这里本地maven仓库使用的是相对路径
,相对于的是你该工程的根目录,不是相对于工程的src
目录
首先修改Android Studio工程build.gradle
如下
其中本地maven仓库的地址按照自己的情况修改,这里使用的是相对路径
build.gradle
文件中使用此plugin,并配置好之前提供的gradle plugin配置项,如下然后gradle sync一下,在右侧app->Tasks->other->hello
,就可以找到插件提供的hello
的task,可以双击执行测试功能1了,运行结果如下图
点击Build APK或者直接run工程,测试功能2,运行结果如下图:
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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。