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

适配分支: feat/ohos_power_saver_plugin_0.0.1

受测提交: bd222d01a59a34327e9f60fa5d5804cbfc0ed69d

一、最终效果与适配目标

视频预加载、动画质量和后台同步常要根据省电模式降级。power_saver_plugin 0.0.1 已提供系统版本、电量、省电状态以及两类变化流,本次适配保持 Dart API 不变,在 OHOS 上接入 Power、BatteryInfo 和公共事件。

在这里插入图片描述

图 1:CHZ-AL00 / HarmonyOS 7.0.0.105 上初始电量为 100%,原系统电源模式为性能模式 602,插件读取为非省电。

在这里插入图片描述

图 2:切换至省电模式后,插件收到 true 事件,页面同步显示省电开启。

在这里插入图片描述

图 3:按真实系统允许的路径恢复到性能模式,插件回读非省电并收到关闭事件。

验证点实测结果证据
初始读取系统版本、电量 100%、非省电状态通过图 1、图 8
省电事件602 切到 601 后收到 true图 2
状态恢复601 -> 600 -> 602 恢复性能模式,收到 false图 3
自动化与构建8 Dart + 2 Widget + 11 ArkTS,共 21 项及 HAP 通过图 6、图 7
验证边界电量数值变化、超级/自定义省电和其他机型未验证图 8

二、成果速览

项目内容
上游基线0.0.1,提交 a62b7cfcbc8fca91490b3742c6bc6c590c9f3d28,MIT
适配分支feat/ohos_power_saver_plugin_0.0.1
适配提交bd222d01a59a34327e9f60fa5d5804cbfc0ed69d
新增 OHOS 能力系统版本、电量、省电状态读取及两类公共事件
保持不变的接口PowerSaverPlugin 的 3 个查询、2 个 Stream 和 dispose()
权限无需新增权限
真机结论真实省电开关与原性能模式恢复通过;电量变化事件未验

2026 年 9 月 11 日核对 pub.dev、上游仓库和三方库适配清单时,0.0.1 是最新发布版本,目标组织中未发现同名 OHOS 实现。随后以最新提交保留历史同步到 AtomGit。

三、实测环境

组件实测版本
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
插件power_saver_plugin 0.0.1

环境搭建参考 Flutter OH 环境搭建指南。本文实测正式稳定版 3.41.10-ohos-1.0.1;版本号更大的 3.44.9+ohos-0.0.1-canary1 是预览版。

四、同步与创建适配分支

git clone https://atomgit.com/oh-flutter/power_saver_plugin.git
cd power_saver_plugin
git switch -c feat/ohos_power_saver_plugin_0.0.1 a62b7cfcbc8fca91490b3742c6bc6c590c9f3d28
flutter create --template=plugin --platforms=ohos --no-pub .

模板插件改成 PowerSaverPlugin,保留 power_saver_plugin 通道。分支新增 OHOS HAR、example、双语文档、Dart/Widget/ArkTS 测试和真机入口,其他平台实现不改。

在这里插入图片描述

图 4:AtomGit origin、适配分支、完整 HEAD 和工作区状态。

五、读取接口和事件契约

final PowerSaverPlugin plugin = PowerSaverPlugin();
final String? version = await plugin.getPlatformVersion();
final bool saving = await plugin.isPowerSavingMode();
final int? battery = await plugin.getBatteryPercentage();

final StreamSubscription<bool> modeSub =
    plugin.onPowerSaverModeChanged.listen((bool value) {});
final StreamSubscription<int> batterySub =
    plugin.onBatteryPercentageChanged.listen((int value) {});

这个库通过单一 MethodChannel 反向调用 Dart 发送事件,而不是 EventChannel。每个 PowerSaverPlugin 实例会设置 channel handler,因此上游契约事实上只适合一个活跃实例。使用方应在页面或服务层集中持有实例,保存两个订阅,并在结束时依次取消订阅和调用 plugin.dispose()

六、Power 模式映射与公共事件

OHOS 查询分别使用 deviceInfo.osFullNamepower.getPowerMode()batteryInfo.batterySOC。省电语义按模式映射:普通 600 与性能 602 为 false,省电 601、超级省电 603 和 API 20 自定义省电 650 为 true;未知模式不猜测,显式报错。电量必须是 0 到 100 的整数。

const mode = power.getPowerMode();
if ([power.DevicePowerMode.MODE_POWER_SAVE,
     power.DevicePowerMode.MODE_EXTREME_POWER_SAVE,
     650].includes(mode)) return true;
