进阶实战 Flutter for OpenHarmony:battery_plus 第三方库实战 - 电池状态监控

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


🎯 一、组件概述与应用场景

📋 1.1 battery_plus 简介

在移动应用开发中,电池状态是一个重要的系统信息。battery_plus 是 Flutter 社区官方维护的电池信息获取插件,提供了跨平台的电池状态监控能力。开发者可以通过该插件获取设备电池电量、充电状态,以及监听电池状态变化,从而实现根据电池状态优化应用行为的功能。

核心特性:

特性 说明
🌐 跨平台支持 支持 Android、iOS、macOS、Web、Linux、Windows、OpenHarmony
📊 电量获取 获取当前电池电量百分比(0-100)
🔌 状态获取 获取电池状态(充电中、放电中、满电、未知)
📡 状态监听 实时监听电池状态变化
⚡ 节能模式 检测设备是否处于节能模式
🔒 单例模式 使用单例模式确保资源高效利用

💡 1.2 实际应用场景

低电量模式优化:当电量低于阈值时,自动降低应用性能以节省电量。

后台任务调度:根据电池状态决定是否执行后台同步任务。

游戏性能调节:在低电量时降低画质以保证续航。

下载任务管理:在充电时自动开始大文件下载。

省电提醒:当电量低于阈值时提醒用户充电。

🏗️ 1.3 系统架构设计

复制代码
┌─────────────────────────────────────────────────────────┐
│                    UI 展示层                             │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐     │
│  │ 电量显示组件 │  │ 状态监控面板 │  │ 省电建议页面 │     │
│  └─────────────┘  └─────────────┘  └─────────────┘     │
└─────────────────────────────────────────────────────────┘
                          │
                          ▼
┌─────────────────────────────────────────────────────────┐
│                    业务逻辑层                            │
│  ┌─────────────────────────────────────────────────┐   │
│  │          BatteryService 电池服务                 │   │
│  │  • getLevel()  • getState()  • isSaveMode()    │   │
│  └─────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────┘
                          │
                          ▼
┌─────────────────────────────────────────────────────────┐
│                    平台适配层                            │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐     │
│  │ Android     │  │ iOS         │  │ OpenHarmony │     │
│  └─────────────┘  └─────────────┘  └─────────────┘     │
└─────────────────────────────────────────────────────────┘

📦 二、项目配置与依赖安装

🔧 2.1 添加依赖配置

打开项目根目录下的 pubspec.yaml 文件,添加以下配置:

yaml 复制代码
dependencies:
  flutter:
    sdk: flutter

  # battery_plus - 电池状态监控插件
  battery_plus:
    git:
      url: https://atomgit.com/openharmony-sig/flutter_plus_plugins.git
      path: packages/battery_plus/battery_plus

配置说明:

  • 使用 git 方式引用开源鸿蒙适配的仓库
  • battery_plus 是 Flutter Community 官方维护的插件
  • 完整支持 OpenHarmony 平台所有功能

⚠️ 重要提示:对于 OpenHarmony 平台,必须使用 git 方式引用适配版本。

📥 2.2 下载依赖

配置完成后,在项目根目录执行以下命令:

bash 复制代码
flutter pub get

🔐 2.3 权限配置

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

📱 2.4 支持的功能

功能 说明 OpenHarmony 支持
batteryLevel 获取电池等级 ✅ yes
isInBatterySaveMode 判断是否处于节能模式 ✅ yes
batteryState 获取电池状态 ✅ yes
onBatteryStateChanged 监听电池状态改变 ✅ yes

🔋 2.5 电池状态枚举

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

🔧 三、核心功能详解

🎯 3.1 创建 Battery 实例

dart 复制代码
import 'package:battery_plus/battery_plus.dart';

final Battery _battery = Battery();

📊 3.2 获取电池电量

dart 复制代码
Future<int> getBatteryLevel() async {
  final batteryLevel = await _battery.batteryLevel;
  return batteryLevel; // 返回 0-100 的整数
}

🔌 3.3 获取电池状态

dart 复制代码
Future<BatteryState> getBatteryState() async {
  final state = await _battery.batteryState;
  return state; // 返回 BatteryState 枚举
}

⚡ 3.4 检测节能模式

dart 复制代码
Future<bool> isInBatterySaveMode() async {
  final isInSaveMode = await _battery.isInBatterySaveMode;
  return isInSaveMode; // 返回 true/false
}

