提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
此方案实则采用两种集成方案分别对V1、V2签名的apk包进行处理
一、V1签名apk渠道号注入
apk本身就是一个zip格式的文件,所以我们从zip格式下手,在zip文件的某一个特殊的区域放入我们需要的信息,而不损坏apk本身,经过探寻发现,在 zip 文件的末尾有一个 Central Directory Record 区域,其末尾包含一个 File comment 区域,可以存放一些数据,所以 File comment 是 zip 文件一部分,如果可以正确的修改这个部分,就可以在不破坏压缩包、不用重新打包的的前提下快速的给 Apk 文件写入自己想要的数据。
欲知详情,请移步:Apk动态写入信息
二、V2签名apk渠道号注入
V2签名apk渠道号注入采用的是美团Walle方案。
1.美团Walle方案
新的签名方案会在ZIP文件格式的 Central Directory 区块所在文件位置的前面添加一个APK Signing Block区块,下面按照ZIP文件的格式来分析新应用签名方案签名后的APK包。
整个APK(ZIP文件格式)会被分为以下四个区块: 1. Contents of ZIP entries(from offset 0 until the start of APK Signing Block) 2. APK Signing Block 3. ZIP Central Directory 4. ZIP End of Central Directory
之前的渠道包生成方案是通过在META-INF目录下添加空文件,用空文件的名称来作为渠道的唯一标识及comment 区域增加内容,是不需要重新签名应用的,这样会节省不少打包的时间,从而提高打渠道包的速度。但在新的应用签名方案下META-INF已经被列入了保护区了,向META-INF添加空文件的方案会对区块1、3、4都会有影响,新应用签名方案签署的应用经过我们旧的生成渠道包方案处理后,在安装时会报以下错误:
Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES:
Failed to collect certificates from base.apk: META-INF/CERT.SF indicates base.apk is signed using APK Signature Scheme v2,
but no such signature was found. Signature stripped?]
而美团Walle方案通过往可扩展的APK Signature Scheme v2 Block中写入,完美实现了V2签名下的渠道包注入
欲知详情,请移步新一代开源Android渠道包生成工具Walle
三、方案集成
既然知道了怎么方案,就可以直接撸代码了。
1.渠道号注入
先通过Walle方案中提供的方案,判断apk包是否是V2签名,是则使用V2签名方案,否则使用V1签名方案
private static void write(String path,String channel){
System.out.println("---------------write start------------------");
File file = new File(path);
boolean isV2Sign = false;
try {
isV2Sign = SignUtils.isV2Sign(file);
if (isV2Sign){
ChannelWriter.put(file,channel);
System.out.println("write V2:"+channel);
} else {
FileUtils.writeApk(file,channel);
System.out.println("write V1:"+channel);
}
} catch (IOException | SignatureNotFoundException e) {
e.printStackTrace();
}
System.out.println("---------------write end------------------");
}
2.渠道号读取
读取则是先读取V2渠道号,为空则读取V1渠道号。当然也可以使用写入时的方式,先判断签名方式,这里就偷个懒,使用这种简单的方式。
private static void read(String path){
System.out.println("---------------read start------------------");
String channel = "";
ChannelInfo channelInfo = WalleChannelReader.getChannelInfo(path);
if (channelInfo!=null){
channel = channelInfo.getChannel();
System.out.println("V2:"+channel);
} else {
channel = GetChannelMsgUtil.readApk(path);
System.out.println("V1:"+channel);
}
System.out.println("---------------read end------------------");
}
3.编译成可执行jar包
详情:Android studio编译可执行jar包
使用:
1.写入
java -jar getChannel.jar w path channel
w表示写入模式,path为apk包全路径,channel为需写入的渠道号
2.读取
java -jar getChannel.jar r path
r表示读取模式,path为apk包全路径
总结
此文章主要是记录,大神请轻喷。
jar包待审核中,过了第一时间贴出来。