if ([power.DevicePowerMode.MODE_NORMAL,
     power.DevicePowerMode.MODE_PERFORMANCE].includes(mode)) return false;
throw new Error(`Unknown power mode: ${mode}`);

插件订阅 COMMON_EVENT_POWER_SAVE_MODE_CHANGEDCOMMON_EVENT_BATTERY_CHANGED。收到事件后重新读取系统真值,再通过 powerSaverModeChangedbatteryPercentageChanged 回调 Dart;无关事件不投递,读取失败也不伪造 false 或 0。订阅创建失败通过 powerObservationError 同时进入两个 Stream 的 error 分支。Engine 解绑会注销 subscriber 并清除 channel。

在这里插入图片描述

图 5:电源模式映射、电量校验、公共事件注册与错误传播。

这些公开系统查询和事件不要求额外权限,插件 module.json5 无需添加 requestPermissions。

七、自动化与 HAP 构建

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

8 项 Dart、2 项 Widget、11 项 ArkTS,共 21 项通过。覆盖查询类型、所有模式映射、非法电量、未知模式、两类事件、无关事件、订阅失败、错误流、幂等 dispose、晚到回调和 Engine 重绑。

在这里插入图片描述

图 6:静态检查、21 项功能测试和示例错误状态结果。

在这里插入图片描述

图 7:无签名 HAP 元数据、摘要和受测提交。

八、固定提交和真实电源模式回环

dependencies:
  power_saver_plugin:
    git:
      url: https://atomgit.com/oh-flutter/power_saver_plugin.git
      ref: bd222d01a59a34327e9f60fa5d5804cbfc0ed69d

隔离宿主锁文件解析到同一 SHA,签名构建和覆盖安装通过。测试前原生回读为性能模式 602。设备拒绝从 601 直接切回 602,所以第一次直接恢复没有被伪装成成功;最终按照系统允许的 602 -> 601 -> 600 -> 602 完成回环。插件事件为 [true, false, false],两个 false 分别对应普通模式和性能模式。最后原生回读 602,插件读取 saving=false

在这里插入图片描述

图 8:真实模式路径、插件事件和最终恢复结果,失败的首次恢复尝试仍在原始日志中保留。

真机电量在本轮始终为 100%,因此只验证了电量读取和公共事件注册,没有制造电量变化来证明变化值回调;超级省电和自定义省电也未主动切换。

应用内补拍:模式回环全过程

在这里插入图片描述

图 9:恢复流程前再次读取性能模式,页面显示省电关闭、电源模式为性能模式。

在这里插入图片描述

图 10:切换到省电模式后,页面实时显示省电开启,并记录真实开启事件。

在这里插入图片描述

图 11:按 602 -> 601 -> 600 -> 602 完成恢复,页面显示省电关闭、电源模式回到性能模式。

九、FAQ

Q1:为什么 601 不能直接恢复到 602

  • 现象: 从省电模式直接请求性能模式被系统拒绝。
  • 原因: 当前设备要求先回到普通模式,再进入性能模式。
  • 解决方法: 记录原模式,并按 601 -> 600 -> 602 恢复;每一步都回读系统状态。
  • 验证结果: 最终原生模式为 602,插件为非省电,事件序列是 [true, false, false]

Q2:为什么收到公共事件后还要重新查询

  • 现象: 事件只说明某项能力变化,不应依赖不完整 payload 猜状态。
  • 原因: 公共事件数据在系统版本间可能不同,当前真值以 Power/BatteryInfo 为准。
  • 解决方法: 收到事件后调用 isSaving()batteryLevel(),校验成功才发给 Dart。
  • 验证结果: 原生测试确认失败读取不会产生假的状态事件。

Q3:为什么建议只创建一个插件实例

  • 现象: 多个实例都调用 setMethodCallHandler,后创建实例可能覆盖前一个处理器。
  • 原因: 这是上游单 MethodChannel 回调模型的固有限制。
  • 解决方法: 在应用服务层集中持有一个实例,并统一分发两个广播流。
  • 验证结果: 本次示例和真机宿主都使用单实例;多实例并非已验证能力。

十、总结

power_saver_plugin 0.0.1 已在 OHOS 上补齐系统版本、电量、省电状态和两类变化通知。21 项自动化、HAP 构建、真实省电开启以及恢复原性能模式均已通过,且全过程没有申请额外权限。

当前未覆盖电量变化、超级/自定义省电、多实例和其他设备。业务应锁定受测 SHA,将省电信号用于体验降级,而不是替代自己的任务成功与网络状态判断。

十一、参考链接

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

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