📡 3.5 监听电池状态变化

dart 复制代码
StreamSubscription<BatteryState>? _subscription;

void startListening() {
  _subscription = _battery.onBatteryStateChanged.listen((BatteryState state) {
    print('电池状态变化: $state');
  });
}

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

📝 四、完整示例代码

下面是一个完整的智能电池状态监控系统示例:

dart 复制代码
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:battery_plus/battery_plus.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '智能电池状态监控系统',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.green),
        useMaterial3: true,
      ),
      home: const MainPage(),
    );
  }
}

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

  @override
  State<MainPage> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  int _currentIndex = 0;

  final List<Widget> _pages = [
    const BatteryStatusPage(),
    const PowerSavingPage(),
    const BatteryHistoryPage(),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: _pages[_currentIndex],
      bottomNavigationBar: NavigationBar(
        selectedIndex: _currentIndex,
        onDestinationSelected: (index) {
          setState(() => _currentIndex = index);
        },
        destinations: const [
          NavigationDestination(icon: Icon(Icons.battery_std), label: '电池状态'),
          NavigationDestination(icon: Icon(Icons.power), label: '省电模式'),
          NavigationDestination(icon: Icon(Icons.history), label: '历史记录'),
        ],
      ),
    );
  }
}

// ============ 电池状态页面 ============

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

  @override
  State<BatteryStatusPage> createState() => _BatteryStatusPageState();
}

class _BatteryStatusPageState extends State<BatteryStatusPage> {
  final Battery _battery = Battery();

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

  @override
  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() {
    _subscription = _battery.onBatteryStateChanged.listen((state) {
      _initBatteryInfo();
    });
  }

  String _getStateText(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 {
      return Icons.battery_6_bar;
    }
  }

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

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('电池状态'),
        centerTitle: true,
        actions: [
          IconButton(
            icon: const Icon(Icons.refresh),
            onPressed: _initBatteryInfo,
          ),
        ],
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(20),
        child: Column(
          children: [
            _buildBatteryCard(),
            const SizedBox(height: 24),
            _buildStatusCard(),
            const SizedBox(height: 24),
            _buildTipsCard(),
          ],
        ),
      ),
    );
  }

  Widget _buildBatteryCard() {
    return Container(
      padding: const EdgeInsets.all(32),
      decoration: BoxDecoration(
        gradient: LinearGradient(
          colors: [_getBatteryColor(_batteryLevel).withOpacity(0.8), _getBatteryColor(_batteryLevel)],
        ),
        borderRadius: BorderRadius.circular(24),
      ),
      child: Column(
        children: [
          Icon(
            _getBatteryIcon(_batteryState, _batteryLevel),
            size: 80,
            color: Colors.white,
          ),
          const SizedBox(height: 16),
          Text(
            '$_batteryLevel%',
            style: const TextStyle(
              fontSize: 56,
              fontWeight: FontWeight.bold,
              color: Colors.white,
            ),
          ),
          const SizedBox(height: 8),
          Container(
            padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 6),
            decoration: BoxDecoration(
              color: Colors.white.withOpacity(0.2),
              borderRadius: BorderRadius.circular(20),
            ),
            child: Text(
              _getStateText(_batteryState),
              style: const TextStyle(color: Colors.white, fontSize: 16),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildStatusCard() {
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          children: [
            _buildStatusItem(
              Icons.power,
              '节能模式',
              _isInBatterySaveMode ? '已开启' : '未开启',
              _isInBatterySaveMode ? Colors.orange : Colors.grey,
            ),
            const Divider(),
            _buildStatusItem(
              _batteryState == BatteryState.charging ? Icons.bolt : Icons.bolt_outlined,
              '充电状态',
              _getStateText(_batteryState),
              _batteryState == BatteryState.charging ? Colors.green : Colors.grey,
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildStatusItem(IconData icon, String title, String value, Color color) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 8),
      child: Row(
        children: [
          Icon(icon, color: color),
          const SizedBox(width: 16),
          Expanded(child: Text(title)),
          Text(value, style: TextStyle(color: color, fontWeight: FontWeight.w500)),
        ],
      ),
    );
  }

  Widget _buildTipsCard() {
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const Text('省电建议', style: TextStyle(fontWeight: FontWeight.bold)),
            const SizedBox(height: 12),
            if (_batteryLevel <= 20) ...[
              _buildTipItem('电量较低,建议尽快充电', Colors.red),
            ],
            if (_batteryLevel <= 50 && _batteryLevel > 20) ...[
              _buildTipItem('电量中等,可开启节能模式延长续航', Colors.orange),
            ],
            if (_isInBatterySaveMode) ...[
              _buildTipItem('节能模式已开启,部分功能可能受限', Colors.orange),
            ],
            if (_batteryLevel > 50 && !_isInBatterySaveMode) ...[
              _buildTipItem('电量充足,可正常使用', Colors.green),
            ],
          ],
        ),
      ),
    );
  }

  Widget _buildTipItem(String text, Color color) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 4),
      child: Row(
        children: [
          Container(
            width: 8,
            height: 8,
            decoration: BoxDecoration(
              color: color,
              shape: BoxShape.circle,
            ),
          ),
          const SizedBox(width: 12),
          Expanded(child: Text(text, style: TextStyle(color: color))),
        ],
      ),
    );
  }
}

