![ff24fc33eb96ab992717d5fadc98296c.png](https://img-blog.csdnimg.cn/img_convert/ff24fc33eb96ab992717d5fadc98296c.png)
标签: 多渠道打包 , 动态写入APK , V2签名
如何实现快速多渠道打包? 如何将 Git 的 SHA-1 值、打包时间、友盟渠道等自定义信息写入到 APK 中?
这就需要我们今天要分享的技术了:动态写入信息到 apk。
一、核心干货
- 如果只用 V1 签名,放到 apk 的 META-INFO 目录即可。本篇讨论 V2 签名的情况。
- 在 V2 签名块中,签名信息是放在了 ID = 0x7109871a 的键值对块中。我们可以把其他自定义数据,也按照键值对块的格式,插入到签名块中。再修改 EoCDR[^1] 的中央目录偏移量以及签名块大小,就能在不破坏签名的情况下往 apk 文件中插入自定义数据。为了避免和系统签名冲突,ID不能使用 0x7109871a(V2签名块的ID) 和 0xf05368c0(V3签名块的ID) 。
如果对 Zip 文件格式和 V2 签名块格式不了解,请移步到:《Android 端 V1/V2/V3 签名的原理》。这里只放一张 Zip 文件的结构图:
![65056478a474599c6774cf352f36e18c.png](https://img-blog.csdnimg.cn/img_convert/65056478a474599c6774cf352f36e18c.png)
二、具体实现
这篇文章会用 EoCDR 表示 Zip 文件的 End of Central Directory Record 区域。 接下来我们用 Kotlin 来实现「动态写入信息到apk」和「从apk中读取信息」:
1. 写入信息到 apk
先高屋建瓴地看一下写入时的详细步骤:
( 1). 获取注释长度;
( 2). 获取 EoCDR 的长度;
( 3). 得到 EoCDR 的偏移量;
( 4). 找到『保存了「中央目录区偏移量」的偏移量』位置A;
( 5). 读取A, 读取中央目录偏移量 centralDirOffset;
( 6). 根据 centralDirOffset, 读取和验证 v2 签名的魔数;
( 7). 验证通过后,获取两个『保存「签名块的大小」的位置』C1、C2 和签名块大小;
( 8). 将想要插入的数据,按照格式转为字节数组 bytes;
( 9). 将 bytes 插入到 C2 之前;
(10). 更新 C1 和 C2 对应的值为 signBlockSize + bytes.size;
(11). 更新位置A的值为 centralDirOffset + bytes.size;
下面我们一步步来实现:
(1) 获取注释长度
在 Java 中,可以通过 ZipFile 获取注释的