欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

本文基于flutter3.27.5开发

一、battery_plus 库概述

电池状态监控是移动应用开发中的常见需求,应用需要根据电池电量、充电状态等信息来优化性能或提醒用户。在 Flutter for OpenHarmony 应用开发中,battery_plus 是一个功能完善的电池状态监控插件,提供了跨平台的电池信息获取能力。

battery_plus 库特点

battery_plus 库基于 Flutter 平台接口实现,提供了以下核心特性:

电量获取:支持获取当前设备电池电量百分比,帮助应用了解设备剩余电量。

充电状态监控:支持获取当前充电状态(充电中、放电中、满电、未知),并支持状态变化监听。

节能模式检测:支持检测设备是否处于节能模式,帮助应用优化性能策略。

状态变化监听:提供 Stream 接口,实时监听电池状态变化,无需轮询。

功能支持对比

功能 Android iOS OpenHarmony
获取电量
获取充电状态
状态变化监听
节能模式检测

使用场景:低电量提醒、性能优化策略、充电状态显示、电池健康监控等。


二、安装与配置

2.1 添加依赖

在项目的 pubspec.yaml 文件中添加 battery_plus 依赖:

dependencies:
  battery_plus:
    git:
      url: https://atomgit.com/openharmony-sig/flutter_plus_plugins.git
      path: packages/battery_plus/battery_plus

然后执行以下命令获取依赖:

flutter pub get

2.2 权限配置

battery_plus 在 OpenHarmony 平台上不需要额外权限配置,系统电池信息接口可直接访问。


三、核心 API 详解

3.1 Battery 类

Battery 是 battery_plus 库的核心类,采用单例模式设计,提供电池信息获取的所有方法。

class Battery {
  factory Battery() {
    _singleton ??= Battery._();
    return _singleton!;
  }
}

使用示例

final battery = Battery();

3.2 batteryLevel 属性

batteryLevel 属性用于获取当前电池电量百分比。

Future<int> get batteryLevel

返回值:返回 0-100 之间的整数,表示电池电量百分比。

使用示例

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

3.3 batteryState 属性

batteryState 属性用于获取当前电池充电状态。

Future<BatteryState> get batteryState

返回值:返回 BatteryState 枚举值,表示当前充电状态。

使用示例

final battery = Battery();
final state = await battery.batteryState;
print('充电状态: $state');

3.4 isInBatterySaveMode 属性

isInBatterySaveMode 属性用于检测设备是否处于节能模式。

Future<bool> get isInBatterySaveMode

返回值:返回布尔值,true 表示设备处于节能模式。

使用示例

final battery = Battery();
final isSaveMode = await battery.isInBatterySaveMode;
if (isSaveMode) {
  print('设备处于节能模式');
}

3.5 onBatteryStateChanged 属性

onBatteryStateChanged 属性是一个 Stream,用于监听电池状态变化。

Stream<BatteryState> get onBatteryStateChanged

返回值:返回 BatteryState 的 Stream,每次电池状态变化时触发。

使用示例

final battery = Battery();
battery.onBatteryStateChanged.listen((BatteryState state) {
  print('电池状态变化: $state');
});

3.6 BatteryState 枚举

BatteryState 枚举定义了电池的所有可能状态。

enum BatteryState {
  full,
  charging,
  discharging,
  unknown
}

枚举值说明

枚举值 说明
full 电池已充满
charging 正在充电中
discharging 正在放电中(使用中)
unknown 状态未知

四、OpenHarmony 平台实现原理

4.1 原生 API 映射

battery_plus 在 OpenHarmony 平台上使用 @ohos.batteryInfo@ohos.power 模块实现:

Flutter API OpenHarmony API
batteryLevel batteryInfo.batterySOC
batteryState batteryInfo.chargingStatus
isInBatterySaveMode power.getPowerMode()

4.2 充电状态映射

OpenHarmony 的 BatteryChargeState 与 Flutter 的 BatteryState 映射关系:

OpenHarmony 状态 Flutter 状态
BatteryChargeState.NONE unknown
BatteryChargeState.ENABLE charging
BatteryChargeState.DISABLE discharging
BatteryChargeState.FULL full

