Flutter for OpenHarmony 实战:三方库 system_settings_2 的鸿蒙化适配指南
环境搭建指引:https://atomgit.com/CPF-Flutter/flutter_samples/blob/master/ohos/getting-started/flutter-oh-env-setup.md
system_settings_2 提供的是一类很常见的"跳转能力":打开系统的某一个设置页(Wi-Fi、蓝牙、显示、声音、应用详情、通知设置……共 25 个)。它的 3.0.2 版支持 Android、iOS,没有 OpenHarmony。
适配它的价值不在接口数量,而在于它逼着我们把鸿蒙的"跨应用跳转"讲清楚:安卓是 Intent(Settings.ACTION_*),iOS 只能开本应用的设置页,而鸿蒙是 startAbility + Want——bundleName/abilityName 指向系统设置应用,uri 决定落到哪个子页面。更麻烦的是:子页面 uri 属于系统约定、不是公开 API,所以"打不开具体页就退回首页"这条兜底是必须的,否则 Dart 侧会因为某台设备少一个页面就吃异常。
适配对象:上游 system_settings_2 3.0.2(MIT);适配产物 TAG 3.0.2-ohos-1.0.0-beta.1。
一、这个库要解决什么
1.1 上游 API
25 个静态方法,全部无参数、无返回值:
await SystemSettings.system(); // 设置首页
await SystemSettings.wifi(); // WLAN
await SystemSettings.bluetooth();
await SystemSettings.nfc();
await SystemSettings.display();
await SystemSettings.sound();
await SystemSettings.date();
await SystemSettings.locale();
await SystemSettings.location();
await SystemSettings.privacy();
await SystemSettings.security();
await SystemSettings.accessibility();
await SystemSettings.internalStorage();
await SystemSettings.powerUsage();
await SystemSettings.powerOptions();
await SystemSettings.apps();
await SystemSettings.notificationPolicy();
await SystemSettings.defaultApps();
await SystemSettings.deviceInfo();
await SystemSettings.app(); // 本应用详情
await SystemSettings.appNotifications(); // 本应用通知设置
// 另有 wireless / dataUsage / dataRoaming / airplaneMode
1.2 契约
class SystemSettings {
static const MethodChannel _channel = MethodChannel('system_settings_2');
static Future<void> wifi() async {
return await _channel.invokeMethod('wifi');
}
// ... 其余 24 个方法同理,方法名是 kebab-case(data-usage / device-info / app-notifications …)
}
一条方法通道、25 个无参方法,Dart 层没有任何平台门,pubspec.yaml 只声明了 android / ios。鸿蒙侧把这条通道接住即可,Dart 一个字都不用改。
1.3 基线:仓库与发布版逐文件一致
node .agents/tools/tree-diff.mjs _probe/cand12/system_settings_2 _probe/ss2_work
# 相同: 81 内容不同: 0 仅 B 有: .github / .gitignore / .vscode 等工程文件
上游 master(db8faac)与 pub.dev 上的 3.0.2 完全一致,基线清晰。
二、选库:四道筛 + 在线查重
2.1 四筛
| 筛子 | 检查 | 结果 |
|---|---|---|
| ① pub.dev 平台列表 | 是否已含 ohos | [android, ios],不含 → 需要适配 |
| ② 兄弟包 | 上游根目录有无 <lib>_ohos;pub.dev 上有无 system_settings_2_ohos | 都没有 |
| ③ Dart 平台门 | 有无 Platform.is* / defaultTargetPlatform 分支 | 无(25 个方法都是纯通道调用) |
| ④ 依赖体检 | node .agents/tools/dep-ohos-check.mjs system_settings_2 | deps ok: -(零依赖) |
2.2 在线查重
同一个 403 陷阱在第 11、12 篇都出现过:hxa-flutter/system_settings_2 返回 403,不可解读。用四组织全量仓库快照(org-repos.mjs,831 个仓库)精确匹配:
---- system_settings_2
干净。(同轮被这条规则排除的还有 ambient_light、device_apps、app_settings、is_lock_screen、volume_listener。)
三、六步适配流程
- 建仓:
node .agents/tools/atomgit.mjs create oh-flutter system_settings_2 "…" - 克隆:
git clone https://gh-proxy.com/https://github.com/timmaffett/system_settings_2.git _probe/ss2_work - 建分支 + 补鸿蒙目录:
git checkout -b feat/ohos_system_settings_2_3.0.2后跑
flutter create -t plugin --platforms ohos --org xyz.hiveright .
—— 这里必须显式--org:上游 android package 是xyz.hiveright.system_settings_2,示例工程是com.example,不加会报
Ambiguous organization in existing files: {xyz.hiveright, com.example} - 写实现:
ohos/src/main/ets/components/plugin/SystemSettingsPlugin.ets - 补文档与示例:三份
README.OpenHarmony*/CHANGELOG.OpenHarmony.md、根 README 说明、示例改成自检台 - 推送打 TAG:分支 + main +
3.0.2-ohos-1.0.0-beta.1;提交前清空signingConfigs

