定制侠鸿蒙版真机白屏排查全记录:四层根因与最终修复

xiezitai · 2026-10-20 19:02 · 9 次阅读

定制侠鸿蒙版真机白屏排查全记录:四层根因与最终修复

一、背景与目标

定制侠(dingzhixia.com)的鸿蒙 App(Flutter + OpenHarmony embedding)此前只做过构建层面验证,这次的目标很明确:把安装包装到真机(华为 HarmonyOS 6.1,API 23)上跑起来。

项目基本情况:

二、问题现象

安装成功,点击启动 → 白屏,什么也没有。进一步观察发现应用实际是启动后秒退,进程都没起来。

三、排查过程:四层根因

这个问题不是一次定位的,而是剥洋葱一样一层层剥出来的。前三次修复都只解决了表层,直到第四次才找到最终根因。

第 1 层:Dart SDK 版本错配,kernel 格式不匹配

现象:日志报 root isolate 创建失败 / kernel invalid。

根因:本机 PATH 里残留了 D 盘旧版 Flutter SDK(3.27.5-ohos-1.0.1 / Dart 3.6.2),且 PUB_CACHE 指向 D 盘旧缓存。pub get 时旧 Dart 污染了 .dart_tool/package_config.json,生成的 kernel_blob.bin 是 v120 格式,而新引擎(Dart 3.11.5)只认 v127。

修复:用目标 SDK 重跑 pub get 修正 package_config,并在构建脚本里把 PATH 前置加固(node + 目标 dart-sdk/bin + flutter/bin),清理 PUB_CACHE 影响。

第 2 层:构建中间目录残留污染

现象:修完 SDK 后依旧白屏。

根因:build/ohos/intermediates/flutter/defaultRelease/flutter_assets/ 里有早前构建残留的 URL 编码中文目录(提示词资源),且 manifest/snapshot 文件不完整,release 包打进了残缺的 assets。

修复:删除中间目录整体重建。

第 3 层:ohpm 依赖模块的 BuildProfile 硬编码 debug

现象:重建后 release 包仍走 debug 代码路径。

根因:hvigor 的 --generate-build-profile 只会给工程内模块生成 BuildProfile.ets;ohpm 依赖模块(@ohos/flutter_ohos、flutter_native_arm64_v8a)保持 har 里的默认值:

export const BUILD_MODE_NAME = 'debug';
export const DEBUG = true;

embedder 的 FlutterLoader.isDebugMode() 就是拿它判断模式的。release 包因此误走 debug 的 copyResource 路径,去设备上找 AOT 包里根本不存在的 kernel_blob.bin。

修复:写了 patch_buildprofile.py,构建前按目标模式修补这两个依赖模块的 BuildProfile.ets,构建后恢复默认值,集成进构建脚本。

第 4 层(最终根因):release 包里混进了 debug 引擎

前三层修完,装机仍然秒退。这次抓到了关键日志:

FlutterNapi --> attachToNative fail, FlutterNapi.hasInit=false
XComFlutterOHOS_Native: Cannot create a FlutterEngine instance in debug mode
without Flutter tooling. To Launch in debug mode, run 'flutter run'...

顺着引擎源码 ohos_main.cpp → ptrace_check.cc 找到判据:

为什么会混入:ohos/oh-package.json5 的 overrides 写死了 debug 引擎 har(arm64_v8a_debug.har,libflutter.so 38.9MB)。flutter 工具本来会按构建模式复制对应引擎 har 到工程(hvigor.dart 的 copyFlutterRuntime),但我们的构建是直连 hvigorw、绕过 flutter 工具,加上 ohpm 是 no-op shim,overrides 永远指向 debug 引擎。

这也解释了为什么第 3 层的 BuildProfile 补丁无效:那个补丁只改 ArkTS 侧,而引擎的 debug 判据在原生 .so 里,与 ArkTS 无关。

修复:新增 switch_engine.py——release/profile 构建时,把 oh_modules 里 flutter_native_arm64_v8a 模块的 libs/arm64-v8a/libflutter.so 替换为对应模式引擎(release 引擎 16.4MB),首次切换自动把 debug .so 备份到 ohos/.engine_cache/,构建后恢复。集成进构建脚本,与签名切换同一套流程。

对比验证:debug / release 两个 embedding har 的 ArkTS 源码完全一致(diff 验证,只有 BuildProfile / 混淆元数据差异),所以只需换 .so,不用动 ArkTS 层。

四、连带修掉的两个装机拦路虎

排查过程中还解决了两个与白屏无关但同样拦住真机安装的问题:

1. 签名策略:release 证书不能 sideload

发布证书签名的包直接 hdc install 会被拒(9568322,not trusted app source)。解法是给 build-profile.json5 增加一套 debug 签名配置(调试证书 + 含本机 UDID 的调试 profile),密钥库复用项目已有的 p12(申请调试证书时复用了同一对密钥提交 CSR,私钥公钥配对验证一致)。切换脚本 switch_signing.py,构建参数第二位传 debug|release。

2. compatibleSdkVersion 格式坑

设备是 HarmonyOS 6.1.0 = API 23,低于工程的 compileSdk 26。直接写 "23.0.0" 被拒(00306042 Specification Limit Violation)。正确写法:API 10-25 必须用 主.次.修订(API) 格式,即 "6.1.0(23)";compile/targetSdkVersion 保持 26.0.0(新 SDK 编译、低版本设备运行,引擎兼容没问题)。

五、验证结果

最终产物:发布/entry-default-signed-dbgcert-rel4-20261020.hap(36.8MB,AOT release + release 引擎 + 调试签名):

验证项 结果
hap 内 libflutter.so 16.4MB release 引擎(此前是 38.9MB debug 引擎)
安装 hdc install -r 成功(注意必须用相对路径)
启动 登录页完整渲染:品牌 logo、账号密码输入、三方登录按钮齐全
稳定性 进程持续运行 6 分钟以上无退出;锁屏唤醒后重启 UI 仍正常
日志 无 debug 模式报错、无 attachToNative 失败,仅剩无害的 fallback 字体警告

六、沉淀:直连 hvigorw 构建的注意点

这次踩的坑大多源于「绕过 flutter 工具链直连 hvigorw」,把要点沉淀下来:

  1. 引擎必须按模式手动切换:overrides 写死 debug har,release/profile 构建前必须替换 libflutter.so(否则 debug 引擎的 tracing 检查会让包秒退)。
  2. ohpm 依赖模块的 BuildProfile 要手动 patch:hvigor 不刷新依赖模块的这个文件。
  3. PATH 要防旧 SDK 污染:多 SDK 环境务必把目标 SDK 的 bin 前置,并清理 PUB_CACHE 影响;kernel 格式版本(v120 vs v127)不匹配时表现就是白屏 / isolate 创建失败。
  4. compatibleSdkVersion 格式:API 10-25 用 主.次.修订(API),API 26+ 才用纯三段式。
  5. hdc install 用相对路径:传绝对路径会被拼成 cwd + 绝对路径双路径。
  6. 排查抓手:白屏 / 秒退先抓 hilog -x 里 FlutterNapi / Native 引擎相关标签,比盲目翻源码快得多。

七、待验证

评论

还没有评论,登录后来说两句。