Flutter 3.47 鸿蒙三方库适配实战:从 0 到 1 处理 flutter_dynamic_icon_plus
动态应用图标是一个“看起来很小、实现差异极大”的能力。Android 侧要靠 activity-alias 预注册多套图标并切换 alias 的启用状态,还得绕开部分厂商的黑名单;iOS 侧走 setAlternateIconName。flutter_dynamic_icon_plus 把两套机制封装成一致的方法。把它带到鸿蒙时,问题是:鸿蒙侧既没有等价的图标切换系统 API,也没有角标数字接口,这种情况下"适配"应该做什么?
本文以 flutter_dynamic_icon_plus 1.4.1 为例,记录我如何保留完整的方法通道、在鸿蒙端如实返回能力边界,并在 HarmonyOS API 26 模拟器上完成构建、安装、启动和方法调用验证。上机结果没有出现“切换成功”的假象:所有查询接口返回明确的否定值,所有切换接口保持安全无操作。
适配仓库: oh-flutter/flutter_dynamic_icon_plus
适配分支: feat/ohos_flutter_dynamic_icon_plus_1.4.1
适配 TAG: 1.4.1-ohos.1
一、先看最终效果
图 1:HarmonyOS API 26 模拟器启动 Demo。页面显示 flutter_dynamic_icon_plus 1.4.1,状态为等待操作。
图 2:点击“查询图标支持情况”后的真实结果。supportsAlternateIcons 返回 false,当前图标名为 null。
| 验证点 | 实测结果 | 证据 |
|---|---|---|
| Flutter OH 3.47 工程构建 | 通过 | entry-default-signed.hap |
| 签名、安装和启动 | 通过 | 图 1 |
supportsAlternateIcons | 返回 false | 图 2 |
getAlternateIconName | 返回 null | 图 2 |
setAlternateIconName | 安全无操作 | 图 3 |
| 角标读写 | 返回 0 / 安全无操作 | 图 4 |
| 鸿蒙图标切换能力 | 尚未接入 | 适配边界 |
继续在模拟器上点击其余两个按钮,确认切换和角标入口也都保持明确的语义:
图 3:调用 setAlternateIconName 后返回完成,但不会伪造图标已切换的状态。
图 4:调用 applicationIconBadgeNumber 后返回 0,与“该平台没有角标机制”一致。
二、这个库原来是怎么工作的
上游包的公共入口是 FlutterDynamicIconPlus 的五个静态方法。Dart 层通过名为 flutter_dynamic_icon_plus 的 MethodChannel 把调用传给原生端。
Dart FlutterDynamicIconPlus
-> MethodChannel('flutter_dynamic_icon_plus')
-> Android activity-alias / iOS setAlternateIconName
-> 图标名、支持状态或角标数字
Android 的实现需要宿主应用预先在 AndroidManifest.xml 里声明多个 activity-alias,切换图标本质上是启用或禁用这些 alias,所以包还提供了 blacklistBrands、blacklistManufactures、blacklistModels 参数来绕开已知不稳定的厂商机型。这些参数在鸿蒙端没有对应含义,但为了接口签名兼容,这次适配保留参数原样接收。
值得单独说明的是 iOS 角标:applicationIconBadgeNumber 是 iOS 独有的概念,Android 压根没有系统级角标接口。也就是说这条库本身在 Android 上就只实现了方法签名的一部分。鸿蒙端沿用了同样的策略:保留方法,如实返回边界。
三、实际环境
Flutter 鸿蒙环境搭建不在本文重复展开,直接参考 Flutter OH 环境搭建指南。
| 组件 | 版本 |
|---|---|
| Flutter OH | 3.47.4-ohos-1.0.4 |
| Dart | 3.13.3 |
| DevEco Studio | 26.0.0 Release |
| HarmonyOS SDK | API 26 |
| 测试设备 | DevEco 模拟器 Pura X View(HarmonyOS 7.0.0.105,API 26) |
本次验证使用 DevEco Studio 26.0.0 自带的 Pura X View 模拟器,系统版本与目标真机同为 HarmonyOS 7.0.0.105 / API 26;HAP 的签名、安装与启动链路和真机一致。
| 目标库 | flutter_dynamic_icon_plus 1.4.1 |
四、确认上游版本并同步到 AtomGit
上游包地址是 GitHub chandrabezzo/flutter_dynamic_icon_plus,版本 1.4.1 使用 MIT License。适配前我在 AtomGit 目标组织中搜索了同名库,没有找到可以直接使用的 OHOS 实现。
仓库初始适配提交为 b23954b,完成后分支最新提交为 61dd171。
git clone https://atomgit.com/oh-flutter/flutter_dynamic_icon_plus.git
cd flutter_dynamic_icon_plus
git switch feat/ohos_flutter_dynamic_icon_plus_1.4.1
git log --oneline -5
五、创建适配分支并检查工程结构
git switch -c feat/ohos_flutter_dynamic_icon_plus_1.4.1
关键目录如下:
flutter_dynamic_icon_plus/
├── lib/ # 原有 Dart API 和 MethodChannel
├── ohos/
│ ├── index.ets # OHOS 插件导出入口
│ └── src/main/ets/components/plugin/
│ └── FlutterDynamicIconPlusPlugin.ets # MethodChannel 实现
├── example/lib/main.dart # 上机验证 Demo
├── pubspec.yaml # 声明 ohos 平台
└── README.OpenHarmony_CN.md # 鸿蒙适配说明
六、适配过程:五个方法的能力映射
我先从 lib/flutter_dynamic_icon_plus.dart 和 lib/flutter_dynamic_icon_plus_method_channel.dart 读取现有接口,逐一确定鸿蒙端的返回语义:
| Dart 方法 | 参数 | OHOS 本次策略 |
|---|---|---|
supportsAlternateIcons | 无 | 返回 false(鸿蒙没有公开图标切换 API) |
alternateIconName | 无 | 返回 null(没有当前备用图标的概念) |
setAlternateIconName | 图标名、三类黑名单、静默标志 | 安全无操作,返回成功 |
applicationIconBadgeNumber | 无 | 返回 0(没有系统角标机制) |
setApplicationIconBadgeNumber | 角标数 | 安全无操作,返回成功 |
这个映射里最需要解释的是“为什么切换接口返回成功而不是报错”。原因是这条库的调用方通常会把切换动作写进设置流程:如果鸿蒙端直接抛异常,业务代码需要为鸿蒙平台单独包一层 try-catch 才能不中断设置页的提交流程。而查询接口 supportsAlternateIcons 已经是官方提供的探测手段——正确的调用方应该先查询再切换。所以“查询返回 false + 切换无害化”是更平滑的组合:调用方按标准流程写代码,在鸿蒙上自然表现为“没有可切换的图标”,而不是异常。
OHOS 插件实现使用标准的 FlutterPlugin 骨架:
onAttachedToEngine(binding: FlutterPluginBinding): void {
this.channel?.setMethodCallHandler(null);
this.channel = new MethodChannel(
binding.getBinaryMessenger(),
'flutter_dynamic_icon_plus',
);
this.channel.setMethodCallHandler(this);
}
onDetachedFromEngine(binding: FlutterPluginBinding): void {
this.channel?.setMethodCallHandler(null);
this.channel = null;
}
核心方法分支如下:
onMethodCall(call: MethodCall, result: MethodResult): void {
switch (call.method) {
case 'getPlatformVersion':
result.success('OpenHarmony 3.47.4');
return;
case 'supportsAlternateIcons':
result.success(false);
return;
case 'getAlternateIconName':
result.success(null);
return;
case 'setAlternateIconName':
result.success(null);
return;
case 'getApplicationIconBadgeNumber':
result.success(0);
return;
case 'setApplicationIconBadgeNumber':
result.success(null);
return;
default:
result.notImplemented();
}
}
七、构建配置与签名
示例工程的目标 SDK 对齐到 26:
{
"name": "default",
"compatibleSdkVersion": "26.0.0",
"targetSdkVersion": "26.0.0",
"runtimeOS": "HarmonyOS"
}
Demo 的 AppScope/app.json5 统一成 com.example.flutter_oh_demo,与 DevEco 调试签名对应。证书和密码没有提交到仓库。
八、通过 AtomGit 引入适配版
dependencies:
flutter_dynamic_icon_plus:
git:
url: https://atomgit.com/oh-flutter/flutter_dynamic_icon_plus.git
ref: 1.4.1-ohos.1
九、构建、安装和设备验证
cd example
flutter pub get
flutter analyze
flutter build hap --debug
hdc install -r build/ohos/hap/entry-default-signed.hap
hdc shell aa start -a EntryAbility -b com.example.flutter_oh_demo
构建输出为 ✓ Built build/ohos/hap/entry-default-signed.hap.,随后安装启动成功。模拟器上依次点击三个按钮,分别得到图 2、图 3、图 4:查询返回 false 和 null,切换与角标返回完成且无异常。
十、适配结果和当前边界
| 层次 | 已完成内容 | 尚未完成内容 |
|---|---|---|
| Dart API | 保留五个静态方法和参数签名 | 无 |
| MethodChannel | 通道名和方法名全部对齐 | 无 |
| OHOS 插件 | 注册、版本查询、能力边界回传 | 图标切换与角标系统能力 |
| Demo | API 26 模拟器启动和三个按钮验证 | 真实图标资源切换 |
| 文档 | README.OpenHarmony_CN.md、CHANGELOG | 无 |
HarmonyOS 目前没有和 iOS setAlternateIconName 等价的公开接口,Android 的 activity-alias 方案也不能直接移植。如果后续鸿蒙开放了图标切换或桌面快捷方式能力,可以在 setAlternateIconName 分支里接入真实实现,并把 supportsAlternateIcons 改为真实探测。当前实现保证契约稳定,业务代码不需要为鸿蒙写特判。
十一、FAQ
Q1:为什么 setAlternateIconName 返回成功但图标没有变化?
- 现象: 模拟器上切换图标后没有任何视觉变化,也没有报错。
- 原因: 鸿蒙端没有图标切换能力,方法保持安全无操作。
- 解决方法: 调用方先查询
supportsAlternateIcons,返回false时禁用切换入口。 - 验证结果: 图 2 证明查询返回
false;图 3 证明切换调用不会抛异常。
Q2:为什么角标读取返回 0 而不是报错?
- 现象:
applicationIconBadgeNumber在鸿蒙端返回 0。 - 原因: 鸿蒙没有系统级应用角标接口,返回 0 表示“没有角标”这一确定状态。
- 解决方法: 以
supportsAlternateIcons或平台判断决定是否展示角标相关 UI。 - 验证结果: 图 4 显示返回值为 0,页面无异常。
Q3:黑名单参数在鸿蒙端有意义吗?
- 现象:
setAlternateIconName接收blacklistBrands等参数但完全忽略。 - 原因: 这些参数是为 Android 厂商兼容准备的,鸿蒙端没有对应机制。
- 解决方法: 保留参数签名以兼容调用方代码,鸿蒙分支不使用这些值。
- 验证结果: 携带参数的调用在模拟器上正常走完通道。
十二、总结
这次适配保留了 flutter_dynamic_icon_plus 1.4.1 的五个静态方法和 flutter_dynamic_icon_plus 通道,在 OHOS 侧实现了标准 FlutterPlugin 注册、版本查询和五项能力边界。Demo 通过 Flutter OH 3.47.4 构建成签名 HAP,并在 HarmonyOS API 26 模拟器上完成安装、启动和全部按钮验证。
当前成果是“契约完整、边界清楚”的适配基线。后续如果鸿蒙开放动态图标能力,可在同一分支上替换实现,不影响调用方代码。适配代码和说明都在 AtomGit 适配分支,复现时建议锁定 1.4.1-ohos.1 TAG。
十三、参考资料和仓库地址
- 适配仓库主页
- 适配分支
- 适配 TAG
- 最终提交 61dd171
- ArkTS MethodChannel 实现
- Dart 公共入口
- 鸿蒙适配说明
- pub.dev 包页面
- pub.dev 1.4.1 版本页
- 上游 GitHub 仓库
- 上游 LICENSE
- Flutter 官方插件与平台通道文档
- Flutter OH 鸿蒙 SDK 仓库
- HarmonyOS 开发者官方文档
欢迎加入CPF-Flutter 鸿蒙社区:https://atomgit.com/CPF-Flutter
更多推荐

所有评论(0)