13 KiB
STEP-080 — Android AAR 与 RN Test Host 标准构建流水线 v2
状态:已按真实 Linux → pbf → Windows 11 → Android 模拟器链路验证通过
日期:2026-09-14
1. 目的
本文固定 MapLibreParticleLab Android Native AAR 完成后,到 Windows 11 构建 RN Test Host、启动 Metro、安装 App、执行 QBIN V4 验证的标准流程。
以后正常验证不得再临时复制 AAR、临时改 MavenLocal、在 Windows 重编 Native AAR,或凭经验猜 Metro 端口。
2. 最终权威链路
Linux MapLibreParticleLab
→ 编译 Native OpenGL AAR
→ 发布到 /mnt/nas/pbf/maven
→ 公网 https://pbf.jpcn.ccwu.cc/maven
Linux RN package
→ npm pack
→ 发布到 /mnt/nas/pbf/npm
→ 公网 https://pbf.jpcn.ccwu.cc/npm
Windows 11 RN Test Host
→ npm install 公网 tgz
→ Gradle 从公网 Maven 自动取得 Native AAR
→ Expo prebuild
→ assembleDebug
→ Metro :8091
→ adb reverse 8081 → 8091
→ 安装并启动 App
→ QBIN V4 真机/模拟器验证
3. Linux 与 Windows 的职责边界
Linux 负责
- MapLibre Native Android OpenGL AAR 编译。
- Native AAR 版本管理。
- RN package 打包。
- AAR/POM/module 与 RN tgz 发布到 pbf。
- 公网回读并校验 SHA-256。
Windows 11 负责
- 从 pbf npm 安装 RN package。
- 通过 Gradle 从 pbf Maven 消费对应 Native AAR。
- Expo prebuild。
- Test Host Debug APK 编译。
- Metro、ADB reverse、安装、启动和人工验证。
禁止
- Windows 正常流程中重新编译 MapLibre Native AAR。
- Windows 正常流程中使用 Maven Local 替代 pbf Maven。
- Linux 与 Windows 之间通过局域网临时复制 AAR 作为正式验证路径。
- 覆盖旧 Maven 版本坐标。
4. 版本一致性硬门槛
以当前已验证版本为例:
RN package = 13.4.1-particle.3
Native AAR = 13.4.1-particle.3
以下位置必须全部一致,否则停止构建:
platform/android/VERSIONpackages/maplibre-particle-rn/package.jsonpackages/maplibre-particle-rn/android/build.gradlepackages/maplibre-particle-rn/app.plugin.jsintegration/react-native/MapLibreParticleRNTestHost/plugins/withParticleNativeAndroid.js
5. Linux:AAR 构建与发布
推荐使用仓库内标准脚本:
cd /mnt/sda1/MapLibreParticleLab
tools/particle_android_pipeline/linux_build_publish.sh
如果只是检查版本、SDK、路径和发布条件:
tools/particle_android_pipeline/linux_build_publish.sh --preflight
Linux Android SDK 当前实际路径:
/root/Android/Sdk
AAR 必须使用新的版本目录发布,不能覆盖历史 .2:
/mnt/nas/pbf/maven/cc/navsea/maplibre/android-sdk-particle-opengl/<version>/
当前 .3 目录为:
/mnt/nas/pbf/maven/cc/navsea/maplibre/android-sdk-particle-opengl/13.4.1-particle.3/
至少包含:
android-sdk-particle-opengl-13.4.1-particle.3.aar
android-sdk-particle-opengl-13.4.1-particle.3.pom
android-sdk-particle-opengl-13.4.1-particle.3.module
RN package 使用 npm pack 生成,并发布到:
/mnt/nas/pbf/npm/navsea-maplibre-particle-rn-<version>.tgz
6. Linux:把 AAR 正式发布到公网 pbf
https://pbf.jpcn.ccwu.cc/ 的服务器文件根目录固定映射为:
/mnt/nas/pbf
因此 Maven 公网根:
https://pbf.jpcn.ccwu.cc/maven/
对应 Linux:
/mnt/nas/pbf/maven/
npm/tgz 公网根:
https://pbf.jpcn.ccwu.cc/npm/
对应 Linux:
/mnt/nas/pbf/npm/
发布不需要 SSH 到其他服务器,也不需要从 Win11 上传;Linux 直接写 /mnt/nas/pbf 即完成公网发布。
6.1 发布 Native AAR
先定义版本:
VERSION=13.4.1-particle.3
GROUP_PATH=cc/navsea/maplibre/android-sdk-particle-opengl
SRC="$HOME/.m2/repository/$GROUP_PATH/$VERSION"
DST="/mnt/nas/pbf/maven/$GROUP_PATH/$VERSION"
正常发布必须使用一个从未发布过的新版本。先保护旧版本:
test ! -e "$DST" || {
echo "目标版本已经存在,禁止覆盖:$DST" >&2
exit 1
}
确认本地 Maven publication 完整:
ls -lh "$SRC"
sha256sum "$SRC/android-sdk-particle-opengl-$VERSION.aar"
创建公网 Maven 版本目录并复制:
mkdir -p "$DST"
cp -a "$SRC"/. "$DST"/
至少确认:
test -f "$DST/android-sdk-particle-opengl-$VERSION.aar"
test -f "$DST/android-sdk-particle-opengl-$VERSION.pom"
test -f "$DST/android-sdk-particle-opengl-$VERSION.module"
6.2 公网回读验证 AAR
公网 URL 规则:
https://pbf.jpcn.ccwu.cc/maven/cc/navsea/maplibre/android-sdk-particle-opengl/<VERSION>/android-sdk-particle-opengl-<VERSION>.aar
发布后必须从公网重新下载,不允许只检查 /mnt/nas/pbf 本地文件:
LOCAL_AAR="$DST/android-sdk-particle-opengl-$VERSION.aar"
PUBLIC_AAR="https://pbf.jpcn.ccwu.cc/maven/$GROUP_PATH/$VERSION/android-sdk-particle-opengl-$VERSION.aar"
TMP_AAR="$(mktemp)"
curl -fL "${PUBLIC_AAR}?nocache=$(date +%s)" -o "$TMP_AAR"
sha256sum "$LOCAL_AAR" "$TMP_AAR"
cmp -s "$LOCAL_AAR" "$TMP_AAR"
cmp 必须返回 0。只有公网回读字节完全一致,才算 AAR 发布完成。
同时可验证 POM/module HTTP 200:
curl -fI "https://pbf.jpcn.ccwu.cc/maven/$GROUP_PATH/$VERSION/android-sdk-particle-opengl-$VERSION.pom"
curl -fI "https://pbf.jpcn.ccwu.cc/maven/$GROUP_PATH/$VERSION/android-sdk-particle-opengl-$VERSION.module"
6.3 发布 RN package 到公网 npm 目录
在仓库中生成 tgz:
cd /mnt/sda1/MapLibreParticleLab/packages/maplibre-particle-rn
npm pack
生成文件示例:
navsea-maplibre-particle-rn-13.4.1-particle.3.tgz
正式发布路径:
TGZ="navsea-maplibre-particle-rn-$VERSION.tgz"
PUBLIC_TGZ_DIR="/mnt/nas/pbf/npm"
test ! -e "$PUBLIC_TGZ_DIR/$TGZ" || {
echo "公网同版本 tgz 已存在,禁止覆盖;请升级版本" >&2
exit 1
}
cp "$TGZ" "$PUBLIC_TGZ_DIR/$TGZ"
公网 URL:
https://pbf.jpcn.ccwu.cc/npm/navsea-maplibre-particle-rn-<VERSION>.tgz
发布后必须公网回读并比较 SHA:
TMP_TGZ="$(mktemp)"
curl -fL "https://pbf.jpcn.ccwu.cc/npm/$TGZ?nocache=$(date +%s)" -o "$TMP_TGZ"
sha256sum "$TGZ" "$TMP_TGZ"
cmp -s "$TGZ" "$TMP_TGZ"
正常发布不得重新覆盖同一版本的 tgz。今天 .3 的覆盖属于修复历史错误包的例外,不应成为日常流程。
7. Windows 11:从公网取得 RN package 与 AAR
Windows 正常流程不直接下载 AAR 文件。AAR 由 Gradle 根据 RN package 中的 Maven coordinate 自动从 pbf Maven 获取。
当前 Test Host 建议工作目录:
D:\React\MapLibreParticleRNTestHost-V4
不要在 V:\ 盘符根目录执行 Expo prebuild;本次实测 Expo autolinking 在盘符根目录会出现 Couldn't find package.json up from path V:\。
7.1 安装 RN package
cd D:\React\MapLibreParticleRNTestHost-V4
npm install --force `
https://pbf.jpcn.ccwu.cc/npm/navsea-maplibre-particle-rn-13.4.1-particle.3.tgz
正常情况下新版本不需要清 npm cache;只有确认同版本曾被错误覆盖时才做:
npm cache clean --force
安装后必须核对实际依赖:
Get-Content node_modules\@navsea\maplibre-particle-rn\package.json
Select-String `
-Path node_modules\@navsea\maplibre-particle-rn\android\build.gradle `
-Pattern 'android-sdk-particle-opengl'
必须看到目标版本,例如:
cc.navsea.maplibre:android-sdk-particle-opengl:13.4.1-particle.3
7.2 Expo prebuild 与 Android SDK
执行:
cd D:\React\MapLibreParticleRNTestHost-V4
npx expo prebuild --platform android
Windows Android SDK 当前实际路径:
C:\Users\taibe\AppData\Local\Android\Sdk
如果 Gradle 报 SDK location not found,优先在当前 PowerShell 显式设置:
$env:ANDROID_HOME='C:\Users\taibe\AppData\Local\Android\Sdk'
$env:ANDROID_SDK_ROOT='C:\Users\taibe\AppData\Local\Android\Sdk'
并写入:
D:\React\MapLibreParticleRNTestHost-V4\android\local.properties
内容:
sdk.dir=C\:\\Users\\taibe\\AppData\\Local\\Android\\Sdk
7.3 构建 Debug APK
cd D:\React\MapLibreParticleRNTestHost-V4\android
$env:ANDROID_HOME='C:\Users\taibe\AppData\Local\Android\Sdk'
$env:ANDROID_SDK_ROOT=$env:ANDROID_HOME
.\gradlew.bat :app:assembleDebug
成功产物:
D:\React\MapLibreParticleRNTestHost-V4\android\app\build\outputs\apk\debug\app-debug.apk
8. Metro、ADB reverse、安装与启动
Test Host 的固定规则是:
Metro 实际监听端口:8091
App 默认访问端口:8081
ADB reverse:tcp:8081 → tcp:8091
8.1 启动 Metro
cd D:\React\MapLibreParticleRNTestHost-V4
npx expo start --port 8091 --clear
8.2 配置 reverse
另开一个 PowerShell:
adb -s 192.168.1.146 reverse --remove-all
adb -s 192.168.1.146 reverse tcp:8081 tcp:8091
adb -s 192.168.1.146 reverse --list
必须看到:
tcp:8081 tcp:8091
8.3 安装并启动
adb -s 192.168.1.146 install -r `
D:\React\MapLibreParticleRNTestHost-V4\android\app\build\outputs\apk\debug\app-debug.apk
adb -s 192.168.1.146 shell am force-stop org.maplibre.particle.rntesthost
adb -s 192.168.1.146 shell am start `
-n org.maplibre.particle.rntesthost/.MainActivity
9. V3 fixture 与 Metro watchFolders
当前 Test Host 同时保留旧 V3 数据集和 V4 QBIN 数据集。
独立 Windows Host 使用:
D:\React\MapLibreParticleRNTestHost-V4
D:\React\particle-v3-fields
src/fieldDatasets.ts 使用 ../../particle-v3-fields/...,因此这些 fixture 位于 Metro 项目根之外。
此时 metro.config.js 必须把外部 fixture 目录加入 watchFolders,例如独立 Windows Host:
const path = require("path");
const { getDefaultConfig } = require("expo/metro-config");
const config = getDefaultConfig(__dirname);
config.resolver.assetExts = [...new Set([...config.resolver.assetExts, "f32", "u8", "qbin"])];
config.watchFolders = [
path.resolve(__dirname, "..", "particle-v3-fields"),
];
module.exports = config;
修改 metro.config.js 后必须重启 Metro,普通 Reload 不足以保证配置重载。
如果看到:
Unable to resolve ../../particle-v3-fields/...
先确认文件实际存在,再检查 watchFolders;不要重复复制同一批 fixture 或误判为 QBIN 问题。
10. QBIN V4 验收确认
V4 测试区必须走:
assets/qbin-golden/*.qbin
→ FieldRuntime.submitEncodedField(...)
→ WeatherRuntimeBridgeModule.submitEncodedField(...)
→ WeatherRuntime.submitEncodedField(...)
→ JNI native_map_view.cpp
→ RasterArraySource::submitEncodedField(...)
→ QbinV2Decoder::decode(...)
这与旧 V3 metadata.json + .f32 + .u8 → submitField(...) 是两条不同链路。
至少验证:
- V4 Wind:T0/T1 load、Color Binding、Particle Binding、T0/midpoint/T1 seek。
- V4 Wave:同上。
- V4 Current:同上。
- V4 Rain:Color Binding、T0/midpoint/T1;Particle Binding 为 N/A。
- PLAY / PAUSE / playback speed。
clearEncodedField/clearAllEncodedFields。
人工确认 V4 功能正常后,才可判定 Windows Android QBIN V4 验证通过。
11. 本次 .3 已验证发布基线
Native AAR:
cc.navsea.maplibre:android-sdk-particle-opengl:13.4.1-particle.3
SHA-256: 9ef03eb0d0c03457adc04847cfa69fb67d85191daecd64d3b76db2ad8cc688cd
最终修正后的 RN tgz:
https://pbf.jpcn.ccwu.cc/npm/navsea-maplibre-particle-rn-13.4.1-particle.3.tgz
SHA-256: abdd5b5f313b6dc2bc2f2b00848d1901be72fed6a6e1fa15899efb10df9f923f
Windows 11 Debug APK 已于 2026-09-14 成功构建、安装并由用户完成功能验证。
12. 本次实际踩过的弯路与固定处理
A. Win11 不要重编 Native AAR
症状:为了验证 Test Host,又在 Windows 尝试重建 MapLibre Native。
固定规则:Native AAR 只在 Linux 生产;Windows 只通过 pbf Maven 消费。
B. 不要用局域网复制 AAR 作为正常路径
固定规则:Linux 发布到 /mnt/nas/pbf/maven,Windows Gradle 从 https://pbf.jpcn.ccwu.cc/maven 获取。
C. RN package 版本号相同但内部仍依赖旧 AAR
必须检查 android/build.gradle、app.plugin.js、Test Host plugin 的 Maven coordinate,不能只看 package.json 版本号。
D. Android Kotlin 必须实编译
Linux TypeScript/Core 检查无法替代 Android Kotlin 编译。本次实际发现 value >= if (...) 在 Kotlin 编译器下失败,最终改为显式括号与 Double 常量。
E. Expo 不要在 V:\ 根目录 prebuild
本次实际出现 Couldn't find package.json up from path V:\。固定使用普通子目录,例如 D:\React\MapLibreParticleRNTestHost-V4。
F. App 报 localhost:8081,而 Metro 在 8091
这是正常设计,不要把 Metro 改回 8081。正确映射是:
adb reverse tcp:8081 tcp:8091
G. fixture 文件存在但 Metro 仍 Unable to resolve
优先检查 watchFolders,不要重复复制 fixture。仓库 Test Host 的 metro.config.js 已加入仓库布局/独立 Windows 布局自动探测。
13. 文档优先级
本文件 v2 覆盖 STEP-080 v1 中“Linux bundle → Windows MavenLocal”的正常发布结论。
tools/particle_android_pipeline/ 中旧脚本保留用于历史/离线用途;正常联网验证以本文的 pbf 公网链路为准。