87 lines
2.3 KiB
Markdown
87 lines
2.3 KiB
Markdown
# apkdiff
|
||
|
||
APK 增量更新模块,基于 [bsdiff](https://github.com/mendsley/bsdiff) + zlib + minizip。
|
||
|
||
通过对比新旧 APK 中每个文件的内容差异,生成体积远小于完整 APK 的 patch 文件,在设备端应用 patch 生成新 APK。
|
||
|
||
## 结构
|
||
|
||
```
|
||
├── bsdiff.c / bsdiff.h # bsdiff 核心算法(原库,未修改)
|
||
├── bspatch.c / bspatch.h # bspatch 核心算法(原库,未修改)
|
||
├── common/
|
||
│ ├── patch_format.h # Patch 文件格式定义
|
||
│ └── zlib_stream.h/.c # zlib 压缩/解压,适配 bsdiff/bspatch stream
|
||
├── gen/
|
||
│ ├── CMakeLists.txt # 构建 gen.exe
|
||
│ └── main.c # Patch 生成工具入口
|
||
├── jni/
|
||
│ ├── CMakeLists.txt # NDK CMake 构建
|
||
│ ├── Android.mk # 备选 ndk-build 构建
|
||
│ ├── Application.mk # NDK 配置
|
||
│ ├── apkpatch.c # JNI native 实现
|
||
│ └── Patcher.kt # Kotlin 包装类
|
||
└── third_party/
|
||
└── zlib/ # zlib 源码(作为 submodule 或直接包含)
|
||
```
|
||
|
||
## Patch 文件格式
|
||
|
||
```
|
||
Header:
|
||
[16B] Magic "APKDIFF/1.0\0\0\0"
|
||
[4B] uint32_t entry_count
|
||
|
||
Entry (×entry_count):
|
||
[2B] uint16_t path_len
|
||
[NB] path
|
||
[1B] type (0=PATCH, 1=NEW, 2=COPY)
|
||
[8B] int64_t old_size
|
||
[8B] int64_t new_size
|
||
[4B] uint32_t compressed_size
|
||
[NB] zlib compressed data (COPY 时无数据)
|
||
```
|
||
|
||
## gen.exe 编译(Windows)
|
||
|
||
需要 MSVC + CMake:
|
||
|
||
```bash
|
||
cmake -B gen/build -S gen -G "Visual Studio 18 2026" -A x64
|
||
cmake --build gen/build --config Release
|
||
```
|
||
|
||
## gen.exe 用法
|
||
|
||
```bash
|
||
gen.exe <old.apk> <new.apk> <output.patch>
|
||
```
|
||
|
||
## JNI 编译(Android NDK)
|
||
|
||
```bash
|
||
cmake -B jni/build/arm64-v8a -S jni \
|
||
-G "Unix Makefiles" \
|
||
-DCMAKE_TOOLCHAIN_FILE=<NDK>/build/cmake/android.toolchain.cmake \
|
||
-DANDROID_ABI=arm64-v8a \
|
||
-DANDROID_PLATFORM=android-21 \
|
||
-DCMAKE_BUILD_TYPE=Release \
|
||
-DCMAKE_MAKE_PROGRAM=<NDK>/prebuilt/windows-x86_64/bin/make.exe
|
||
|
||
make -C jni/build/arm64-v8a -j8
|
||
```
|
||
|
||
## Android 端使用
|
||
|
||
```kotlin
|
||
import love.qz.apkpatcher.Patcher
|
||
|
||
val oldApk = context.applicationInfo.sourceDir
|
||
val result = Patcher.applyPatch(oldApk, patchPath, newApkPath)
|
||
// result == 0 → 成功
|
||
```
|
||
|
||
## License
|
||
|
||
BSD 2-Clause (bsdiff/bspatch), zlib License (zlib/minizip)
|