Flutter实现:获取应用电池使用占比及安卓系统电池统计信息
Flutter 获取安卓应用电池使用百分比数据
核心前提:权限要求
安卓系统对电池统计数据的访问有严格限制,必须申请android.permission.BATTERY_STATS权限,而且这个权限无法通过代码直接申请,需要引导用户跳转到应用的权限设置页面手动开启「查看电池使用情况」权限。
实现步骤
1. 配置安卓Manifest权限
在android/app/src/main/AndroidManifest.xml里添加权限声明:
<uses-permission android:name="android.permission.BATTERY_STATS" />
2. 原生安卓端实现数据获取
在安卓的MainActivity里创建MethodChannel,编写获取电池统计的逻辑:
import android.app.AppOpsManager import android.content.Context import android.os.Build import android.os.Process import androidx.annotation.NonNull import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel class MainActivity : FlutterActivity() { private val CHANNEL = "battery_stats" override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result -> if (call.method == "getAppBatteryUsage") { if (hasBatteryStatsPermission()) { val batteryUsage = getAppBatteryUsage() result.success(batteryUsage) } else { result.error("PERMISSION_DENIED", "需要开启电池统计权限", null) } } else { result.notImplemented() } } } private fun hasBatteryStatsPermission(): Boolean { val appOps = getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager val mode = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { appOps.unsafeCheckOpNoThrow(AppOpsManager.OPSTR_BATTERY_STATS, Process.myUid(), packageName) } else { appOps.checkOpNoThrow(AppOpsManager.OPSTR_BATTERY_STATS, Process.myUid(), packageName) } return mode == AppOpsManager.MODE_ALLOWED } private fun getAppBatteryUsage(): Double? { val batteryStatsManager = getSystemService(Context.BATTERY_STATS_SERVICE) as android.os.BatteryStatsManager val uid = Process.myUid() // 获取当前应用的电池使用百分比(相对于总电池消耗) val usagePercent = batteryStatsManager.getBatteryUsagePercentage( setOf(uid), android.os.BatteryStatsManager.STATS_SINCE_CHARGED, System.currentTimeMillis() ) return usagePercent } }
3. Flutter端调用原生方法
在Flutter代码里,通过MethodChannel调用原生接口,同时处理权限引导:
import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:url_launcher/url_launcher.dart'; class BatteryStatsPage extends StatefulWidget { const BatteryStatsPage({super.key}); @override State<BatteryStatsPage> createState() => _BatteryStatsPageState(); } class _BatteryStatsPageState extends State<BatteryStatsPage> { static const platform = MethodChannel('battery_stats'); double? _batteryUsagePercent; String? _errorMessage; Future<void> _getBatteryUsage() async { try { final double result = await platform.invokeMethod('getAppBatteryUsage'); setState(() { _batteryUsagePercent = result; _errorMessage = null; }); } on PlatformException catch (e) { setState(() { _errorMessage = e.message; _batteryUsagePercent = null; // 引导用户去开启权限 _openPermissionSettings(); }); } } Future<void> _openPermissionSettings() async { final Uri url = Uri.parse('package:${await platform.invokeMethod('getPackageName')}'); if (!await launchUrl(url, mode: LaunchMode.externalApplication)) { throw Exception('无法打开设置页面'); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('电池使用统计')), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ if (_batteryUsagePercent != null) Text( '当前应用电池使用占比: ${_batteryUsagePercent!.toStringAsFixed(2)}%', style: const TextStyle(fontSize: 18), ), if (_errorMessage != null) Text( _errorMessage!, style: const TextStyle(color: Colors.red, fontSize: 16), ), const SizedBox(height: 20), ElevatedButton( onPressed: _getBatteryUsage, child: const Text('获取电池使用数据'), ), ], ), ), ); } }
注意事项
- 上述代码仅适配安卓10及以上版本,低版本系统可能需要调整
BatteryStatsManager的调用逻辑,或者使用旧的BatteryStatsAPI。 - 不同安卓厂商可能对权限页面有自定义,引导用户开启时可能需要适配不同品牌的路径。
- 电池使用百分比是相对于设备自上次充电以来的总消耗占比,和系统设置里展示的数据逻辑一致。
内容的提问来源于stack exchange,提问作者Joel
相关产品推荐
相关产品推荐

