修改apk植入动态信息总结

时间:2022-10-30 21:41:07

需求背景

作为游戏的发行平台,在游戏客户端对接SDK后需要进行不同渠道的分发。(一些小发行没有自己的渠道,靠自己的经验选择一些第三方的渠道进行推送,如媒介通过软文链接、xx渠道合作等)那这个时候发行需要收集一些渠道相关的数据信息,给推广提供数据依据。为了区分不同渠道,发行拿到游戏 apk 后,需要针对各个不同的渠道给apk进行标记,标记apk 就涉及到动态修改apk

【这里记录下参考的两篇文章及实现思路原理】

实现方案

技术点前提:

  • 理解apk 本质上是一个 zip 的归档文件

技术要点:

  • 修改apk后,apk文件格式不能损坏、且能正常的被Android安装、文件验证通过

参考1:美团Android自动化之旅—生成渠道包

这篇文章中可借鉴二种方案

  • 1、使用 apk-tool 解压apk 修改 AndroidMainfest.xml 的 meta-data
  • 2、直接修改过apk 在 META-INF 添加空文件,已文件名作为渠道标记

参考2:一种动态为apk写入信息的方案
方案参考:

  • 3、理解zip 的归档文件组织的规则,并利用zip 的 comment 区域加入自定义的struct 用来标记自己想要的信息

对比上面的所有方案,方案1:需要apk tool 解析反编译修改,这导致需要重新签证 apk 、且执行速度比 方案2、3 都比较慢。方案3 对比2 可能扩展性、安全性更好(能够自定义自己的数据结构)所有本人的选择了方案3.

额外说明下:如果对接过腾讯MSDK的可以看到,WGPlatform其中有一接口为,获得对应的渠道号:(开发这个需求自然想到以前对接MSDK的获得渠道接口)

public static String WGGetChannelId()

通过 JD-GUI 反编译分析可以看到如下代码:

  public static String WGGetChannelId() {
return "" + WGPfManager.getInstance().getChannelId();
}
private String getConfigChannelId() {
String channel = "";

Activity act = WeGame.getInstance().getActivity();
String apkSelfFilePath = act.getPackageCodePath();
try
{
String comment = ApkExternalInfoTool.readChannelId(new File(apkSelfFilePath));
Logger.d("Comment: " + comment);
channel = comment;
if (!CommonUtil.ckIsEmpty(channel))
return channel;
}
catch (IOException e) {
e.printStackTrace();
Logger.d("Read apk file for channelId Error");
}

channel = readChannelFromIni();
if (!CommonUtil.ckIsEmpty(channel)) {
return channel;
}

channel = "00000000";
return channel;
}

继续分析可以看到,MSDK 也是利用zip 的 Comment (zip的文件显示概要)区域进行加入特定信息实现的。

ZIP 文件格学习

wiki 地址:Zip (file format)

zip格式图概述:

修改apk植入动态信息总结

这里有意思的一个点记录下:

The name “zip” (meaning “move at high speed”) was suggested by Katz’s friend, Robert Mahoney. They wanted to imply that their product would be faster than ARC and other compression formats of the time

zip 的意思 move at high speed 。为什么?可以看这的例子

For example, we may start with a .ZIP file that contains files A, B and C. File B is then deleted and C updated. This may be achieved by just appending a new file C to the end of the original ZIP file and adding a new central directory that only lists file A and the new file C. When ZIP was first designed, transferring files by floppy disk was common, yet writing to disks was very time consuming. If you had a large zip file, possibly spanning multiple disks, and only needed to update a few files, rather than reading and re-writing all the files, it would be substantially faster to just read the old central directory, append the new files then append an updated central directory.

新浪博客一篇文章 zip文件格式说明能较说明理解。

这里用到的重点是 End of central directory record 这里有 2 两个字节表示的 comment 内容端的长度。

代码实现

这里也只是贴一下github 上一个实现的代码,可以借鉴实现。
MultiChannelPackageTool