Flutter 鸿蒙实战:用 battery_plus 三方库给应用加上电池状态监测与充电动效

Flutter 社区地址: https://atomgit.com/CPF-Flutter/flutter_flutter
github三方库地址:https://github.com/fluttercommunity/plus_plugins/tree/main/packages/battery_plus/battery_plus
pub地址:https://pub.dev/packages/battery_plus
鸿蒙适配版:https://atomgit.com/CPF-Flutter/flutter_plus_plugins
我的工程适配地址:https://atomgit.com/weixin_52908342/battery_demo

库版本:battery_plus 4.1.0(CPF-Flutter 鸿蒙适配版,commit 9571de2)|验证环境:Flutter 鸿蒙 SDK 3.44.9(oh-3.44.9-dev)|DevEco Studio 26.0.0.821 | 设备:DevEco 模拟器 Pura X View | HarmonyOS 7.0.0.106(API 26)

应用里的电池状态提示、电量告警、充电动效几乎是移动 App 标配。battery_plus 是 Flutter 生态里用得最多的电池状态插件(pub.dev 月下载百万级),CPF-Flutter 社区已在 flutter_plus_plugins monorepo 里完成鸿蒙适配。本文介绍它在 OpenHarmony 上的引入方式、4 个接口的逐个调用与真实运行效果,并附 FAQ 与问题反馈流程。
在这里插入图片描述
在这里插入图片描述
isInBatterySaveMode

一、环境搭建

本章不重复展开,直接引用官方文档:Flutter OH 开发环境搭建指导
在这里插入图片描述

完成后用 flutter doctor -v 验证,FlutterHarmonyOS toolchain 两项均为 [√] 即可。本文实际使用的版本:Flutter OH oh-3.44.9-dev(commit 77e0c8d13b)、DevEco Studio 26.0.0.821、HarmonyOS SDK API 26。

二、应用背景

2.1 当前的应用场景与痛点

  • 儿童手表 / 老人手环类 App:需要根据电池余量动态降低刷新率、上传频率
  • 导航 / 出行类:电量不足时提示用户充电,自动降级 UI 亮度
  • 共享设备类:实时上报设备电量给云端
  • 视频 / 游戏类:低电量时关闭高耗电特效

痛点在于:Flutter 官方 battery_plus 只覆盖 Android/iOS/Web/Windows/macOS/Linux,鸿蒙侧此前一片空白——应用迁到 OpenHarmony 后电池相关功能直接失效。

2.2 为什么需要这个库

自己写插件需要处理 ArkTS 通道、系统 API 差异、事件流生命周期,成本高;battery_plus 的鸿蒙适配版由 CPF-Flutter 社区维护,一行 git 依赖即可获得跨端一致的 API。

2.3 解决什么问题

一句话总结:让 Flutter 应用在鸿蒙上以与 Android/iOS 完全相同的 API 读取电池状态。具体提供:

  1. 当前电量百分比(0-100)
  2. 电池状态(充电中 / 放电中 / 已充满 / 未知)
  3. 省电模式查询
  4. 电池状态变化事件流(免轮询、自动推送)

三、功能介绍

功能API说明适用场景
电量查询batteryLevel返回 Future<int>,0-100电量展示、低电告警
状态查询batteryState返回 Future<BatteryState> 枚举充电动效、充电提示音
省电模式isInBatterySaveMode返回 Future<bool>省电模式下降低刷新率
状态变化流onBatteryStateChangedStream<BatteryState>,订阅后自动推送实时监听插拔充电线

四、使用方法

4.1 在应用中引入三方库(AtomGit 链接方式)

dependencies:
  flutter:
    sdk: flutter
  battery_plus:
    git:
      url: https://atomgit.com/CPF-Flutter/flutter_plus_plugins.git
      ref: 9571de239933ab2893dbd49037e128135b050a7c
      path: packages/battery_plus/battery_plus

三个注意点:

  1. path 必须写到双层目录 packages/battery_plus/battery_plus(monorepo 里插件在嵌套子目录),写成 packages/battery_plus 会 404
  2. ref 建议写 commit hash(本文用 9571de2),tag/分支名可能漂移
  3. URL 用 AtomGit 而非 pub.dev——pub 上的 battery_plus 没有 ohos 平台实现,必须走 CPF-Flutter 的适配仓库

执行 flutter pub get 后即可 import 'package:battery_plus/battery_plus.dart';

