Files
MapLibreParticleLab/integration/react-native/MapLibreParticleRNTestHost

MapLibreParticleRNTestHost

这是 MapLibreParticleLab 内的独立 React Native 开发宿主,不是 NavSea 业务应用。它只有一个 MLRNMapView 与 WeatherRuntime 控制页,用于证明低频控制面:React 的 reactTag 经薄 Android 模块定位该 View,再定位该 View 的 MapLibreMap 与 map-owned WeatherRuntime。

版本与首次 prebuild 边界

  • package manager 为 npm(packageManager: npm@10.9.4),锁文件为 package-lock.json;当前环境的 npm ci --dry-run --ignore-scripts 无须 --legacy-peer-deps 即可解析。
  • package 明确固定 React Native 0.85.2、React 19.2.3、Expo 56.0.4、TypeScript 5.9.3、MLRN 11.3.6;app.json 明确请求 New Architecture。Hermes 的最终启用状态必须在首次 Android prebuild 后检查生成工程。
  • AGP 8.5.0、Gradle 8.14.3、Kotlin 2.1.20、NDK 27.1.12297006、JDK 17、minSdk 24、compile/targetSdk 36 是本 Test Host 的人工验收配置目标,不是尚未生成 Android 工程的已验证结果。首次 prebuild 后必须以实际 Gradle wrapper、AGP/Kotlin plugin、SDK/NDK 与 Hermes/New Architecture 配置为准核对。
  • MLRN 的 root Gradle extras 固定 org.maplibre.reactnative.nativeVersion=13.4.1-step060d 与 nativeVariant=opengl;这是 STEP-060D attach 诊断 AAR 的唯一临时版本,避免与先前 13.4.1 Maven Local artifact 缓存混淆。

Custom SDK 来源(手工执行)

Gate C 封存环境负责生成 custom AAR;Test Host 只负责 Maven Local handoff。Expo plugin 对唯一 custom 坐标 org.maplibre.gl:android-sdk-opengl 排除 Maven Central,而将 Maven Local 排在首位。因此未先发布本仓库 custom SDK 时 dependency resolution 必须失败,不能悄悄使用官方 SDK;MLRN 的独立 turf/annotation/scalebar 依赖不被这个 SDK-only 排除误伤。

cd /mnt/sda1/MapLibreParticleLab/platform/android
# 仅当 checkout 已变化,或下方已核对 AAR 的 SHA-256 不一致时才需要:
RENDERER=opengl BUILDTYPE=Release make apackage
# 当前 Gate C 已生成并核对的 AAR 可直接发布,不需要为 STEP-060C 重建:
./gradlew :MapLibreAndroid:publishOpenglreleasePublicationToMavenLocal --console=plain
cd /mnt/sda1/MapLibreParticleLab/integration/react-native/MapLibreParticleRNTestHost
npm ci
npx expo prebuild --platform android --clean
npx expo run:android

上述 Android 命令必须在 Gate C 封存 Linux 环境由用户手工执行;本 Step 的 Codex 没有执行。STEP-060C 的 Maven Local publication 已于 2026-09-07 人工通过:signOpenglreleasePublication SKIPPED,没有 no configured signatory,发布 AAR、POM、module metadata 均存在,且没有 .asc。当前 Gate C build output 与 Maven Local AAR 的共同 SHA-256 是 2e73e25cfd31bb181f75ba2d84974afb949640f72de46bc0234d4579abe3ba38,含 WeatherRuntime/MapLibreMap classes 和四 ABI。47646fb… 只是 publication 前中间 AAR SHA,不再是当前 artifact。后续只有 checkout 或 AAR 变化时,才重新 build/publish 并核对 provenance;不得以 -x sign 绕过签名,Maven Central 正式 publication 仍要求签名。2026-08-29 的旧 AAR(SHA-256 5c67…f85e5c)只可作 Gate C 历史证据,不能用于 STEP-060。

Bridge 与生命周期

WeatherRuntimeBridge 每个命令通过 UIManagerHelper.getUIManager(...FABRIC).resolveView(reactTag) 解析 View,并只接受 MLRNMapView。它直接读取公开的 MLRNMapView.mapLibreMap,不复制 MLRN 的私有 mViews,不保存 current map,也没有第二套 timeline/playback state。MapLibreMap 持有每个 map 的唯一 WeatherRuntime:style replacement、View detach 和 React unmount 都会 dispose 旧 facade;style ready 后 attach 创建新的 facade。

Style JSON 明确创建 background、host-field RasterArraySource、WeatherColorLayer 与 RasterParticleLayer。Bridge 仅在 source/layers 都存在且 style 已加载时 attach;它不会创建私有 Style registry。错误为结构化 reject:MAP_VIEW_NOT_FOUND、MAP_NOT_READY、STYLE_NOT_READY、WEATHER_OBJECTS_NOT_READY、RUNTIME_DISPOSED、INVALID_ARGUMENT 或 Native REJECTED。

Phase A / B 操作

页面 style ready 后显示 reactTag/runtime;Phase A 按钮为 getState、enable、WeatherColor visible、particle visible、FPS 30。Phase B 还通过 bridge 暴露 epoch-ms forecast seek、PLAY/PAUSE、速度、stops、独立 particle/trail RGBA、粒子视觉参数和 WeatherColor opacity。JS 只校验小参数,并不保存另一套 runtime 状态;snapshot 来自 Native。

当前不包含 Binary Field,不传 number[]、JSON 数组或 base64 field。3.01 MiB canonical field ingress 留给 STEP-061。

启动入口是 App.tsx。Android build、安装及设备操作必须由用户手工执行,详见 docs/60_测试/STEP-060_RNTestHost_Android人工编译与验收_v1.md。