在这里插入图片描述

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

🎯 欢迎来到 Flutter for OpenHarmony 第三方库实战系列!本文将带你实现电池状态监测功能,通过 battery_plus 库获取设备电量、充电状态、节能模式等信息。


🚀 项目概述:我们要构建什么?

电池状态是移动应用开发中重要的系统信息,合理利用电池信息可以优化应用行为,提升用户体验。battery_plus 提供了跨平台的电池状态监控能力,支持获取电池电量、充电状态、节能模式检测以及实时监听电池状态变化。

本文将构建的应用具备以下核心特性:

🔋 电量获取:获取当前电池电量百分比(0-100)。

⚡ 充电状态:获取电池状态(充电中、放电中、满电、未知)。

🌱 节能模式:检测设备是否处于节能模式。

📡 实时监听:监听电池状态的实时变化。

充电状态变化

电量变化

低于 20%

充电中

应用启动

创建 Battery 实例

获取初始电池信息

batteryLevel - 电量百分比

batteryState - 充电状态

isInBatterySaveMode - 节能模式

显示电池信息

监听状态变化

电池状态改变

更新 UI

电量判断

显示低电量警告

可执行耗电任务

🎯 核心功能一览

功能模块 属性/方法 核心能力
🔋 电量获取 batteryLevel 获取电池电量百分比
⚡ 充电状态 batteryState 获取充电状态
🌱 节能模式 isInBatterySaveMode 检测节能模式
📡 状态监听 onBatteryStateChanged 监听电池状态变化

💡 为什么选择 battery_plus?

1️⃣ 官方维护

Flutter Community 官方维护的插件,质量和更新有保障。

2️⃣ 跨平台支持

支持 Android、iOS、macOS、Windows、Linux、Web 和 OpenHarmony 等多个平台。

3️⃣ 功能完整

支持电量获取、状态检测、节能模式判断和状态变化监听。

4️⃣ OpenHarmony 原生适配

专门针对 OpenHarmony 平台进行了适配,完整支持所有功能。

📋 电池状态枚举

状态 说明
BatteryState.full 电池处于满电状态
BatteryState.charging 电池处于充电状态
BatteryState.discharging 电池处于放电状态
BatteryState.unknown 电池状态未知

📦 第一步:环境配置

1.1 添加依赖

在开始编码之前,我们需要先配置项目的依赖。打开项目根目录下的 pubspec.yaml 文件,添加以下内容。

dependencies:
  flutter:
    sdk: flutter

  # 电池状态监测(OpenHarmony 适配版本)
  battery_plus:
    git:
      url: "https://atomgit.com/openharmony-sig/flutter_plus_plugins.git"
      path: "packages/battery_plus/battery_plus"

1.2 执行依赖安装

配置完成后,在项目根目录执行以下命令来下载并安装所有依赖包。

flutter pub get

1.3 权限配置

在 OpenHarmony 平台上,使用 battery_plus 获取电池信息不需要额外配置权限。该插件使用系统公开的电池信息接口,无需申请特殊权限。


📱 第二步:电池功能详解

2.1 核心 API 介绍

Battery 类

主接口类,提供电池信息获取功能。

class Battery {
  // 获取电池电量百分比(0-100)
  Future<int> get batteryLevel;
  
  // 获取电池状态
  Future<BatteryState> get batteryState;
  
  // 检测是否处于节能模式
  Future<bool> get isInBatterySaveMode;
  
  // 监听电池状态变化
  Stream<BatteryState> get onBatteryStateChanged;
}

BatteryState 枚举

enum BatteryState {
  // 满电状态
  full,
  
  // 充电中
  charging,
  
  // 放电中
  discharging,
  
  // 未知状态
  unknown,
}

⚠️ 重要说明

  • batteryLevel 返回 0-100 的整数
  • 模拟器上可能返回 unknown 状态
  • 监听状态变化时记得在 dispose 时取消订阅

2.2 电池服务实现

下面的 BatteryService 类封装了电池信息获取的逻辑。

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

class BatteryService extends ChangeNotifier {
  final Battery _battery = Battery();
  
  int _batteryLevel = 0;
  BatteryState _batteryState = BatteryState.unknown;
  bool _isInBatterySaveMode = false;
  StreamSubscription<BatteryState>? _subscription;

  int get batteryLevel => _batteryLevel;
  BatteryState get batteryState => _batteryState;
  bool get isInBatterySaveMode => _isInBatterySaveMode;
  
