Files
MapLibreParticleLab/integration/react-native/MapLibreParticleRNTestHost/README.md
OpenAI Codex a91e3601f3
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
feat: add STEP-062 real weather test map
2026-09-09 09:13:03 +08:00

8.3 KiB
Raw Blame History

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、expo-file-system 56.0.11、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-step061 与 nativeVariant=opengl。STEP-061 必须构建并 Maven Local publish 这个唯一的新坐标,禁止覆盖已经冻结的 13.4.1-step060f;本轮 RDC 修复仅推进坐标和文档,未构建或发布。

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
# STEP-061 必须先按当前 checkout 重建,且只能发布新的 `13.4.1-step061` 坐标:
./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。

STEP-061 Binary U/V Field transport

正式 Binary ingress 为 metadataJson + payloadFileUri/path。Test Host 使用 Expo FileSystem File.write(Uint8Array) 将 raw bytes 写入 app cache;TurboModule 只接收 metadata 和本地 file:// URI(也接受绝对本地路径),Kotlin 对可读性与 64 MiB 上限 fail-closed 后读取原始 byte[],并且只调用既有 WeatherRuntime.submitWindField(metadataJson, byte[])。没有 number[]/Array<number>、payload JSON、base64、hex 或网络下载层。

Submit binary WIND T0/T1 固定生产 4×3 的两帧 WIND/GLOBAL canonical field:north-west origin、row-major、interleaved-uv、float32-le,并以 DataView.setFloat32(..., true) 显式写入 U=eastward、V=northward。初始状态与每轮开始均为 PENDING,绝不预先显示 READY。按钮先通过既有 clearWindFields() 清空 Source-owned Timeline,再依序提交一个声明字节数与文件实际字节数不一致的 invalid probe、T0、T1,并严格断言 Core 结果依次为 REJECTED_ADAPTER、ACCEPTED_PENDING_INITIAL_WINDOW、INITIAL_WINDOW_READY,最后 Native WeatherRuntime.state 必须为 READY;任意不符均显示 ERROR。

界面严格区分 Core evidence: INITIAL_WINDOW_READY + runtime READY 与 producer 已提交的 T0/T1 generation/time identity;后者不是 Native/Core runtime window。MIX 明确为 Core-owned / not exposed。Android 最终 T0/T1 真值由既有 logcat HOST_FIELD_SNAPSHOT_READY 与 HOST_FIELD_INITIAL_WINDOW_READY 验证,本 Step 不新增 Core getter。

启动入口是 App.tsx。app.json 已固定 orientation: landscape;下一次 Android prebuild/build 应生成 MainActivity android:screenOrientation="landscape"。Android build、安装及设备操作必须由用户手工执行,详见 docs/60_测试/STEP-060_RNTestHost_Android人工编译与验收_v1.md。

STEP-062 真实 WeatherV2 综合地图

Test Host 固定消费已验收的 org.maplibre.gl:android-sdk-opengl:13.4.1-step061,本阶段不构建或发布 AAR。页面 style 顺序是 background → GSI raster → WeatherColorLayer → RasterParticleLayer;GSI 使用国土地理院标准地图 https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png(256、maxzoom 18、含 attribution),相机初始聚焦日本及周边 WeatherV2 bounds。

受控 assets assets/weather/ecmwf-hres-wind-20260807/ 原样复制 Android Validation 的 dataset.json 与四个 metadata.json/field.f32。expo-asset 是明确直接依赖,metro.config.js 仅增加 .f32 asset extension。点击 LOAD REAL WEATHER T0-T3 会先 clear,然后通过 Asset.fromModule(...).downloadAsync() 取得四个 Expo cache file:// URI,按 producer validTime 提交;JS 只传小型 metadata JSON 和文件引用,不 materialize 3.01 MiB payload 为数组、JSON、base64 或 hex。

硬断言依次为 T0=ACCEPTED_PENDING_INITIAL_WINDOW、T1=INITIAL_WINDOW_READY、T2/T3=ACCEPTED_NEXT_SNAPSHOT,并在最后要求 Native state=READY;任何偏差均显示 ERROR。界面提供 PLAY/PAUSE、HALF/NORMAL/DOUBLE、四个 epoch-ms forecast seek、AUTO/30/60 FPS、两层可见性、冻结 WeatherColor stops、独立 particle/trail 色彩,以及粒子/轨迹视觉参数。Expo/系统管理 asset cache;本页不自建 .f32 临时文件。

Windows 安装与 Metro reverse

Test Host 的 Metro 固定在 8091,但 Debug APK 的 RN dev-server 探测仍从设备 localhost:8081 发起。手工安装前以受控脚本 scripts/05-install-and-run.ps1 保留两条 reverse:tcp:8091 -> tcp:8091 与 tcp:8081 -> tcp:8091。脚本固定设备 192.168.1.146、package org.maplibre.particle.rntesthost、activity .MainActivity,并在安装前完成 reverse。