navigator.getbattery()需在promise解析后监听chargingchange、levelchange等事件,因batterymanager实例异步创建且https环境才可用,android webview及ios safari不支持,隐私策略会导致数据模糊化。

如何用 navigator.getBattery() 检测电池状态变化
现代浏览器(Chrome 61+、Edge 79+、Firefox 120+)支持 navigator.getBattery(),但它返回的是一个 Promise,不是实时对象。直接调用后不监听事件,就只能拿到初始快照,无法响应充电插拔、电量跌落等动态变化。
关键点:必须用 .then() 获取 BatteryManager 实例,再对它的四个事件监听:
-
chargingchange:充电状态切换(true/false) -
levelchange:电量百分比变化(精度约 1%,非连续触发) -
chargingtimechange:预估充满时间变动(如从“充电中”变为“已充满”) -
dischargingtimechange:预估剩余放电时间变动
为什么 addEventListener 必须在 getBattery() 的 Promise 解析后注册
因为 BatteryManager 实例是异步创建的,且所有事件监听器都绑定在该实例上。如果先写 battery.addEventListener(...) 再 await,会报 TypeError: Cannot read property 'addEventListener' of undefined。
正确顺序示例:
if ('getBattery' in navigator) {
navigator.getBattery().then(battery => {
// ✅ 此时 battery 是有效实例
battery.addEventListener('chargingchange', () => {
console.log('充电状态:', battery.charging); // true / false
});
battery.addEventListener('levelchange', () => {
console.log('当前电量:', Math.round(battery.level * 100) + '%');
});
});
}
常见失效场景和兼容性注意点
即使 API 存在,也未必能拿到真实数据:
- HTTPS 环境下才可用(HTTP 页面中
navigator.getBattery返回undefined) - 部分 Android WebView 或旧版 Safari(iOS 一直不支持)直接不提供该 API
- 某些系统级省电模式或隐私设置(如 Firefox 的“增强型跟踪保护”)会禁用电池信息,返回固定值:
level: 1.0、charging: true、chargingTime: Infinity -
levelchange不会高频触发——它只在系统上报显著变化时发出(比如从 87% → 85%,但不会报告 87% → 86.9%)
如何安全降级并避免未定义错误
不能假设 battery 一定有值,也不能假设所有属性都可读。尤其 chargingTime 和 dischargingTime 在未知状态下可能为 Infinity 或 NaN,直接参与计算会出错。
推荐写法:
battery.addEventListener('levelchange', () => {
if (battery.level === null || isNaN(battery.level)) return;
const percent = Math.round(battery.level * 100);
// ...
});
<p>battery.addEventListener('chargingchange', () => {
if (battery.charging === null) return;
const status = battery.charging ? 'charging' : 'discharging';
// ...
});</p>
真正难处理的不是监听逻辑,而是系统有意模糊化电池数据——这是隐私策略决定的,不是代码能绕过的。你看到的“电量跳变”或“充电状态延迟”,大概率是底层主动限频或脱敏的结果。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