  bool get isCharging => _batteryState == BatteryState.charging;
  bool get isFull => _batteryState == BatteryState.full;
  bool get isLowBattery => _batteryLevel < 20;

  Future<void> initialize() async {
    await _loadBatteryInfo();
    _startListening();
  }

  Future<void> _loadBatteryInfo() async {
    try {
      final level = await _battery.batteryLevel;
      final state = await _battery.batteryState;
      final saveMode = await _battery.isInBatterySaveMode;

      _batteryLevel = level;
      _batteryState = state;
      _isInBatterySaveMode = saveMode;
      notifyListeners();
    } catch (e) {
      debugPrint('获取电池信息失败: $e');
    }
  }

  void _startListening() {
    _subscription = _battery.onBatteryStateChanged.listen((state) {
      _batteryState = state;
      notifyListeners();
    });
  }

  Future<void> refresh() async {
    await _loadBatteryInfo();
  }

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

🎨 第三步:完整示例代码

下面是一个完整的电池状态监测应用。

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:battery_plus/battery_plus.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 BatteryPage(),
      debugShowCheckedModeBanner: false,
    );
  }
}

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

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

class _BatteryPageState extends State<BatteryPage> {
  final Battery _battery = Battery();

  int _batteryLevel = 0;
  BatteryState _batteryState = BatteryState.unknown;
  bool _isInBatterySaveMode = false;
  StreamSubscription<BatteryState>? _batteryStateSubscription;

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

  Future<void> _initBatteryInfo() async {
    final level = await _battery.batteryLevel;
    final state = await _battery.batteryState;
    final saveMode = await _battery.isInBatterySaveMode;

    setState(() {
      _batteryLevel = level;
      _batteryState = state;
      _isInBatterySaveMode = saveMode;
    });
  }

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

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

  IconData _getBatteryIcon(BatteryState state, int level) {
    if (state == BatteryState.charging) {
      return Icons.battery_charging_full;
    } else if (state == BatteryState.full) {
      return Icons.battery_full;
    } else if (level <= 20) {
      return Icons.battery_alert;
    } else if (level <= 50) {
      return Icons.battery_4_bar;
    } else if (level <= 80) {
      return Icons.battery_5_bar;
    } else {
      return Icons.battery_full;
    }
  }