4.3 状态监听实现

OpenHarmony 平台通过定时器轮询实现状态变化监听:

const UPDATE_INTERVAL = 200;

onListen(args: Any, events: EventSink): void {
  this.battery_events = events;
  this.timerId = setInterval(this.chargeModeCallback, UPDATE_INTERVAL);
}

chargeModeCallback: Callback<EventSink> = () => {
  const battertChargeState: string = this.getChargingStatus();
  if (battertChargeState != this.chargeMode && this.battery_events) {
    this.chargeMode = battertChargeState;
    this.battery_events.success(this.chargeMode);
  }
}

五、实战案例

5.1 获取电池基本信息

Future<void> getBatteryInfo() async {
  final battery = Battery();
  
  final level = await battery.batteryLevel;
  final state = await battery.batteryState;
  final isSaveMode = await battery.isInBatterySaveMode;
  
  print('电量: $level%');
  print('状态: $state');
  print('节能模式: $isSaveMode');
}

5.2 监听电池状态变化

StreamSubscription<BatteryState>? _subscription;

void startListening() {
  final battery = Battery();
  _subscription = battery.onBatteryStateChanged.listen((state) {
    switch (state) {
      case BatteryState.charging:
        print('开始充电');
        break;
      case BatteryState.discharging:
        print('正在使用电池');
        break;
      case BatteryState.full:
        print('充电完成');
        break;
      case BatteryState.unknown:
        print('状态未知');
        break;
    }
  });
}

void stopListening() {
  _subscription?.cancel();
  _subscription = null;
}

5.3 低电量提醒

Future<void> checkLowBattery() async {
  final battery = Battery();
  final level = await battery.batteryLevel;
  
  if (level <= 20) {
    print('电量不足,请及时充电');
  } else if (level <= 10) {
    print('电量严重不足!');
  }
}

5.4 根据电量优化性能

Future<void> optimizePerformance() async {
  final battery = Battery();
  final level = await battery.batteryLevel;
  final isSaveMode = await battery.isInBatterySaveMode;
  
  if (isSaveMode || level <= 20) {
    print('启用省电模式,降低动画帧率');
  } else {
    print('正常性能模式');
  }
}

5.5 完整的电池监控组件

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

  
  State<BatteryMonitor> createState() => _BatteryMonitorState();
}

class _BatteryMonitorState extends State<BatteryMonitor> {
  final Battery _battery = Battery();
  int _batteryLevel = 0;
  BatteryState _batteryState = BatteryState.unknown;
  bool _isSaveMode = false;
  StreamSubscription<BatteryState>? _subscription;

  
  void initState() {
    super.initState();
    _initBatteryInfo();
    _listenBatteryState();
  }

  Future<void> _initBatteryInfo() async {
    final level = await _battery.batteryLevel;
    final state = await _battery.batteryState;
    final isSaveMode = await _battery.isInBatterySaveMode;
    
    setState(() {
      _batteryLevel = level;
      _batteryState = state;
      _isSaveMode = isSaveMode;
    });
  }

  void _listenBatteryState() {
    _subscription = _battery.onBatteryStateChanged.listen((state) {
      setState(() {
        _batteryState = state;
      });
    });
  }

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

  
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('电量: $_batteryLevel%'),
        Text('状态: ${_getStateText()}'),
        Text('节能模式: ${_isSaveMode ? "开启" : "关闭"}'),
      ],
    );
  }

  String _getStateText() {
    switch (_batteryState) {
      case BatteryState.charging:
        return '充电中';
      case BatteryState.discharging:
        return '使用中';
      case BatteryState.full:
        return '已充满';
      case BatteryState.unknown:
        return '未知';
    }
  }
}

六、最佳实践

6.1 及时取消监听

监听电池状态变化时,务必在组件销毁时取消订阅:


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

6.2 错误处理

对电池信息获取进行错误处理:

Future<void> safeGetBatteryLevel() async {
  try {
    final battery = Battery();
    final level = await battery.batteryLevel;
    print('电量: $level%');
  } on PlatformException catch (e) {
    print('获取电量失败: ${e.message}');
  }
}

6.3 性能优化建议

根据电池状态调整应用行为:

