实战分享:一行命令搞定加固、签名生成各个市场渠道包
本文作者
作者:binbinqq86
链接:
https://blog.csdn.net/binbinqq86/article/details/81033796
本文由作者授权发布。
本文文章接作者的:3种方法带你玩自定义Android Gradle插件,属于自定义插件的实战篇,这个实战也是比较有意义的,可以说让我受到启发的一篇文章。
我之前鼓励大家去上线个人app,在上市场的过程中,你会发现很多市场是需要用其专门的加固方案的,因为我当时上的少,就一个个手动去上传加固。
其实程序员,更应该学会自动化,在自动化上花再多时间也不过分,磨刀不误砍柴工,作者这方面做的比我好,非常值得我去学习。
也非常建议大家,对各种事情,能够从多角度去看待。
根据标题,我们直接上最终效果图,如果不符合您的需求,您可以绕过,如果能帮助到您,笔者将深感荣幸,谢谢您的支持。
打包完成,来看看我们最终的渠道包:
整个过程实现一行命令,全自动出混淆加固签名渠道包,而且一次性快速全部输出到指定目录,就问你想不想了解一下呢。
由于运营人员需要对不同android市场上投放的渠道包做一些统计分析,用来更加精准的去控制业务方向,所以产生了渠道包一说,原来打渠道包都是打一个包,更换一下manifest里面的meta-data的值,如果项目很大,构建速度将会非常慢,那么打几十上百个市场的渠道包可想而知,是非常耗时耗力,非常痛苦的,我们决不容忍这种浪费时间的操作存在,于是乎就有了各种多渠道打包的技术方案,比如美团一代打包工具(只支持v1签名),美团二代(瓦力,支持v2签名),360加固等等,如此一来,就轻松了解决了这些痛点。
这里我们不去深入研究他们的实现原理,只是简单介绍一下几种不同方案:
原生方案:
其实就是采用gradle去配置不同的productFlavor,然后用manifestPlaceholder占位符去解析manifest文件里面的meta-data的value,来进行打包,耗时耗力,原理就是一个一个包去打,虽然免去了手动,但是很耗时。
美团一代:
这种只有在v1签名的时候才可以这么做,它将APK直接当做zip解压,目录里会有一个META-INF目录而此目录是不参与签名校验的。
因此在META-INF目录内添加不同渠道名的空文件,可以唯一标识一个渠道。采用这种方式,每打一个渠道包只需复制一个apk,在META-INF中添加一个使用渠道号命名的空文件即可。
美团二代:
由于7.0之后的签名机制都是v2了,所以美团一代的打包方式已经不可行了,于是美团出了新的打包方案,就是通过在Apk中的APK Signature Block区块添加自定义的渠道信息来生成渠道包,从而提高了渠道包生成效率,可以作为单机工具来使用,也可以部署在HTTP服务器上来实时处理渠道包Apk的升级网络请求。
打包一次即可完成几百个包的生成
360
360打渠道包也是修改manifest中的meta-data值,但是不区分v1,v2,因为它是先打渠道包,然后再进行签名的,所以没有上述签名引起的问题。
本文将以360为例,去讲解今天的内容。
首先是去创建我们的打包插件,怎么创建gradle插件,可以参考我的另外一篇文章:自定义Android Gradle插件,本文不再赘述。这里我们新建buildSrc工程,然后去360加固官网下载需要的工具,放到我们的源码目录,当然你也可以放其他任何目录:
http://jiagu.360.cn/#/global/download
我们新建了三个groovy文件,PackageExtension是用来扩展gradle配置属性的:
package com.tb.plugin
class PackageExtension{
/**
* app版本号
*/
def appVersion
}
TbPluginPackageApk是我们自定义的打包插件:
package com.tb.plugin
import org.gradle.api.Plugin
import org.gradle.api.Project
/**
* @author tb
* @time 2018/7/3 下午5:20
* @des 打包apk插件
*/
class TbPluginPackageApk implements Plugin<Project> {
void apply(Project project) {
project.extensions.create("packageConfig", PackageExtension)
project.android.applicationVariants.all{
def variantName = it.name.capitalize()
PackageTask task = project.tasks.create("assemble${variantName}Package", PackageTask.class)
task.targetProject = project
task.variant = it
task.doFirst {
println '>>>默认包全部生成,开始打加固签名渠道包。。。'
}
//依赖assemble,需要先编译出所有的该variant的包
task.dependsOn it.assemble
it.outputs.all{
println "appName>>>$it.outputFileName"
}
}
}
}
当然这个插件依赖于assemble任务,需要先编译出一个apk,然后拿着这个文件去360加固签名,打渠道包。
PackageTask就是真正实现我们加固签名渠道包任务的类:
package com.tb.plugin
import com.android.build.gradle.api.ApplicationVariant
import org.gradle.api.DefaultTask
import org.gradle.api.GradleException
import org.gradle.api.Project
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.TaskAction
/**
* @author tb
* @time 2018/7/31 下午3:57
* @des 360加固文档:http://jiagu.360.cn/#/global/help/6
*/
class PackageTask extends DefaultTask {
public Project targetProject
public ApplicationVariant variant
def appVersion
/**
* 360加固工具存放目录
*/
def JIAGU_ROOT_PATH
/**
* 加固完成后存放apk的目录
*/
def JIAGU_COMPLETED_PATH
/**
* 用来存放渠道包的目录
*/
def OUTPUT_CHANNEL_APK_PATH
void packageTask() {
//根据当前运行的系统判断使用哪个版本加固工具
String os = System.getProperties().getProperty("os.name")
println "os is: $os"
if (os.toLowerCase().startsWith('mac')) {
JIAGU_ROOT_PATH = './buildSrc/tools/360mac/jiagu'
} else if (os.toLowerCase().startsWith('linux')) {
// JIAGU_ROOT_PATH = './buildSrc/tools/360linux'
} else {
new RuntimeException('os not support')
return
}
appVersion = targetProject.packageConfig.appVersion
JIAGU_COMPLETED_PATH = "$JIAGU_ROOT_PATH/completed"
OUTPUT_CHANNEL_APK_PATH = "./buildSrc/output"
variant.outputs.all {
def apkFile = it.outputFile
if (apkFile == null || !apkFile.exists()) {
throw new GradleException("$apkFile doesn't exists!!!")
}
def out = new StringBuilder()
def err = new StringBuilder()
//先移除目录,再新建
def rm = "rm -rf $JIAGU_COMPLETED_PATH".execute()
rm.waitForProcessOutput(out, err)
println "tb===rm -rf $JIAGU_COMPLETED_PATH>>>$out>>>$err"
def mkdir = "mkdir $JIAGU_COMPLETED_PATH".execute()
mkdir.waitForProcessOutput()
println "tb===mkdir $JIAGU_COMPLETED_PATH>>>$out>>>$err"
//先登陆会保存到db数据库,登陆一次即可
//加固(必须先签名apk才能加固),加固后需要重新签名
//使用360自动渠道包+自动签名,需要先导入渠道信息和签名信息
// 保证output文件夹存在
"rm -rf $OUTPUT_CHANNEL_APK_PATH".execute().waitForProcessOutput(out, err)
"mkdir $OUTPUT_CHANNEL_APK_PATH".execute().waitForProcessOutput(out, err)
"chmod 777 $OUTPUT_CHANNEL_APK_PATH".execute().waitForProcessOutput(out, err)
def cmd = "java -jar $JIAGU_ROOT_PATH/jiagu.jar -jiagu $apkFile $OUTPUT_CHANNEL_APK_PATH -autosign -automulpkg".execute()
cmd.in.eachLine {
println "tb===>>>$it"
}
//使用分步方式:加固、签名、渠道包========================================================================================
// def jg = "java -jar $JIAGU_ROOT_PATH/jiagu.jar -jiagu $apkFile $JIAGU_COMPLETED_PATH".execute()
// jg.in.eachLine {
// println "tb>>>===$it"
// }
//此处也可以先签名,然后使用美团的瓦力去打渠道包,不过不是写入manifest文件的meta-data中,可以用sdk直接获取渠道号
// def ls="ls $JIAGU_COMPLETED_PATH".execute()
// ls.waitForProcessOutput(out,err)
// println "tb===已加固文件:$out>>>$err"
}
}
}
里面的注释写的非常详细了,基本过程就是拿到我们编译出来的apk,然后调用360加固的一些命令,这里的命令全部都是参考官方文档,没有难度。
唯一要注意的几个点:
首先需要先进行登陆360,自己在命令行执行一次即可,信息会保存在jiagu.db的数据库中,所以这里不去写在这个代码里了,我们打开mac的终端,调用命令:
java -jar 加固目录/jiagu.jar -login username password
登陆成功后即可进行上传apk,另外就是需要在官网先配置一下用户信息,也就是开发者信息,简单填写即可。
然后可以进行一些可选增强服务,比如升级通知服务,崩溃日志服务,消息推送服务,支持x86架构设备服务,这里我们选崩溃日志和x86支持.
java -jar 加固目录/jiagu.jar -config -x86 -crashlog
360支持一行命令实现加固,出渠道包,签名一条龙服务,当然你也可以自己去分步实现各个环节,这里的一条龙前提就是你要配置好签名信息和渠道信息,命令也非常简单,如下:
java -jar 加固目录/jiagu.jar -improtsign 签名绝对路径
java -jar 加固目录/jiagu.jar -importmulpkg 渠道文件绝对路径
导入完成后,可以使用如下命令去查看:
java -jar 加固目录/jiagu.jar -showsign
java -jar 加固目录/jiagu.jar -showmulpkg
至此,准备工作就完成了,下面在我们的主工程里面配置打包命令,也就是我们的app所在module的build.gradle文件:
这里我们配置了packageConfig,新建了一个task,名字为assembleChannel,意思就是打渠道包,它依赖于assembleReleasePackage这个任务,这个任务就是我们插件里面建立的任务,所以任务的执行依赖关系如下:
assembleChannel
—>assembleReleasePackage
—>assembleRelease
下面我们在Android studio的Terminal输入如下命令:
./gradlew clean assembleChannel
敲一下回车,就出现了我们文章开头的效果图,一行命令,打包完成,收工~
去360加固个人中心也可以看到我们上传的加固签名等信息,非常方便:
最后
最后就不多说废话了,还有不明白的童鞋可以点击原文,给作者留言。
https://github.com/binbinqq86/tbPlugin
推荐阅读:
扫一扫 关注我的公众号
如果你想要跟大家分享你的文章,欢迎投稿~
┏(^0^)┛明天见!