  Color _getBatteryColor(int level, BatteryState state) {
    if (state == BatteryState.charging) {
      return Colors.green;
    } else if (level <= 20) {
      return Colors.red;
    } else if (level <= 50) {
      return Colors.orange;
    } else {
      return Colors.green;
    }
  }

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

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('电池状态'),
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        actions: [
          IconButton(
            icon: const Icon(Icons.refresh),
            onPressed: _initBatteryInfo,
            tooltip: '刷新',
          ),
        ],
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(16),
        child: Column(
          children: [
            _buildBatteryCard(),
            const SizedBox(height: 16),
            _buildStatusCard(),
            const SizedBox(height: 16),
            _buildSaveModeCard(),
            const SizedBox(height: 16),
            _buildTipsCard(),
          ],
        ),
      ),
    );
  }

  Widget _buildBatteryCard() {
    final color = _getBatteryColor(_batteryLevel, _batteryState);
    final icon = _getBatteryIcon(_batteryState, _batteryLevel);

    return Card(
      child: Padding(
        padding: const EdgeInsets.all(24),
        child: Column(
          children: [
            Icon(
              icon,
              size: 100,
              color: color,
            ),
            const SizedBox(height: 16),
            Text(
              '$_batteryLevel%',
              style: TextStyle(
                fontSize: 56,
                fontWeight: FontWeight.bold,
                color: color,
              ),
            ),
            const SizedBox(height: 8),
            Text(
              '电池电量',
              style: TextStyle(
                fontSize: 16,
                color: Colors.grey.shade600,
              ),
            ),
            const SizedBox(height: 16),
            _buildBatteryBar(),
          ],
        ),
      ),
    );
  }

  Widget _buildBatteryBar() {
    return Column(
      children: [
        Row(
          children: [
            Expanded(
              child: ClipRRect(
                borderRadius: BorderRadius.circular(8),
                child: LinearProgressIndicator(
                  value: _batteryLevel / 100,
                  backgroundColor: Colors.grey.shade300,
                  valueColor: AlwaysStoppedAnimation<Color>(
                    _getBatteryColor(_batteryLevel, _batteryState),
                  ),
                  minHeight: 12,
                ),
              ),
            ),
          ],
        ),
        const SizedBox(height: 8),
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            Text('0%', style: TextStyle(color: Colors.grey.shade500)),
            Text('50%', style: TextStyle(color: Colors.grey.shade500)),
            Text('100%', style: TextStyle(color: Colors.grey.shade500)),
          ],
        ),
      ],
    );
  }

  Widget _buildStatusCard() {
    IconData statusIcon;
    Color statusColor;
    String statusDescription;

    switch (_batteryState) {
      case BatteryState.charging:
        statusIcon = Icons.power;
        statusColor = Colors.green;
        statusDescription = '设备正在充电,可以执行耗电任务';
        break;
      case BatteryState.full:
        statusIcon = Icons.battery_full;
        statusColor = Colors.green;
        statusDescription = '电池已充满,电量充足';
        break;
      case BatteryState.discharging:
        statusIcon = Icons.power_off;
        statusColor = _batteryLevel < 20 ? Colors.red : Colors.orange;
        statusDescription = _batteryLevel < 20
            ? '电量较低,建议充电'
            : '设备正在使用电池供电';
        break;
      case BatteryState.unknown:
        statusIcon = Icons.help_outline;
        statusColor = Colors.grey;
        statusDescription = '无法获取电池状态';
        break;
    }

    return Card(
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Row(
          children: [
            Container(
              width: 56,
              height: 56,
              decoration: BoxDecoration(
                color: statusColor.withOpacity(0.1),
                borderRadius: BorderRadius.circular(12),
              ),
              child: Icon(
                statusIcon,
                size: 28,
                color: statusColor,
              ),
            ),
            const SizedBox(width: 16),
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    '状态: ${_getBatteryStateText(_batteryState)}',
                    style: const TextStyle(
                      fontSize: 16,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                  const SizedBox(height: 4),
                  Text(
                    statusDescription,
                    style: TextStyle(
                      fontSize: 14,
                      color: Colors.grey.shade600,
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildSaveModeCard() {
    return Card(
      child: ListTile(
        leading: Container(
          width: 48,
          height: 48,
          decoration: BoxDecoration(
            color: _isInBatterySaveMode
                ? Colors.orange.withOpacity(0.1)
                : Colors.grey.withOpacity(0.1),
            borderRadius: BorderRadius.circular(12),
          ),
          child: Icon(
            _isInBatterySaveMode ? Icons.energy_savings_leaf : Icons.eco,
            color: _isInBatterySaveMode ? Colors.orange : Colors.grey,
          ),
        ),
        title: const Text('节能模式'),
        subtitle: Text(
          _isInBatterySaveMode
              ? '已开启 - 系统将限制后台活动'
              : '未开启',
        ),
        trailing: Switch(
          value: _isInBatterySaveMode,
          onChanged: null,
        ),
      ),
    );
  }

  Widget _buildTipsCard() {
    return Card(
      color: Theme.of(context).colorScheme.surfaceContainerHighest,
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              children: [
                Icon(
                  Icons.lightbulb_outline,
                  color: Theme.of(context).colorScheme.primary,
                ),
                const SizedBox(width: 8),
                Text(
                  '使用场景',
                  style: Theme.of(context).textTheme.titleMedium?.copyWith(
                    fontWeight: FontWeight.bold,
                  ),
                ),
              ],
            ),
            const SizedBox(height: 12),
            const Text('• 低电量时减少后台任务'),
            const Text('• 充电时执行耗电操作'),
            const Text('• 节能模式下降低刷新频率'),
            const Text('• 根据电量调整动画效果'),
            const Text('• 低电量警告提示用户'),
          ],
        ),
      ),
    );
  }
}

❓ 第四步:常见问题与解决方案

1. 电池状态返回 unknown

原因:模拟器或某些特殊设备无法获取电池状态。

解决方案

String getSafeStateText(BatteryState state) {
  if (state == BatteryState.unknown) {
    return '无法获取';
  }
  return _getBatteryStateText(state);
}

// 建议在真机上测试

2. 电池状态监听不触发

原因:某些设备不会频繁触发状态变化事件。

解决方案

// 结合定时刷新和事件监听
class BatteryManager {
  final Battery _battery = Battery();
  Timer? _refreshTimer;
  StreamSubscription? _subscription;
  
  void startMonitoring(Function onUpdate) {
    // 定时刷新(每分钟)
    _refreshTimer = Timer.periodic(
      const Duration(minutes: 1),
      (_) => onUpdate(),
    );
    
    // 监听状态变化
    _subscription = _battery.onBatteryStateChanged.listen((_) => onUpdate());
  }
  
  void stopMonitoring() {
    _refreshTimer?.cancel();
    _subscription?.cancel();
  }
}

3. 根据电量优化应用行为

解决方案

class BatteryAwareTaskManager {
  final Battery _battery = Battery();
  
  Future<bool> shouldExecuteTask() async {
    final batteryLevel = await _battery.batteryLevel;
    final isInSaveMode = await _battery.isInBatterySaveMode;
    final state = await _battery.batteryState;
    
    if (batteryLevel < 20 || isInSaveMode) {
      return false;
    }
    
    if (state == BatteryState.discharging && batteryLevel < 50) {
      return false;
    }
    
    return true;
  }
  
  Future<void> executeHeavyTask() async {
    if (await shouldExecuteTask()) {
      print('执行耗电任务');
    } else {
      print('跳过耗电任务');
    }
  }
}

4. 低电量警告提示

解决方案

class LowBatteryWarning {
  final Battery _battery = Battery();
  StreamSubscription? _subscription;
  static const int _warningThreshold = 20;
  bool _hasShownWarning = false;

  void startMonitoring(BuildContext context) {
    _subscription = _battery.onBatteryStateChanged.listen((state) async {
      if (state == BatteryState.discharging) {
        final level = await _battery.batteryLevel;
        if (level < _warningThreshold && !_hasShownWarning) {
          _hasShownWarning = true;
          _showWarningDialog(context, level);
        } else if (level >= _warningThreshold) {
          _hasShownWarning = false;
        }
      }
    });
  }

  void _showWarningDialog(BuildContext context, int level) {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: const Row(
          children: [
            Icon(Icons.battery_alert, color: Colors.red),
            SizedBox(width: 8),
            Text('低电量警告'),
          ],
        ),
        content: Text('当前电量仅剩 $level%,请及时充电'),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: const Text('知道了'),
          ),
        ],
      ),
    );
  }

  void stopMonitoring() {
    _subscription?.cancel();
  }
}

