适配仓库: https://atomgit.com/oh-flutter/app_version_details
适配 TAG: 尚未发布,当前请锁定受测提交

受测提交: f161b93e3c484aecf8a8910b22a64827dff71bf3

一、最终效果与适配目标

关于页、问题反馈、升级提示和日志上报都要显示应用版本。app_version_details 1.0.3 提供完整版本、版本名、构建号和包名,但原生实现没有覆盖 OHOS。最容易犯的错误是返回插件自身版本,或者把示例工程清单里的静态值硬编码到插件里。

这次适配从系统读取当前宿主应用的 BundleInfo。同一个插件装进不同应用,必须返回各自已安装包的真实 versionNameversionCode 和 bundle name。Flutter 构建还可能根据宿主 pubspec.yaml 覆盖 AppScope 里的版本值,因此最终判断依据应是设备已安装元数据。

在这里插入图片描述

图 1:真机宿主显示完整版本、名称、构建号和包名。

验证点实测结果证据
四个公开 API完整版本、版本名、构建号和包名互相一致图 1、图 6
系统元数据对照两轮读取均与 bm dump 一致图 6
重复读取每轮额外读取 5 次,结果稳定图 6
自动化与构建23 项 Dart/Widget/ArkTS 功能测试及 HAP 构建通过图 4、图 5
验证边界结论针对已安装宿主元数据,不把构建前静态清单当成真机事实真机说明

成果速览

项目内容
上游基线1.0.3 对应提交 ee25940295f5106fa15de0255bfdb3d5a0ab35b0,Apache-2.0
适配分支feat/ohos_app_version_details_1.0.3
适配 TAG尚未发布
真机受测提交f161b93e3c484aecf8a8910b22a64827dff71bf3
当前远程 HEAD81c7d18bd0188a152925fa38b16c41b37a6a13a8,后续只更新设备验证文档
新增 OHOS 能力读取宿主完整版本与 bundle name,隔离旧 Engine 异步回调
真机结论四个 Dart API 与已安装 bundle 元数据对照通过

二、本次环境

项目实测版本
Flutter OH3.41.10-ohos-1.0.1
Dart3.11.5
DevEco Studio26.0.0 Release
HarmonyOS SDKAPI 26,示例兼容 API 18
真机CHZ-AL00,HarmonyOS 7.0.0.105
目标库app_version_details 1.0.3

环境安装直接参考 Flutter OH 环境搭建指南。截至 2026 年 9 月 12 日,版本号最大的 Flutter OH 标签是预览版 3.44.9+ohos-0.0.1-canary1,最新正式稳定标签仍是 3.41.10-ohos-1.0.1。本文保留真正完成插件构建和真机回归的稳定版,不把未经同等验证的预览版写成实测环境。

三、仓库基线与分支

上游没有 1.0.3 标签,本次以提交 ee25940295f5106fa15de0255bfdb3d5a0ab35b0 为基线,并核对公开 Dart 入口与 1.0.3 发布包一致。Apache-2.0 许可证和历史完整保留。选库前检查清单及实时组织仓库,没有发现同包名适配。

git clone https://atomgit.com/oh-flutter/app_version_details.git
cd app_version_details
git switch feat/ohos_app_version_details_1.0.3
git remote -v

分支及平台骨架复现:

git switch -c feat/ohos_app_version_details_1.0.3 ee25940295f5106fa15de0255bfdb3d5a0ab35b0
flutter create --template=plugin --platforms=ohos --no-pub .

模板中的示例类名和通道随后改回原项目定义。图 2 汇总了实际 AtomGit origin、适配分支和 HEAD,可核对仓库来源与当前分支状态。

在这里插入图片描述

图 2:AtomGit origin、适配分支和当前 HEAD。

四、四个 Dart API 实际只有两个原生读取

final details = AppVersionDetails();
final version = await details.getVersion();
final packageName = await details.getPackageName();
final versionName = await details.getVersionName();
final buildNumber = await details.getBuildNumber();

通道 app_version_details 只有 getAppVersiongetPackageName 两个原生方法。getVersionName()getBuildNumber() 沿用 Dart helper,从 1.2.3+456 中拆分,不需要在 OHOS 再增加一套逻辑。保持这条调用链能避免四个接口读取出互相矛盾的版本。

五、读取 BundleInfo 并隔离旧引擎请求

pubspec.yaml 注册 AppVersionDetailsPlugin 后,生产 ArkTS 调用:

const info = await bundleManager.getBundleInfoForSelf(0);
if (call.method === 'getAppVersion') {
  result.success(`${info.versionName}+${info.versionCode}`);
} else {
  result.success(info.name);
}

真实代码还校验 versionName 非空、versionCode 为非负安全整数、bundle name 非空。无效元数据和系统异常返回 ERROR,未知方法返回 notImplemented,不会用伪造默认值掩盖原生失败。

系统查询是异步的。插件在 Engine attach 时递增 generation,请求发起时保存当前值;查询回来后如果 generation 已变,返回 UNAVAILABLE。这样旧引擎发起的读取不会在重绑后被当成新引擎数据。

读取自身 bundle 信息不需要额外权限。返回的是宿主,不是插件 HAR 的包名和版本。

完整版本用 versionName+versionCode 拼接时,分隔符也属于原 API 契约。版本名本身如果包含业务后缀,Dart helper 仍按既有规则解析;OHOS 端不应自行改成点号、括号或本地化格式,否则同一套 Flutter 代码会在平台间得到不同结构。