// ============ 省电模式页面 ============

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('省电模式'),
        centerTitle: true,
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(20),
        child: Column(
          children: [
            _buildInfoCard(),
            const SizedBox(height: 24),
            _buildTipsList(),
          ],
        ),
      ),
    );
  }

  Widget _buildInfoCard() {
    return Container(
      padding: const EdgeInsets.all(24),
      decoration: BoxDecoration(
        gradient: LinearGradient(
          colors: [Colors.green.shade400, Colors.green.shade600],
        ),
        borderRadius: BorderRadius.circular(16),
      ),
      child: const Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            children: [
              Icon(Icons.power, color: Colors.white),
              SizedBox(width: 8),
              Text(
                '省电模式说明',
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 18,
                  fontWeight: FontWeight.bold,
                ),
              ),
            ],
          ),
          SizedBox(height: 12),
          Text(
            '开启省电模式后,系统会限制后台活动、降低性能以延长电池续航时间。',
            style: TextStyle(color: Colors.white70, height: 1.5),
          ),
        ],
      ),
    );
  }

  Widget _buildTipsList() {
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const Text('省电技巧', style: TextStyle(fontWeight: FontWeight.bold)),
            const SizedBox(height: 16),
            _buildTipItem('降低屏幕亮度'),
            _buildTipItem('关闭不必要的后台应用'),
            _buildTipItem('关闭蓝牙和定位服务'),
            _buildTipItem('使用深色主题'),
            _buildTipItem('减少通知推送'),
          ],
        ),
      ),
    );
  }

  Widget _buildTipItem(String text) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 8),
      child: Row(
        children: [
          Icon(Icons.check_circle, color: Colors.green.shade400, size: 20),
          const SizedBox(width: 12),
          Text(text),
        ],
      ),
    );
  }
}

// ============ 历史记录页面 ============

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

  @override
  State<BatteryHistoryPage> createState() => _BatteryHistoryPageState();
}

class _BatteryHistoryPageState extends State<BatteryHistoryPage> {
  final Battery _battery = Battery();
  final List<BatteryRecord> _records = [];
  StreamSubscription<BatteryState>? _subscription;

  @override
  void initState() {
    super.initState();
    _addRecord();
    _listenBatteryState();
  }

  void _addRecord() async {
    final level = await _battery.batteryLevel;
    final state = await _battery.batteryState;
    setState(() {
      _records.insert(0, BatteryRecord(
        level: level,
        state: state,
        time: DateTime.now(),
      ));
      if (_records.length > 20) {
        _records.removeLast();
      }
    });
  }

  void _listenBatteryState() {
    _subscription = _battery.onBatteryStateChanged.listen((_) {
      _addRecord();
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('历史记录'),
        centerTitle: true,
      ),
      body: _records.isEmpty
          ? const Center(child: Text('暂无记录'))
          : ListView.builder(
              padding: const EdgeInsets.all(16),
              itemCount: _records.length,
              itemBuilder: (context, index) {
                final record = _records[index];
                return _buildRecordCard(record);
              },
            ),
    );
  }

