uni-app 中获取真实电量需绕过 uni.getBatteryInfo,Android 用 plus.android 读 sticky 广播 level/scale 计算百分比并声明 BATTERY_STATS 权限,iOS 需提前调 setBatteryMonitoringEnabled(true) 再读 batteryLevel;平台必须运行时判断,轮询间隔≥5秒,返回统一整数 0–100。

uni-app 里不能靠 uni.getBatteryInfo 拿到真实电量——Vue2 项目中它完全静默失效,Vue3 虽能用但依赖插件且 Android/iOS 行为不一致。真机可用的方案只有一条:绕过 uni 封装,用 plus.android 和 plus.ios 直接调原生。
Android 端必须用 ACTION_BATTERY_CHANGED 广播读取 level 和 scale
Android 不提供实时回调接口,ACTION_BATTERY_CHANGED 是 sticky broadcast,注册即得最新快照值,但必须同时读 level 和 scale 才能算出百分比:
-
level单独读可能返回 -1(尤其在部分 Android 12+ 机型),直接除会出NaN或崩溃 -
scale是分母,不是固定值,不同设备可能为 100、255 或其他,硬编码 100 会严重失准 - 计算必须用
Math.floor((level / scale) * 100),避免浮点误差导致显示 “100.0000000001%” - 权限必须声明
android.permission.BATTERY_STATS,否则真机运行时直接闪退(不是报错) - 别试
getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)——Android 10+ 上基本返回 0 或抛异常,targetSdkVersion ≥ 30 后已被系统限制
iOS 端必须先调 setBatteryMonitoringEnabled(true) 才能读 batteryLevel
iOS 的 batteryLevel 默认是 -1.0,不是“没值”,而是明确表示监控未启用。不提前开启,永远拿不到有效数据:
- 必须在 App 启动早期(比如
App.vue的onLaunch)就执行dev.setBatteryMonitoringEnabled(true),不能等用户点按钮才触发 -
dev.batteryLevel()返回的是 0.0 ~ 1.0 浮点数,要乘以 100 再Math.round()得整数百分比(如 0.94 → 94) - 模拟器永远返回 -1.0 或
undefined,plus.ios 在模拟器下不可用,不连真机测不出任何东西 - 后台状态下该值不再刷新,即使 App 还在运行,电量也会卡住——轮询逻辑必须加判断,避免误判
不能复用一套代码,平台分支必须显式判断
别用 process.env.UNI_PLATFORM 统一处理,它在某些构建环境下可能不准;必须用 plus && plus.os.name === 'Android' 或 === 'iOS' 做运行时判断:
- Android 侧注册广播 receiver 时,不能传
null(Android 8+ 会拒绝),得用plus.android.implements实现一个真正类实例 - iOS 侧如果漏掉
isBatteryMonitoringEnabled()判断,后续所有batteryLevel()都是 -1,前端显示 “-1%” 是常见错误现象 - 封装成工具函数时,返回值统一为整数 0–100,避免业务层重复做类型转换和边界校验
- Vue2 项目里
uni.getBatteryInfo是个“静默陷阱”:调了没反应、控制台无日志、success/fail 都不进——不是你写错了,是它压根没实现
轮询获取电量变化时,间隔不能低于 5 秒
Android 广播只能快照读取,iOS 没有监听机制,两者都只能靠定时轮询。但太密会反向耗电:
- 推荐间隔 ≥ 5000ms,太短(如 1000ms)会频繁唤醒 CPU,反而加速耗电
- 必须在页面卸载或组件销毁时
clearInterval,否则内存泄漏 - iOS 轮询要加防抖:连续两次读数相同且 >99%,可粗略认为已充满,避免无效刷新
- 充电状态(USB/AC/Wireless)无法通过原生 API 精确获取,只能靠
EXTRA_PLUGGED+ 电量趋势粗略判断
最容易被忽略的是:Android 广播注册后不用手动 unregisterReceiver,因为 ACTION_BATTERY_CHANGED 是 sticky 类型,系统不回收;而 iOS 的 setBatteryMonitoringEnabled(true) 是一次性全局开关,早开比晚开强——晚开一秒,就少一秒有效数据。


















