版权声明 © 2024 万维网联盟(World Wide Web Consortium)。 W3C® 责任声明、商标以及 宽松文档许可证 规则适用。
本节描述本文档在发布时的状态。当前的 W3C 出版物列表以及本技术报告的最新修订版可在 https://w3org.cn/TR/ 的 W3C 技术报告索引 中找到。
设备与传感器工作组将在本规范上进行编辑现代化工作,对 API 的安全性与隐私方面进行一次自审与修订后,再请求横向审查。现有的安全与隐私问题已列出。
发布为工作草案并不意味着 W3C 及其成员的认可。
这是一份草案文档,可能会随时被其他文档更新、替换或废弃。将其作为非进行中工作引用是不恰当的。
本文件由遵循W3C 专利政策的组织编写。W3C维护一份针对本工作组交付物的专利披露公开列表;该页面还包含披露专利的说明。任何实际了解某专利且认为该专利包含必要权利要求的个人,必须依据《W3C 专利政策》第 6 节进行披露。
本文档受 2023 年 11 月 3 日 W3C 流程文档 管辖。
本节是非规范性的。
Battery Status API 规范定义了一种方式,使 Web 开发者能够以编程方式获取宿主设备的电池状态。如果不了解设备的电池状态,开发者只能假设设备有足够的电量来完成当前任务,这会导致设备的电池耗尽速度快于预期,因为开发者无法基于电池状态作出决策。若能获取电池信息,开发者就可以编写更节能的 Web 内容与应用,从而提升用户体验。但需要注意,若该 API 被天真地实现,可能会对电池寿命产生负面影响。
当设备未充电或电量不足时,Battery Status API 可用于推迟或缩减工作量。比如,一个高级 Web 邮件客户端在设备充电时可以每隔几秒向服务器检查新邮件,而在设备未充电或电量低时则降低检查频率。再如,基于 Web 的文字处理器可以监控电池电量,在电池耗尽前自动保存更改,以防止数据丢失。
除了标记为非规范性的章节外,本规范中的所有创作指南、图表、示例和注释均为非规范性内容。本规范中的其他所有内容均为规范性内容。
本文档中的关键字 MAY(可以)、MUST(必须)和 SHOULD(应该)应仅在全大写时,按照 BCP 14 [RFC2119] [RFC8174] 中的描述进行解释。
本规范定义了适用于单一产品的一致性标准:实现其所包含接口的 用户代理 (user agent)。
本规范中定义的 API 用于判断宿主设备的电池状态。
用户代理SHOULD不应暴露电池状态的高精度读数,因为这可能成为新的指纹识别向量。
用户代理MAY请求用户授权访问电池状态信息,或在其隐私浏览模式下强制执行用户权限要求。
用户代理SHOULD以不显眼的方式告知用户脚本正在使用该 API,以提升透明度并允许用户撤销该 API 的访问权限。
用户代理MAY对暴露的值进行混淆,使作者无法直接判断宿主设备是否无电池、是否在充电或是否提供了伪造值。
WebIDL[SecureContext, Exposed=Window]
interface BatteryManager : EventTarget {
readonly attribute boolean charging;
readonly attribute unrestricted double chargingTime;
readonly attribute unrestricted double dischargingTime;
readonly attribute double level;
attribute EventHandler onchargingchange;
attribute EventHandler onchargingtimechange;
attribute EventHandler ondischargingtimechange;
attribute EventHandler onlevelchange;
};
BatteryManager 接口表示宿主设备的当前电池状态信息。
如果用户代理 无法报告电池状态信息,则它无法为任意属性报告数值,例如因用户或系统偏好、设置或限制而导致的情况。
BatteryManager 实例在创建时拥有以下内部槽位
| 内部槽位 | 初始值 |
|---|---|
| [[Charging]] |
true
|
| [[ChargingTime]] | 0 |
| [[DischargingTime]] | 正无穷 |
| [[Level]] | 1.0 |
[[Charging]] 内部槽位表示系统电池的充电状态。若电池在放电则**MUST**设为 false,若电池在充电、实现无法报告状态、或系统未连接电池等情况下则**MUST**设为 true。
当系统电池的充电状态发生变化时,用户代理必须以 true 或 false(取决于电池是充电还是放电)以及 “chargingchange” 为参数,运行更新电池状态并通知算法。
[[ChargingTime]] 内部槽位表示系统电池完全充满所剩余的秒数。若电池已满或系统未连接电池,则**MUST**设为 0;若电池在放电、实现无法报告剩余充电时间或其它情况,则**MUST**设为正无穷。
当电池的充电时间更新时,用户代理必须以新的充电时间(秒)以及 “chargingtimechange” 为参数,运行更新电池状态并通知算法。
[[DischargingTime]] 属性表示系统电池完全放电并导致系统即将挂起的剩余秒数。若电池在充电、实现无法报告剩余放电时间、系统未连接电池或其它情况,则**MUST**设为正无穷。
当电池的放电时间更新时,用户代理必须以新的放电时间(秒)以及 “dischargingtimechange” 为参数,运行更新电池状态并通知算法。
[[Level]] 内部槽位表示系统电池的电量水平。若系统电池电量耗尽且系统将被挂起,则**MUST**设为 0;若电池已满、实现无法报告电量或系统未连接电池,则**MUST**设为 1.0。
当电池电量水平更新时,用户代理必须以新的电量水平以及 “levelchange” 为参数,运行更新电池状态并通知算法。
关于何时触发 “chargingtimechange”、 “dischargingtimechange” 与 “levelchange” 事件的触发频率留给实现自行决定。
charging 的 getter 步骤为返回 this.[[Charging]]。
chargingTime 的 getter 步骤为返回 this.[[ChargingTime]]。
dischargingTime 的 getter 步骤为返回 this.[[DischargingTime]]。
以下是事件处理程序(及对应的事件类型),MUST 作为属性由BatteryManager 对象支持:
| 事件处理器 | 事件处理器事件类型 |
|---|---|
onchargingchange
|
chargingchange
|
onchargingtimechange
|
chargingtimechange
|
ondischargingtimechange
|
dischargingtimechange
|
onlevelchange
|
levelchange
|
要更新电池状态并通知(给定内部槽位 slot、值 value 与事件名 eventName),执行以下步骤:
如果宿主设备包含多个电池,BatteryManager SHOULD 提供统一的电池视图。
内部槽位 [[Charging]] MUST 为 true,只要至少有一个电池的充电状态为 true;否则 MUST 为 false。
内部槽位 [[ChargingTime]] 可设为各电池并行充电时的最大充电时间,或在串行充电时设为各电池充电时间之和。
内部槽位 [[DischargingTime]] 可设为各电池并行放电时的最大放电时间,或在串行放电时设为各电池放电时间之和。
内部槽位 [[Level]] 可设为同等容量电池的平均电量,或在容量不同的电池之间使用加权平均。
Battery Status API 是一个策略控制特性,其标识字符串为 “battery”。其默认允许列表为 'self'。
本节是非规范性的。
以下示例在每次电量变化时把电池电量写入控制台:
// We get the initial value when the promise resolves ...
navigator.getBattery().then(function(battery) {
console.log(battery.level);
// ... and any subsequent updates.
battery.onlevelchange = function() {
console.log(this.level);
};
});
同样的效果也可以使用 addEventListener() 方法实现:
navigator.getBattery().then(function(battery) {
console.log(battery.level);
battery.addEventListener('levelchange', function() {
console.log(this.level);
});
});
下面的示例在指示灯上显示充电状态、电量水平以及剩余时间(单位:分钟):
<!DOCTYPE html>
<html>
<head>
<title>Battery Status API Example</title>
<script>
window.onload = function () {
function updateBatteryStatus(battery) {
document.querySelector('#charging').textContent = battery.charging ? 'charging' : 'not charging';
document.querySelector('#level').textContent = battery.level;
document.querySelector('#dischargingTime').textContent = battery.dischargingTime / 60;
}
navigator.getBattery().then(function(battery) {
// Update the battery status initially when the promise resolves ...
updateBatteryStatus(battery);
// .. and for any subsequent updates.
battery.onchargingchange = function () {
updateBatteryStatus(battery);
};
battery.onlevelchange = function () {
updateBatteryStatus(battery);
};
battery.ondischargingtimechange = function () {
updateBatteryStatus(battery);
};
});
};
</script>
</head>
<body>
<div id="charging">(charging state unknown)</div>
<div id="level">(battery level unknown)</div>
<div id="dischargingTime">(discharging time unknown)</div>
</body>
</html>
BatteryManager 接口 §6.[[BatteryManager]] 作为 Navigator 的内部槽位 §5.1[[BatteryPromise]] 作为 Navigator 的内部槽位 §5.1charging 属性(BatteryManager) §6.2[[Charging]] 作为 BatteryManager 的内部槽位 §6.1chargingTime 属性(BatteryManager) §6.3[[ChargingTime]] 作为 BatteryManager 的内部槽位 §6.1dischargingTime 属性(BatteryManager) §6.4[[DischargingTime]] 作为 BatteryManager 的内部槽位 §6.1getBattery() 方法(Navigator) §5.2level 属性(BatteryManager) §6.5[[Level]] 作为 BatteryManager 的内部槽位 §6.1onchargingchange 属性(BatteryManager) §6.6onchargingtimechange 属性(BatteryManager) §6.6ondischargingtimechange 属性(BatteryManager) §6.6onlevelchange 属性(BatteryManager) §6.6EventTarget 接口
EventHandler
Window 接口
boolean 类型
DOMException 接口
double 类型
[Exposed] 扩展属性
NotAllowedError 异常
Promise 接口
[SecureContext] 扩展属性
unrestricted double 类型
WebIDL[SecureContext]
partial interface Navigator {
Promise<BatteryManager> getBattery();
};
[SecureContext, Exposed=Window]
interface BatteryManager : EventTarget {
readonly attribute boolean charging;
readonly attribute unrestricted double chargingTime;
readonly attribute unrestricted double dischargingTime;
readonly attribute double level;
attribute EventHandler onchargingchange;
attribute EventHandler onchargingtimechange;
attribute EventHandler ondischargingtimechange;
attribute EventHandler onlevelchange;
};工作组深深感谢 Mounir Lamouri、Jonas Sicking 以及整个 Mozilla WebAPI 团队对原型实现提供的宝贵反馈。也感谢 System Information API 与 Device Orientation Event 规范的作者提供的初始灵感。以及为我们带来 Page Visibility 规范的同事们,使本规范的引言章节能够讨论同样适用于本规范的真实高价值使用案例。特别感谢 Device APIs Working Group 的所有参与者以及其他提供了大量反馈和评论的朋友们,让 Web 变得更加美好。最后,感谢 Lukasz Olejnik、Gunes Acar、Claude Castelluccia 与 Claudia Diaz 对 API 的隐私分析。
引用自
引用自
引用自