4.2 调用接口实现功能

4.2.1 Battery():获取单例
final battery = Battery();

Battery 是单例工厂:第二次 Battery() 会复用同一实例。不要重复创建,否则事件流订阅会被覆盖。

4.2.2 batteryLevel:电量查询

功能说明:异步 getter,返回当前电量百分比(0-100 的整数)。

final level = await battery.batteryLevel;
print('当前电量:$level%');

运行效果

batteryLevel 运行效果
demo 首屏:大字 100% 即 batteryLevel 返回值,电量充足时显示绿色。下方副标题标注了对应的 API 名。

4.2.3 batteryState:状态查询

功能说明:异步 getter,返回 BatteryState 枚举(charging / discharging / full / unknown)。

final state = await battery.batteryState;
switch (state) {
  case BatteryState.charging:    print('充电中');
  case BatteryState.discharging: print('放电中');
  case BatteryState.full:        print('已充满');
  default:                       print('未知');
}

运行效果

batteryState 变化
通过 DevEco 模拟器命令 Emulator -instance "Pura X View" -battery 65 改变电量后刷新:大字变为 65%,事件流日志累积了多次调用记录。模拟器无真实电池硬件,batteryState 显示 unknown 属正常行为。

4.2.4 isInBatterySaveMode:省电模式查询

功能说明:异步 getter,返回设备是否处于省电模式。注意方法名是 isInBatterySaveMode(不是 isInPowerSaveMode,早期文档有此拼写错误)。

final powerSave = await battery.isInBatterySaveMode;
if (powerSave) {
  // 降级:关闭高刷、减少上报频率
}

运行效果

isInBatterySaveMode
右侧卡片:isInBatterySaveMode() 返回 false(省电模式未开启)。鸿蒙适配版当前固定返回 false,见 5.1 Q5。

4.2.5 onBatteryStateChanged:状态变化事件流

功能说明Stream<BatteryState>,订阅一次持续推送,免去手动轮询。必须在 dispose() 里 cancel 防止泄漏。

StreamSubscription<BatteryState>? _sub;


void initState() {
  super.initState();
  _sub = battery.onBatteryStateChanged.listen((s) {
    print('电池状态变化:${s.name}');
  });
}


void dispose() {
  _sub?.cancel();
  super.dispose();
}

运行效果

onBatteryStateChanged 事件触发
通过模拟器命令 Emulator -batteryStatus 1(切换到充电态)触发真实事件:底部暗色事件流卡新增一行 [00:54:45] onBatteryStateChanged → charging——无需任何手动刷新,事件自动推送到 Dart 层;顶部状态栏电池图标同步出现闪电符号。

补充:battery_plus 4.x 没有 onBatteryLevelChanged(电量百分比变化流),如需细粒度电量监控请自行 Timer.periodic 轮询 batteryLevel

4.3 完整示例代码

可直接复制运行的 main.dart(含 4 个接口的全调用 + 事件流日志 UI):

import 'dart:async';

import 'package:battery_plus/battery_plus.dart';
import 'package:flutter/material.dart';

void main() => runApp(const BatteryApp());

class BatteryApp extends StatelessWidget {
  const BatteryApp({super.key});

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'battery_plus · OpenHarmony',
      theme: ThemeData(colorSchemeSeed: const Color(0xFF2EA043)),
      home: const BatteryPage(),
    );
  }
}

class BatteryPage extends StatefulWidget {
  const BatteryPage({super.key});

  
  State<BatteryPage> createState() => _BatteryPageState();
}

class _BatteryPageState extends State<BatteryPage> {
  final _battery = Battery();
  int _level = -1;
  BatteryState _state = BatteryState.unknown;
  bool _powerSave = false;
  final List<String> _events = [];
  StreamSubscription<BatteryState>? _stateSub;

  
  void initState() {
    super.initState();
    _refresh();
    _stateSub = _battery.onBatteryStateChanged.listen((s) {
      _log('onBatteryStateChanged → ${s.name}');
    });
  }

  
  void dispose() {
    _stateSub?.cancel();
    super.dispose();
  }

  void _log(String msg) {
    final now = DateTime.now();
    setState(() {
      _events.insert(0,
          '[${now.hour.toString().padLeft(2, '0')}:${now.minute.toString().padLeft(2, '0')}:${now.second.toString().padLeft(2, '0')}] $msg');
      if (_events.length > 30) _events.removeLast();
    });
  }

