环境搭建指引: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_2deps 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。)


三、六步适配流程

  1. 建仓:node .agents/tools/atomgit.mjs create oh-flutter system_settings_2 "…"
  2. 克隆:git clone https://gh-proxy.com/https://github.com/timmaffett/system_settings_2.git _probe/ss2_work
  3. 建分支 + 补鸿蒙目录: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}
  4. 写实现:ohos/src/main/ets/components/plugin/SystemSettingsPlugin.ets
  5. 补文档与示例:三份 README.OpenHarmony* / CHANGELOG.OpenHarmony.md、根 README 说明、示例改成自检台
  6. 推送打 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"
方法设备侧结果
systemsystem -> com.huawei.hmos.settings uri="" (ok);截图确认打开的是设置首页(含 WLAN/显示和亮度/声音和振动/关于本机等入口)
wireless / wifi点击成功、截图留档;两者都落到 wifi_entry(鸿蒙的"无线与网络"就是 WLAN 页)
bluetoothbluetooth -> com.huawei.hmos.settings uri="bluetooth_entry" (ok)
nfcnfc -> 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 与发布版逐文件一致)
适配 TAG3.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 SDK3.44.9+ohos-0.0.1-canary1(Dart 3.12.2)
DevEco Studio26.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

Logo

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

更多推荐