  Widget _buildRecordCard(BatteryRecord record) {
    return Card(
      margin: const EdgeInsets.only(bottom: 12),
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Row(
          children: [
            Container(
              width: 48,
              height: 48,
              decoration: BoxDecoration(
                color: _getColor(record.level).withOpacity(0.1),
                borderRadius: BorderRadius.circular(12),
              ),
              child: Center(
                child: Text(
                  '${record.level}%',
                  style: TextStyle(
                    color: _getColor(record.level),
                    fontWeight: FontWeight.bold,
                  ),
                ),
              ),
            ),
            const SizedBox(width: 16),
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    _getStateText(record.state),
                    style: const TextStyle(fontWeight: FontWeight.w500),
                  ),
                  Text(
                    _formatTime(record.time),
                    style: TextStyle(color: Colors.grey.shade600, fontSize: 12),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }

  Color _getColor(int level) {
    if (level <= 20) return Colors.red;
    if (level <= 50) return Colors.orange;
    return Colors.green;
  }

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

  String _formatTime(DateTime time) {
    return '${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}:${time.second.toString().padLeft(2, '0')}';
  }
}

class BatteryRecord {
  final int level;
  final BatteryState state;
  final DateTime time;

  BatteryRecord({
    required this.level,
    required this.state,
    required this.time,
  });
}

🏆 五、最佳实践与注意事项

⚠️ 5.1 单例使用

Battery 类设计为单例模式,建议在应用中只创建一个实例:

dart 复制代码
class BatteryService {
  static final Battery _instance = Battery();
  static Battery get instance => _instance;
}

📡 5.2 及时取消订阅

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

dart 复制代码
@override
void dispose() {
  _subscription?.cancel();
  super.dispose();
}

🔋 5.3 结合其他信息优化体验

将电池信息与网络状态、应用状态等结合,实现更智能的资源管理:

dart 复制代码
Future<bool> shouldPerformSync() async {
  final level = await _battery.batteryLevel;
  final state = await _battery.batteryState;
  final isInSaveMode = await _battery.isInBatterySaveMode;
  
  return level > 30 && state != BatteryState.discharging && !isInSaveMode;
}

📱 5.4 常见问题处理

状态返回 unknown:某些设备或模拟器可能返回 unknown,建议进行容错处理。

监听不触发:确保在正确的生命周期中启动监听,并在 dispose 中取消。


📌 六、总结

本文通过一个完整的智能电池状态监控系统案例,深入讲解了 battery_plus 插件的使用方法与最佳实践:

电量获取:掌握获取电池电量的基本方法。

状态监控:实现电池状态的实时监听。

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

智能优化:根据电池状态优化应用行为。

掌握这些技巧,你就能构建出专业级的电池状态监控功能,提升应用的续航体验。


参考资料

相关推荐
Geek_Vison32 分钟前
保险APP已经用了Flutter,还能接入小程序吗?
flutter·小程序·uni-app·mpaas·小程序容器
FungLeo1 小时前
成为全栈·Flutter App 篇·go_router 与四 Tab App Shell:保留导航状态、深链和登录回跳
flutter·移动开发·成为全栈·go_router·路由设计·深链接
m0_738185821 小时前
Flutter 鸿蒙化实战:screen_protector 适配 OpenHarmony,防截屏/防泄露
flutter·华为·harmonyos·鸿蒙
梦想的颜色7 小时前
【编程实战】AI 时代 APP 开发全栈硬核指南:技术选型 + AI 架构 + 模型落地全维度决策
python·flutter·react native·react.js·ai·桌面应用·milvus
yuanlaile1 天前
2026年全新Flutter 跨平台开发全栈学习资料整理
flutter·getx·鸿蒙 next·flutter开发鸿蒙·flutter入门实战·flutter全栈
恋猫de小郭2 天前
Genkit Dart 1.0 发布,Flutter 原生的 AI Agent 终于完整了
android·前端·flutter
第10086个小白2 天前
flutter桌面端打包方式(Inno Setup Compiler)版本
前端·flutter
陆断枫2 天前
Flutter 3.47 动画引擎盘点:Impeller 全平台,和那些"新特性"
flutter
程序员老刘2 天前
Flet 1.0 思路很好,可惜来晚了
flutter·ai编程·客户端
m0_738185822 天前
Flutter 鸿蒙化实战:qr_code_scanner_plus 适配 OpenHarmony,二维码扫描
flutter·华为·harmonyos·鸿蒙