5. 充电状态检测

解决方案

Future<bool> isCharging() async {
  final battery = Battery();
  final state = await battery.batteryState;
  return state == BatteryState.charging || state == BatteryState.full;
}

Future<void> performHeavyTask() async {
  if (await isCharging()) {
    print('正在充电,可以执行耗电任务');
    // 执行同步、下载、处理等任务
  } else {
    print('未在充电,建议推迟耗电任务');
  }
}

6. 结合 StreamBuilder 实现响应式 UI

解决方案

class BatteryStatusWidget extends StatelessWidget {
  final Battery _battery = Battery();

  BatteryStatusWidget({super.key});

  
  Widget build(BuildContext context) {
    return StreamBuilder<BatteryState>(
      stream: _battery.onBatteryStateChanged,
      builder: (context, snapshot) {
        final state = snapshot.data ?? BatteryState.unknown;
        
        return FutureBuilder<int>(
          future: _battery.batteryLevel,
          builder: (context, levelSnapshot) {
            final level = levelSnapshot.data ?? 0;
            
            return ListTile(
              leading: Icon(
                state == BatteryState.charging
                    ? Icons.battery_charging_full
                    : Icons.battery_std,
                color: level < 20 ? Colors.red : Colors.green,
              ),
              title: Text('电量: $level%'),
              subtitle: Text('状态: ${state.name}'),
            );
          },
        );
      },
    );
  }
}

📚 API 参考

Battery 类

属性/方法 返回值 说明
batteryLevel Future<int> 电池电量百分比
batteryState Future<BatteryState> 电池状态
isInBatterySaveMode Future<bool> 是否节能模式
onBatteryStateChanged Stream<BatteryState> 状态变化流

BatteryState 枚举

说明
full 满电状态
charging 充电中
discharging 放电中
unknown 未知状态

🎉 总结

本文详细介绍了 battery_plus 库在 OpenHarmony 平台上的使用方法,包括:

  1. 环境配置:添加依赖配置
  2. API 使用:获取电量、状态、节能模式等信息
  3. 完整示例:包含信息展示、状态监听的电池监测应用
  4. 问题解决:常见问题的排查和解决方案

通过电池状态监测功能,开发者可以:

  • 根据电量优化应用行为
  • 在充电时执行耗电任务
  • 低电量时减少后台活动
  • 提供更好的用户体验

battery_plus 提供了完整的电池信息获取能力,是 OpenHarmony 平台上实现电池状态监测的理想选择。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