四、代码写在哪个文件
ohos/src/main/ets/components/plugin/SystemSettingsPlugin.ets # 本篇唯一新增的实现文件
4.1 25 个 Intent → 1 个 Want(uri 决定子页面)
const SETTINGS_BUNDLE: string = 'com.huawei.hmos.settings';
const SETTINGS_ABILITY: string = 'com.huawei.hmos.settings.MainAbility';
const want: Want = {
bundleName: SETTINGS_BUNDLE,
abilityName: SETTINGS_ABILITY,
uri: 'wifi_entry', // 子页面
};
await context.startAbility(want); // 需要 UIAbilityContext
"针对本应用"的两个页面不是独立 uri,而是同一个页面 + 参数:
if (method === 'app' || method === 'app-notifications') {
const params: Record<string, Object> = {};
params['pushParams'] = ability.context.abilityInfo.bundleName;
want.parameters = params;
}
4.2 插件必须实现 AbilityAware
startAbility 是 UIAbilityContext 的能力,插件默认拿不到 UIAbility:
onAttachedToAbility(binding: AbilityPluginBinding): void {
this.ability = binding.getAbility();
Log.i(TAG, 'ability attached: ' + this.ability?.context.abilityInfo.bundleName);
}
拿不到时抛明确错误,而不是静默失败。
4.3 兜底:打不开具体子页面就退回首页
try {
await context.startAbility(want);
Log.i(TAG, `${method} -> ${SETTINGS_BUNDLE} uri="${uri}" (ok)`);
} catch (error) {
Log.w(TAG, `${method} -> uri="${uri}" failed code=${err.code} ${err.message}, falling back to settings home`);
await context.startAbility({ bundleName: SETTINGS_BUNDLE, abilityName: SETTINGS_ABILITY } as Want);
Log.i(TAG, `${method} -> settings home (fallback ok)`);
}
这条兜底不是"想当然":实测在本机上 mobile_network_entry 这个 uri 就不被识别(aa start -U mobile_network_entry 直接落到设置首页),说明子页面 uri 确实会随系统版本变化。
4.4 模板垃圾这次也别手软
flutter create 又生成了 SystemSettings_2Plugin.kt/.swift、lib/system_settings_2_method_channel.dart、lib/system_settings_2_platform_interface.dart、test/system_settings_2_*_test.dart、example/integration_test/ 等——本库不是联邦式插件,上游只有一个 Dart 文件,这些都必须删。
五、真机(模拟器)验证
示例被改造成自检台:25 个按钮逐一对应上游 25 个方法,点一次把结果写进界面与 [SS2-CHECK] 日志,是否真的跳到目标页用截图 + hilog 双重确认。
| 项 | 值 |
|---|---|
| 设备 | Pura 90 模拟器,HarmonyOS 6.1.1(24) / API 24,ohos-x64,1320×2856 |
| 构建 | flutter build hap --debug --target-platform ohos-x64 |
| 日志 | hdc shell hilog -x | Select-String "SystemSettingsPlugin" |
| 方法 | 设备侧结果 |
|---|---|
system | system -> com.huawei.hmos.settings uri="" (ok);截图确认打开的是设置首页(含 WLAN/显示和亮度/声音和振动/关于本机等入口) |
wireless / wifi | 点击成功、截图留档;两者都落到 wifi_entry(鸿蒙的"无线与网络"就是 WLAN 页) |
bluetooth | bluetooth -> com.huawei.hmos.settings uri="bluetooth_entry" (ok) |
nfc | nfc -> com.huawei.hmos.settings uri="more_connections_entry" (ok) |
device-info(about_entry) | 手工进"设置 → 关于本机"确认页面存在(显示设备名称 emulator、存储 12GB/16GB、型号、HarmonyOS 版本 6.1.0) |
| 其余 20 个 | 未逐一截图;每个方法调用都会在 hilog 留 (ok) 或 falling back 一行,靠它就能判断是否落到目标页 |



