Flutter 鸿蒙插件适配实战:用 power_saver_plugin 0.0.1 读取电量并监听省电模式
适配仓库: 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 OH | 3.41.10-ohos-1.0.1 |
| Dart | 3.11.5 |
| DevEco Studio | 26.0.0 Release |
| HarmonyOS SDK | API 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.osFullName、power.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_CHANGED 和 COMMON_EVENT_BATTERY_CHANGED。收到事件后重新读取系统真值,再通过 powerSaverModeChanged 或 batteryPercentageChanged 回调 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
更多推荐



所有评论(0)