Future<void> adjustAppBehavior() async {
  final battery = Battery();
  final level = await battery.batteryLevel;
  final isSaveMode = await battery.isInBatterySaveMode;
  
  if (isSaveMode || level < 20) {
    // 禁用后台任务
    // 降低动画帧率
    // 减少网络请求频率
  }
}

6.4 避免频繁获取

电池状态变化监听已由插件内部处理,避免在代码中频繁调用获取方法:

// 不推荐:频繁轮询
Timer.periodic(Duration(seconds: 1), (_) async {
  final state = await battery.batteryState;
});

// 推荐:使用 Stream 监听
battery.onBatteryStateChanged.listen((state) {
  // 自动响应状态变化
});

七、常见问题

Q1:为什么获取的电量有时候不准确?

电池电量由系统提供,可能存在一定的延迟或误差。建议在关键操作前重新获取最新电量。

Q2:onBatteryStateChanged 的触发频率是多少?

OpenHarmony 平台实现中,默认每 200ms 检查一次状态变化,只有状态真正改变时才会触发事件。

Q3:节能模式检测支持哪些平台?

目前节能模式检测支持 Android、iOS、Windows 和 OpenHarmony 平台。

Q4:如何在模拟器上测试电池功能?

部分模拟器支持模拟电池状态。建议使用真机测试以获得准确结果。

Q5:Web 平台支持情况如何?

Web 平台依赖浏览器的 Battery Status API,部分浏览器可能不支持或返回有限信息。

Q6:为什么不在充电时显示"未知"而不是"使用中"?

这是 battery_plus OpenHarmony 平台实现的一个已知问题。当设备使用电池供电(不在充电)时,OpenHarmony 的 BatteryChargeState.NONE 状态被错误地映射为 "unknown",而不是 "discharging"

由于 battery_plus 是第三方库(非本地项目代码),无法直接修改其实现。临时解决方案是在前端代码中处理这种异常情况:

String _getStateText(BatteryState state) {
  switch (state) {
    case BatteryState.charging:
      return '充电中';
    case BatteryState.discharging:
    case BatteryState.unknown:
      // OpenHarmony平台上BatteryChargeState.NONE返回unknown
      // 实际上是放电状态
      return '使用中';
    case BatteryState.full:
      return '已充满';
  }
}

或者在获取状态时进行转换:

BatteryState convertUnknownToDischarging(BatteryState state) {
  if (state == BatteryState.unknown) {
    return BatteryState.discharging;
  }
  return state;
}

八、总结

battery_plus 库为 Flutter for OpenHarmony 开发提供了完整的电池状态监控能力。通过简洁的 API,开发者可以轻松获取电量、充电状态、节能模式等信息,并实时监听状态变化。该库在鸿蒙平台上已经完成了完整的适配,支持所有核心功能,开发者可以放心使用。


九、完整代码示例

以下是一个完整的可运行示例,展示了 battery_plus 库的核心功能:
在这里插入图片描述

pubspec.yaml

name: battery_plus_demo
description: Flutter for OpenHarmony battery_plus 演示项目
publish_to: 'none'
version: 1.0.0+1

environment:
  sdk: '>=3.0.0 <4.0.0'

dependencies:
  flutter:
    sdk: flutter
  battery_plus:
    git:
      url: https://atomgit.com/openharmony-sig/flutter_plus_plugins.git
      path: packages/battery_plus/battery_plus

flutter:
  uses-material-design: true

main.dart

import 'dart:async';

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