验证环境说明:本轮原计划用 API 26 的
Pura X View,但它反复崩溃、启动只剩空壳进程,最终改用同为 x86_64 的Pura 90(HarmonyOS 6.1.1 / API 24)。hap 的compatibleSdkVersion是5.1.0(18),两代设备都能装。
六、编译与构建踩坑
6.1 示例的 Dart 语言版本会直接卡住鸿蒙构建
上游示例写的是 sdk: '>=2.15.1 <3.0.0'(Dart 2 时代),在 Dart 3.12 工具链下连 super.key 都不可用:
lib/main.dart:55:35: Error: The 'super-parameters' language feature is disabled for this library.
改成 sdk: '>=3.0.0 <4.0.0' 之后还有一个隐蔽点:必须删掉 example/build 再构建,否则旧的 kernel 缓存会让同一个错误一直复现(我第一次改成 >=2.15.1 <4.0.0 仍报错,是因为语言版本仍低于 2.17;第二次改对约束后仍报错,则是构建缓存没清)。
6.2 --org 不是可选项
Ambiguous organization in existing files: {xyz.hiveright, com.example}.
The --org command line argument must be specified to recreate project.
6.3 模板垃圾清理清单
SystemSettings_2Plugin.kt / SystemSettings_2Plugin.swift / lib/system_settings_2_method_channel.dart / lib/system_settings_2_platform_interface.dart / test/system_settings_2_*_test.dart / example/integration_test/ / example/ios/Runner/SceneDelegate.swift / example/android/**.gradle.kts。
教训(与第 11 篇同一个坑):删目录前先 git ls-files <目录>——上游 iOS 源码目录是单数 Source/、模板生成的是复数 Sources/,整目录删会把上游被跟踪的文件一起删掉。
七、已知限制
- 子页面 uri 依赖系统实现:表里未覆盖或某版本不存在的页面会退回设置首页(日志写明);
- 部分安卓概念在鸿蒙没有独立页面:NFC 归在"更多连接"下,数据漫游/飞行模式归在"移动网络"下,因此共用同一个 uri;
app/app-notifications依赖pushParams:设置应用是否支持该参数由系统决定,不支持时同样退回首页;- 不模拟 iOS"只能开本应用设置页"的限制:
system()等方法照常打开对应页面,行为更接近安卓; - 示例 SDK 约束被放宽、模板文件被清理(原因见第六节)。
八、常见问题
Q1:为什么鸿蒙要用 uri 而不是像安卓那样一个 Action 一个页面?
鸿蒙把"系统设置"整体做成一个应用(com.huawei.hmos.settings),页面之间是它内部的导航,对外只暴露 uri 这一层约定。所以适配的形状就是"一个 Want + 一张方法名到 uri 的表"。
Q2:子页面 uri 从哪来?
属于系统约定(各版本设置应用内部的深链名),不是公开 API。这也是实现里必须做"打不开就退回首页"的原因——不要假设某个 uri 一定存在。
Q3:为什么插件还需要 UIAbility?
startAbility 的调用方必须是 UIAbilityContext;插件默认只拿到二进制信使(BinaryMessenger)。所以本插件实现 AbilityAware,由框架在 ability 绑定时把 UIAbility 交给它。
Q4:app 和 app-notifications 怎么定位到"我这个应用"?
同一个设置页 + want.parameters.pushParams = <自身包名>。是否生效由设置应用决定,不生效时退回首页。
Q5:25 个方法都要一个一个测吗?
不必。日志里每个方法都会留 (ok) 或 falling back,先用日志定位"哪些 uri 不被识别",再对关键页面截图。本次实测 system / bluetooth / nfc 三个页面日志与截图都对得上。
Q6:为什么示例不能直接用上游的?
上游示例本身能跑,但鸿蒙侧的 SDK 约束(Dart 2)会直接卡住构建;自检台还顺便把"25 个方法各自的调用结果"可视化,方便对照日志。
Q7:需要声明权限吗?
不需要。startAbility 跳系统设置页不涉及权限声明。
Q8:能不能改设置项(比如直接开关 Wi-Fi)?
不能,也不应该。本库的 Dart API 只有"打开页面",写系统设置需要系统权限;鸿蒙实现严格保持"只跳转、不修改"。
九、本篇用到的库
| 项 | 值 |
|---|---|
| 适配仓库 | https://atomgit.com/oh-flutter/system_settings_2 |
| 上游仓库 | https://github.com/timmaffett/system_settings_2 |
| 上游版本 | 3.0.2(MIT,master db8faac 与发布版逐文件一致) |
| 适配 TAG | 3.0.2-ohos-1.0.0-beta.1 |
| 适配分支 | feat/ohos_system_settings_2_3.0.2 |
| 通道 | 方法通道 system_settings_2(25 个无参方法) |
| 鸿蒙侧依赖 | @kit.AbilityKit(Want / UIAbility)、@ohos.flutter_ohos(AbilityAware) |
dependencies:
system_settings_2:
git:
url: https://atomgit.com/oh-flutter/system_settings_2.git
ref: 3.0.2-ohos-1.0.0-beta.1
验证环境
| 项 | 值 |
|---|---|
| Flutter for OpenHarmony SDK | 3.44.9+ohos-0.0.1-canary1(Dart 3.12.2) |
| DevEco Studio | 26.0.0.621 |
| 设备 | Pura 90 模拟器,HarmonyOS 6.1.1(24) / API 24,ohos-x64(1320×2856) |
| 构建产物 | example/build/ohos/hap/entry-default-signed.hap |
复现命令
$env:PUB_CACHE = "E:\pub-cache"
cd _probe/ss2_work/example/ohos
devecocli signature generate # 首次需要;提交前清空 signingConfigs
cd ..
flutter build hap --debug --target-platform ohos-x64
hdc install -r build/ohos/hap/entry-default-signed.hap
hdc shell aa start -a EntryAbility -b xyz.hiveright.system_settings_2_example
# 依次点"设置首页 / 无线与网络 / WLAN / 蓝牙 / NFC",每次回桌面截图
hdc shell snapshot_display -f /data/local/tmp/ss2.jpeg
hdc file recv /data/local/tmp/ss2.jpeg .
hdc shell hilog -x | Select-String "SystemSettingsPlugin"
欢迎加入 CPF-Flutter 鸿蒙社区:https://atomgit.com/CPF-Flutter
更多推荐



所有评论(0)