适配仓库: https://atomgit.com/oh-flutter/flutter_device_name

适配分支: feat/ohos_flutter_device_name_0.0.3

受测提交: fdd0d8eb565f5b21aed9dd33f24b9b7483285c5d

一、最终效果与适配目标

flutter_device_name 的目标不是读取产品型号,而是读取用户在系统中看到和设置的设备名称。这个区别会直接影响设备列表、局域网发现和“在哪台设备登录”的提示。本次适配只补 OHOS 的 getDeviceName 实现,保持 DeviceName().getName() 的可空返回契约不变。

在这里插入图片描述

图 1:CHZ-AL00 / HarmonyOS 7.0.0.105 上读取到“华为畅享 90 Pro Max”,并显示真实读取时间。

验证点实测结果证据
公共 APIDeviceName().getName() 返回用户设备名称图 1、图 6
独立原生对照同一 UIAbility 直接查询 Settings,结果完全一致图 6
空值与异常空设置返回 null,系统失败显式上抛自动化
生命周期无 UIAbility 时返回 no_ability,重绑后恢复自动化
自动化与构建6 Dart + 8 ArkTS,共 14 项及 HAP 通过图 4、图 5

成果速览

项目内容
上游基线0.0.3,提交 780cbd5c2be9df6d07f473415ff692abec32a945,BSD-3-Clause
首次适配提交991a086c7a278f07d4ceedefd583a5dd7eb7e788
真机修复提交fdd0d8eb565f5b21aed9dd33f24b9b7483285c5d
新增 OHOS 能力从 DEVICE_SHARED Settings 读取用户定义名称
保持不变的接口DeviceName.getName()flutter_device_name 通道
真机结论修复 Context 后与独立原生结果一致;系统重命名回环未覆盖

二、实测环境与基线

组件实测版本
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
插件flutter_device_name 0.0.3

环境安装参考 Flutter OH 环境搭建指南。本文以稳定版 3.41.10-ohos-1.0.1 完成真机回归;更大版本号的 3.44.9+ohos-0.0.1-canary1 是预览版。

2026 年 9 月 11 日核对时,0.0.3 是 pub.dev 最新发布版,上游提交和发布源码一致,许可证为 BSD-3-Clause。目标组织与适配清单中未发现同包名 OHOS 实现后,我将上游历史同步到 AtomGit。

三、创建分支与工程结构

git clone https://atomgit.com/oh-flutter/flutter_device_name.git
cd flutter_device_name
git switch -c feat/ohos_flutter_device_name_0.0.3 780cbd5c2be9df6d07f473415ff692abec32a945
flutter create --template=plugin --platforms=ohos --no-pub .

模板生成的插件壳改为 FlutterDeviceNamePlugin,并保留上游通道 flutter_device_name。适配分支同时加入独立 example、Dart 契约测试、ArkTS 生产源码测试和双语文档。

在这里插入图片描述

图 2:AtomGit origin、适配分支、修复后的完整 HEAD 和干净工作区。

四、公共 API 很小,语义不能偷换

final DeviceName plugin = DeviceName();
final String? name = await plugin.getName();

返回 null 表示系统没有可用的用户设备名称。适配代码不能在这种情况下自动改用 deviceInfo.productModel,因为型号与用户定义名称是两种数据。也不能缓存结果,否则用户在系统设置中重命名后,下一次读取仍会得到旧值。

五、真机发现的 Context 问题

第一版实现用 ApplicationContext 调用 Settings。自动化和构建都通过,但真机返回 null,hilog 出现 Settings: helper is null。我随后在同一个宿主里用 UIAbilityContext 直接查询,能够正确读到名称。这说明问题不在设置项或权限,而在 Context 类型。

最终插件实现 AbilityAware,随 UIAbility 绑定保存上下文,并在解绑时清理:

onAttachedToAbility(binding: AbilityPluginBinding): void {
  this.context = binding.getAbility().context;
}

onDetachedFromAbility(): void {
  this.context = null;
}