void main() {
  runApp(const MyApp());
}

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

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Battery Plus Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.green),
        useMaterial3: true,
      ),
      home: const HomePage(),
    );
  }
}

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

  
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  final Battery _battery = Battery();
  int _batteryLevel = 0;
  BatteryState _batteryState = BatteryState.unknown;
  bool _isSaveMode = false;
  StreamSubscription<BatteryState>? _subscription;
  List<String> _stateHistory = [];

  
  void initState() {
    super.initState();
    _initBatteryInfo();
    _listenBatteryState();
  }

  Future<void> _initBatteryInfo() async {
    try {
      final level = await _battery.batteryLevel;
      final state = await _battery.batteryState;
      final isSaveMode = await _battery.isInBatterySaveMode;
      
      setState(() {
        _batteryLevel = level;
        _batteryState = state;
        _isSaveMode = isSaveMode;
      });
    } catch (e) {
      _showMessage('获取电池信息失败: $e');
    }
  }

  void _listenBatteryState() {
    _subscription = _battery.onBatteryStateChanged.listen((state) {
      setState(() {
        _batteryState = state;
        _stateHistory.insert(0, '${DateTime.now().toString().substring(11, 19)} - ${_getStateText(state)}');
        if (_stateHistory.length > 10) {
          _stateHistory.removeLast();
        }
      });
    });
  }

  void _showMessage(String message) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text(message)),
    );
  }

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

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Battery Plus 演示'),
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            const Text(
              '电池状态监控',
              style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
              textAlign: TextAlign.center,
            ),
            const SizedBox(height: 24),
            
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  children: [
                    Icon(
                      _getBatteryIcon(),
                      size: 80,
                      color: _getBatteryColor(),
                    ),
                    const SizedBox(height: 16),
                    Text(
                      '$_batteryLevel%',
                      style: const TextStyle(
                        fontSize: 48,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    const SizedBox(height: 8),
                    Text(
                      _getStateText(_batteryState),
                      style: TextStyle(
                        fontSize: 18,
                        color: _getBatteryColor(),
                      ),
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 16),
            
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    const Text(
                      '详细信息',
                      style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
                    ),
                    const Divider(),
                    _buildInfoRow('电量', '$_batteryLevel%'),
                    _buildInfoRow('状态', _getStateText(_batteryState)),
                    _buildInfoRow('节能模式', _isSaveMode ? '开启' : '关闭'),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 16),
            
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        const Text(
                          '状态变化历史',
                          style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
                        ),
                        TextButton(
                          onPressed: () {
                            setState(() {
                              _stateHistory.clear();
                            });
                          },
                          child: const Text('清空'),
                        ),
                      ],
                    ),
                    const Divider(),
                    if (_stateHistory.isEmpty)
                      const Text('暂无状态变化记录')
                    else
                      Column(
                        children: _stateHistory.map((record) {
                          return Padding(
                            padding: const EdgeInsets.symmetric(vertical: 4),
                            child: Text(record),
                          );
                        }).toList(),
                      ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 16),
            
            ElevatedButton.icon(
              onPressed: _initBatteryInfo,
              icon: const Icon(Icons.refresh),
              label: const Text('刷新电池信息'),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildInfoRow(String label, String value) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 8),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          Text(label, style: const TextStyle(color: Colors.grey)),
          Text(value, style: const TextStyle(fontWeight: FontWeight.bold)),
        ],
      ),
    );
  }

  IconData _getBatteryIcon() {
    if (_batteryState == BatteryState.charging) {
      return Icons.battery_charging_full;
    }
    if (_batteryLevel >= 90) return Icons.battery_full;
    if (_batteryLevel >= 70) return Icons.battery_6_bar;
    if (_batteryLevel >= 50) return Icons.battery_5_bar;
    if (_batteryLevel >= 30) return Icons.battery_4_bar;
    if (_batteryLevel >= 20) return Icons.battery_3_bar;
    if (_batteryLevel >= 10) return Icons.battery_2_bar;
    if (_batteryLevel >= 5) return Icons.battery_1_bar;
    return Icons.battery_0_bar;
  }

  Color _getBatteryColor() {
    if (_batteryState == BatteryState.charging) {
      return Colors.green;
    }
    if (_batteryLevel <= 20) {
      return Colors.red;
    }
    if (_batteryLevel <= 50) {
      return Colors.orange;
    }
    return Colors.green;
  }

  String _getStateText(BatteryState state) {
    switch (state) {
      case BatteryState.charging:
        return '充电中';
      case BatteryState.discharging:
        return '使用中';
      case BatteryState.full:
        return '已充满';
      case BatteryState.unknown:
        return '未知';
    }
  }
}

运行此示例后,您将看到一个完整的电池状态监控界面,包含电量显示、充电状态、节能模式状态以及状态变化历史记录。连接充电器或断开充电时,界面会自动更新显示最新状态。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