  Future<void> _refresh() async {
    final level = await _battery.batteryLevel;
    final state = await _battery.batteryState;
    bool powerSave = false;
    try {
      powerSave = await _battery.isInBatterySaveMode;
    } catch (_) {
      powerSave = false;
    }
    if (!mounted) return;
    setState(() {
      _level = level;
      _state = state;
      _powerSave = powerSave;
    });
    _log('手动刷新:电量 $level%,状态 ${state.name}');
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('battery_plus · OpenHarmony')),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: [
          Text('$_level%', style: const TextStyle(fontSize: 64)),
          Text('状态:${_state.name} | 省电:$_powerSave'),
          FilledButton(onPressed: _refresh, child: const Text('手动刷新')),
          ..._events.map(Text.new),
        ],
      ),
    );
  }
}

签名与构建(活动要求示例工程含 signingConfig: "default"):

flutter create --platforms ohos .        # 生成 ohos 工程目录
# 在 ohos/build-profile.json5 填入签名材料(DevEco 自动生成于 ~/.ohos/config/)
flutter build hap --debug
hdc install build/ohos/hap/entry-default-signed.hap

无真机时,DevEco 模拟器可用命令脚本化触发电池状态,验证全部接口:

Emulator -instance "<模拟器名>" -battery 18          # 低电量(demo 变红)
Emulator -instance "<模拟器名>" -battery 65          # 中等电量(绿色)
Emulator -instance "<模拟器名>" -batteryStatus 1     # 触发 charging 事件流

五、FAQ

5.1 常见问题

Q1:编译报 The getter 'onBatteryLevelChanged' isn't defined
battery_plus 4.x 只有 onBatteryStateChanged(状态流),没有电量百分比流。用 Timer.periodic 轮询 batteryLevel 替代。

Q2:编译报 The getter 'isInPowerSaveMode' isn't defined
拼写错误:正确方法是 isInBatterySaveMode

Q3:batteryState 在模拟器上一直返回 unknown
正常现象——模拟器无真实电池硬件。用 Emulator -batteryStatus 0|1 强制切换状态可触发事件流;真机上会返回真实状态。

Q4:flutter pub get 解析失败/找不到包
检查 path: packages/battery_plus/battery_plus 是否写完整(双层目录);镜像用 export PUB_HOSTED_URL=https://pub.flutter-io.cn

Q5:isInBatterySaveMode 始终返回 false
鸿蒙适配版当前实现固定返回 false(省电模式真实监听尚未实现),属于已知限制。可关注上游仓库 issue 跟踪进度。

5.2 库本身存在问题:如何提交 Issue

仓库地址:https://atomgit.com/CPF-Flutter/flutter_plus_plugins

  1. 打开仓库 → Issues → 新建 Issue
  2. 标题:[Bug] 现象简述(如 [Bug] isInBatterySaveMode always returns false on OHOS
  3. 正文必备:复现步骤、期望行为、实际行为、设备与 SDK 版本(flutter --version + hdc shell param get const.product.software.version)、最小复现代码
  4. 附上 demo 截图 / hilog 日志(hdc shell hilog -t OHOSAbility -x

5.3 能自己解决:如何提交 PR

  1. Fork 仓库到自己账号:AtomGit 仓库页右上角 Fork
  2. 建分支git checkout -b fix/battery-save-mode
  3. 修改并提交
    git add packages/battery_plus/
    git commit -m "fix(battery_plus): read isInBatterySaveMode from PowerManager on OHOS"
    git push -u origin fix/battery-save-mode
    
  4. 发 PR:AtomGit 上 从 <你的账号>:fix/battery-save-modeCPF-Flutter:master,描述中附鸿蒙设备验证截图(修改后 isInBatterySaveMode 正确返回 true 的效果)

六、其他内容

battery_plus 4.1.0 鸿蒙适配版开箱即用:一行 git 依赖 + 四个 API 即可覆盖电量查询、状态查询、省电模式、状态监听全部场景。配合 DevEco 模拟器的电池模拟命令,无需真机也能完整验证每个接口。已知限制是 isInBatterySaveMode 固定返回 false(可通过社区 Issue/PR 推动)。相比自己从零写 ArkTS 插件,直接复用 CPF-Flutter 适配成果是明显更优的选择。

Logo

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

更多推荐