const name = settings.getValueSync(
  this.context,
  settings.general.DEVICE_NAME,
  '',
  settings.domainName.DEVICE_SHARED,
);
result.success(name.length > 0 ? name : null);

无 UIAbility 时返回 no_ability,Engine 已解绑时返回 plugin_detached,系统查询异常返回 device_name_unavailable。这个插件无需新增权限。

在这里插入图片描述

图 3:UIAbilityContext、DEVICE_SHARED 域、空值和生命周期错误的最终实现。

六、修复后的测试与构建

flutter pub get
flutter analyze
flutter test
node --test ohos/test/device_name.test.cjs
cd example
flutter analyze
flutter build hap --debug --no-codesign

6 项 Dart 和 8 项 ArkTS 共 14 项通过。原生测试包含 Unicode 名称、空值、不缓存、系统异常恢复、未知方法、Engine 重绑、无 Ability、Ability 解绑与重新绑定。Context 修复后重新执行静态检查和无签名 HAP 构建。

在这里插入图片描述

图 4:Context 修复后的 14 项自动化和静态检查结果。

在这里插入图片描述

图 5:修复版 HAP、SHA-256 和远程依赖提交。

七、固定修复提交并真机复验

dependencies:
  flutter_device_name:
    git:
      url: https://atomgit.com/oh-flutter/flutter_device_name.git
      ref: fdd0d8eb565f5b21aed9dd33f24b9b7483285c5d

隔离宿主的 pubspec.lock 确认解析到修复提交,签名 HAP 构建和覆盖安装通过。第二轮真机中,公开 API 返回“华为畅享 90 Pro Max”,同一 UIAbility 通过独立原生通道读取到完全相同的文本,基础探测通过。

在这里插入图片描述

图 6:第一次失败原因、修复提交以及公开 API 与独立 Settings 查询的一致结果。

本轮没有修改系统设备名再改回,因此只证明当前值读取正确;名称变化时不缓存的行为由自动化覆盖,真实重命名回环仍需单独验收。

应用内补拍:插件与原生对照

在这里插入图片描述

图 7:插件公开 API、DEVICE_SHARED、默认域和独立原生读取结果一致。

在这里插入图片描述

图 8:刷新后再次读取同一设备名称,读取时间更新且对照结果仍为“一致”。

八、FAQ

Q1:为什么不能使用 ApplicationContext

  • 现象: 方法正常返回,但真机结果为空,系统日志显示 Settings helper 为空。
  • 原因: 当前 Settings 查询需要 UIAbilityContext,ApplicationContext 不满足调用上下文要求。
  • 解决方法: 实现 AbilityAware,在 Ability attach/detach 时保存和清理 UIAbilityContext。
  • 验证结果: 修复后 8 项 ArkTS 回归、HAP 构建和真机独立对照通过。

Q2:名称为空时为什么不返回产品型号

  • 现象: 业务希望任何设备都显示一段非空文本。
  • 原因: 本库契约是用户定义名称,产品型号不是同一字段。
  • 解决方法: 插件保留 null;业务层可明确显示“未设置”,如确需型号应接入设备信息 API。
  • 验证结果: 空设置返回 null 和 Unicode 名称保真均有自动化覆盖。

Q3:为什么每次都重新读取

  • 现象: 看起来可以缓存名称减少通道调用。
  • 原因: 用户可以在系统设置中重命名,缓存会返回过期值。
  • 解决方法: 每次业务刷新时调用 getName(),页面异步返回后检查 mounted
  • 验证结果: 原生测试修改模拟设置值后,下一次读取立即得到新名称。

九、总结

flutter_device_name 0.0.3 的 OHOS 适配最终只做一件事:用正确的 UIAbilityContext 从 DEVICE_SHARED Settings 读取用户设备名称,并如实处理空值和异常。首次真机失败促使 Context 路径得到修正;14 项自动化、HAP 构建及真机原生对照随后通过。

业务接入必须固定到 fdd0d8e... 修复提交,不能使用此前的首次适配 commit。系统重命名回环和其他设备仍是当前验证边界。

十、参考链接

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

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