实战分享:一行命令搞定加固、签名生成各个市场渠道包

本文文章接作者的:3种方法带你玩自定义Android Gradle插件,属于自定义插件的实战篇,这个实战也是比较有意义的,可以说让我受到启发的一篇文章。

我之前鼓励大家去上线个人app,在上市场的过程中,你会发现很多市场是需要用其专门的加固方案的,因为我当时上的少,就一个个手动去上传加固。

其实程序员,更应该学会自动化,在自动化上花再多时间也不过分,磨刀不误砍柴工,作者这方面做的比我好,非常值得我去学习。

也非常建议大家,对各种事情,能够从多角度去看待。

1

最终效果

根据标题,我们直接上最终效果图,如果不符合您的需求,您可以绕过,如果能帮助到您,笔者将深感荣幸,谢谢您的支持。

实战分享:一行命令搞定加固、签名生成各个市场渠道包

打包完成,来看看我们最终的渠道包:

实战分享:一行命令搞定加固、签名生成各个市场渠道包

整个过程实现一行命令,全自动出混淆加固签名渠道包,而且一次性快速全部输出到指定目录,就问你想不想了解一下呢。

2

背景

由于运营人员需要对不同android市场上投放的渠道包做一些统计分析,用来更加精准的去控制业务方向,所以产生了渠道包一说,原来打渠道包都是打一个包,更换一下manifest里面的meta-data的值,如果项目很大,构建速度将会非常慢,那么打几十上百个市场的渠道包可想而知,是非常耗时耗力,非常痛苦的,我们决不容忍这种浪费时间的操作存在,于是乎就有了各种多渠道打包的技术方案,比如美团一代打包工具(只支持v1签名),美团二代(瓦力,支持v2签名),360加固等等,如此一来,就轻松了解决了这些痛点。

3

实现原理

这里我们不去深入研究他们的实现原理,只是简单介绍一下几种不同方案:

原生方案:

其实就是采用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为例,去讲解今天的内容。

4

开始编码

首先是去创建我们的打包插件,怎么创建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> {
 @Override
 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 {
 @Input
 public Project targetProject
 @Input
 public ApplicationVariant variant
 def appVersion
 /**
 * 360加固工具存放目录
 */
 def JIAGU_ROOT_PATH
 /**
 * 加固完成后存放apk的目录
 */
 def JIAGU_COMPLETED_PATH
 /**
 * 用来存放渠道包的目录
 */
 def OUTPUT_CHANNEL_APK_PATH
 @TaskAction
 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

相关推荐