在这里插入图片描述

图 3:BundleInfo 读取、引擎代次隔离与版本字符串组装。

六、交付文件

适配保留全部 lib/、Android/iOS 代码、Apache-2.0 LICENSE 和上游历史;新增 OHOS HAR、example/ohos/、双语 OpenHarmony 文档、Dart/Widget 测试、生产 ArkTS 测试及设备入口。示例会一次展示四项值,并允许错误后重试。

本地签名、证书、SDK 路径、Node 依赖、生成元数据和 HAP 全部排除。目标仓库没有现成 README.OpenSource 要求,因此没有创建空占位文件。

七、测试与构建

flutter pub get
flutter analyze
flutter test
npm install --prefix ohos/test --no-save --no-package-lock typescript@5.9.3
node --test ohos/test/app_version_details.test.cjs
cd example
flutter test
flutter build hap --debug --no-codesign

9 项 Dart、2 项 widget 和 12 项实际 ArkTS 功能测试通过,共 23 项;另有 1 项重复回复夹具自检,不计为插件功能测试。静态分析无问题,无签名 HAP 构建成功。测试覆盖格式、零值和大版本号、空元数据、系统错误、新鲜读取、未知方法及引擎重绑。

真机代码固定为 f161b93e3c484aecf8a8910b22a64827dff71bf3,之后 81c7d18 只更新设备文档。

在这里插入图片描述

图 4:Flutter 复跑与 23 项 Dart/ArkTS 功能用例统计。

在这里插入图片描述

图 5:HAP 元数据及真机宿主锁定提交。

八、真机与 bm dump 交叉核对

dependencies:
  app_version_details:
    git:
      url: https://atomgit.com/oh-flutter/app_version_details.git
      ref: f161b93e3c484aecf8a8910b22a64827dff71bf3

执行 flutter pub get 后应核对 pubspec.lockresolved-ref。当前没有适配 TAG,因此示例固定到真机实际使用的代码提交,避免分支后续变化导致构建漂移。

隔离宿主在同一 PID 中执行两轮,均得到:完整版本 1.0.0+1、版本名 1.0.0、构建号 1、包名 com.example.flutter_oh_demo,每轮额外重复读取 5 次也保持一致。随后使用 hdc shell bm dump -n com.example.flutter_oh_demo 独立查询,系统安装信息中的名称、versionName=1.0.0versionCode=1 完全一致。

预验收曾错误期待 AppScope 静态值 1000000,因此失败。独立 bm dump 证明 Flutter 构建按宿主 pubspec.yaml 把安装版本覆盖成 1,插件返回是正确的。修正的是宿主断言,不是为了让测试通过而改插件返回值。

这次失败反而补上了一个必要的验收原则:先从系统取得事实,再写断言。若先相信源码清单,测试可能稳定失败;若直接迁就插件返回值,又会失去独立对照。bm dump 让两者有了第三方基线。

在这里插入图片描述

图 6:两轮插件读取与 bm dump 安装元数据对照。

应用内多状态补拍

在这里插入图片描述

图 7:app_version_details 1.0.3 首次读取宿主完整版本、Bundle Name、版本名和构建号。

在这里插入图片描述

图 8:点击刷新后进入第 2 次读取,时间更新,四项版本数据与一致性检查结果保持不变。

九、提交与远端状态

git status --short
git add pubspec.yaml ohos example test README.OpenHarmony.md README.OpenHarmony_CN.md
git commit -m "feat: add OHOS support for app_version_details"
git push -u origin feat/ohos_app_version_details_1.0.3

仓库公开,默认分支为适配分支。2026 年 9 月 12 日匿名读取 HEAD 为 81c7d18bd0188a152925fa38b16c41b37a6a13a8。该 HEAD 在受测代码之后只增加设备验证文档,本文的依赖仍锁定真机受测提交。

十、FAQ

Q1:为什么返回 1.0.0+1,不是 AppScope 中的版本号

  • 现象: 构建前静态清单与真机结果不同。
  • 原因: Flutter 构建会依据宿主 pubspec.yaml 覆盖安装包版本。
  • 解决方法: 以已安装 bundle 的 bm dump 为验收基线。
  • 验证结果: 插件两轮结果与系统安装信息一致。

Q2:getVersionName 和 getBuildNumber 为什么不再调用原生

  • 现象: 四个公开接口只见两个通道方法。
  • 原因: 上游已在 Dart 层从完整版本拆分名称与构建号。
  • 解决方法: 保留 helper,避免平台重复实现。
  • 验证结果: 四项值在真机上互相一致。

Q3:原生失败时 helper 的默认值会生效吗

  • 现象: 业务期待失败后得到默认版本。
  • 原因: helper 只对原生成功返回 null 的情况有默认值,平台异常仍向上传播。
  • 解决方法: 调用方捕获 PlatformException 并明确展示未知状态。
  • 验证结果: Dart 与 ArkTS 测试都覆盖错误传播。

十一、总结

app_version_details 已能在 Flutter 鸿蒙应用中读取真实宿主版本和 bundle name,Dart helper 继续提供版本名与构建号。23 项功能测试、HAP 构建、两轮真机读取及 bm dump 对照形成了完整证据。预验收失败也说明,版本测试必须看最终安装元数据,不能迷信构建前静态文件。

十二、参考链接

欢迎加入CPF-Flutter 鸿蒙社区:https://atomgit.com/CPF-Flutter

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