The functionality described in this specification was initially specified as part of the System Information API but has been extracted in order to be more readily available, more straightforward to implement, and in order to produce a specification that could be implemented on its own merits without interference with other, often unrelated, features.
The Battery Status API specification defines a means for web developers to programmatically determine the battery status of the hosting device. Without knowing the battery status of a device, a web developer must design the web application with an assumption of sufficient battery level for the task at hand. This means the battery of a device may exhaust faster than desired because web developers are unable to make decisions based on the battery status. Given knowledge of the battery status, web developers are able to craft web content and applications which are power-efficient, thereby leading to improved user experience.
The Battery Status API can be used to defer or scale back work when the device is not charging in or is low on battery. An archetype of an advanced web application, a web-based email client, may check the server for new email every few seconds if the device is charging, but do so less frequently if the device is not charging or is low on battery. Another example is a web-based word processor which could monitor the battery level and save changes before the battery runs out to prevent data loss.
The following example shows how a web-based email client could check for new emails every ten seconds without knowledge of the battery status:
<!DOCTYPE html> <html> <head> <title>Email Client</title> <script> var mail = { INTERVAL_DEFAULT: 1000 * 10, interval: null, timer: 0, check: function () { console.log('Checking the server for new emails using an interval of ' + (mail.interval / 1000) + ' seconds.'); }, setTimer: function (interval) { if (interval === mail.interval) { return; } if (mail.timer !== 0) { clearTimeout(mail.timer); } if (interval) { mail.timer = setInterval(function () { mail.check(); }, interval); } mail.interval = interval; } }; window.addEventListener('load', function () { mail.setTimer(!mail.interval ? mail.INTERVAL_DEFAULT : mail.interval); }, false); </script> </head> <body></body> </html>
The script will always check for emails every ten seconds, even if the battery level is critically low and the device is not charging. This is an example of poor resource management.
Using the BatteryManager interface, the web application is, for example, able to throttle checking for emails if the device is low on battery, stop checking for emails if the battery is critically low and resume normal operation when the battery is charging:
<!DOCTYPE html> <html> <head> <title>Battery-aware Email Client</title> <script> var mail = { INTERVAL_BATTERY_LOW: 1000 * 60 * 10, INTERVAL_DEFAULT: 1000 * 10, interval: null, timer: 0, check: function () { console.log('Checking the server for new emails using an interval of ' + (mail.interval / 1000) + ' seconds.'); }, setTimer: function (interval) { if (interval === mail.interval) { return; } if (mail.timer !== 0) { clearTimeout(mail.timer); } if (interval) { mail.timer = setInterval(function () { mail.check(); }, interval); } mail.interval = interval; } }; window.addEventListener('load', function () { mail.setTimer(!mail.interval ? mail.INTERVAL_DEFAULT : mail.interval); }, false); var battery = navigator.battery; battery.addEventListener('dischargingtimechange', function () { if (battery.dischargingTime < 60 * 30 || battery.level < 0.1) { mail.setTimer(mail.INTERVAL_BATTERY_LOW); console.log('30 minutes remaining or level below 10%, checking the server less frequently.'); } else if (battery.dischargingTime < 60 * 10 || battery.level < 0.05) { mail.setTimer(null); console.log('10 minutes remaining or level below 5%, stop checking the server.'); } }, false); battery.addEventListener('chargingchange', function () { if (battery.charging) { mail.setTimer(mail.INTERVAL_DEFAULT); console.log('Battery is charging, checking the server normally.'); } }, false); </script> </head> <body></body> </html>
This specification defines conformance criteria that apply to a single product: the user agent that implements the interfaces that it contains.
Implementations that use ECMAScript to implement the APIs defined in this specification must implement them in a manner consistent with the ECMAScript Bindings defined in the Web IDL specification [[!WEBIDL]], as this specification uses that specification and terminology.
The
EventHandler
interface represents a callback used for event
handlers as defined in [[!HTML5]].
The concepts queue a task and fires a simple event are defined in [[!HTML5]].
The terms event handlers and event handler event types are defined in [[!HTML5]].
The API defined in this specification is used to determine the battery status of the hosting device. The information disclosed has minimal impact on privacy or fingerprinting, and therefore is exposed without permission grants. For example, authors cannot directly know if there is a battery or not in the hosting device.
The NavigatorBattery interface is exposed on the
Navigator
object.
When a BatteryManager
object is created,
charging
MUST be set to true, chargingTime
to 0, level
to 1.0 and dischargingTime
to
the value positive Infinity, if the implementation is unable to report
the battery's charging state, charging time, level or remaining time
respectively.
The charging
attribute MUST be set to false if the battery
is discharging, and set to true, if the battery is charging, the
implementation is unable to report the state, or there is no battery
attached to the system, or otherwise. When the battery charging state
is updated, the user agent MUST queue a task which sets
the charging
attribute's value and fires a simple
event named chargingchange
at the
BatteryManager object.
The chargingTime
attribute MUST be set to 0, if the
battery is full or there is no battery attached to the system, and to
the value positive Infinity if the battery is discharging, the
implementation is unable to report the remaining charging time, or
otherwise. When the battery charging time is updated, the user
agent MUST queue a task which sets the
chargingTime
attribute's value and fires a simple
event named chargingtimechange
at the
BatteryManager object.
The dischargingTime
attribute MUST be set to the value
positive Infinity, if the battery is charging, the implementation is
unable to report the remaining discharging time, there is no battery
attached to the system, or otherwise. When the battery discharging time
is updated, the user agent MUST queue a task which sets
the dischargingTime
attribute's value and fires a
simple event named dischargingtimechange
at the
BatteryManager object.
The level
attribute MUST be set to 0 if the system's
battery is depleted and the system is about to be suspended, and to
1.0 if the battery is full, the implementation is unable to report the
battery's level, or there is no battery attached to the system. When
the battery level is updated, the user agent MUST queue a
task which sets the level
attribute's value and
fires a simple event named levelchange
at
the BatteryManager object.
chargingtimechange
,
dischargingtimechange
, and levelchange
events are fired is left to the implementation.
The following are the event handlers (and their corresponding event handler event types) that MUST be supported as attributes by the BatteryManager object:
event handler | event handler event type |
---|---|
onchargingchange |
chargingchange |
onchargingtimechange |
chargingtimechange |
ondischargingtimechange |
dischargingtimechange |
onlevelchange |
levelchange |
This trivial example writes the battery level to the console each time the level changes:
navigator.battery.onlevelchange = function () { console.log(navigator.battery.level); };
Alternatively, the same using the addEventListener()
method:
navigator.battery.addEventListener('levelchange', function () { console.log(navigator.battery.level); }, false);
The following example updates the indicators to show the charging state, level and time remaining in minutes:
<!DOCTYPE html> <html> <head> <title>Battery Status API Example</title> <script> var battery = navigator.battery; battery.onchargingchange = function () { document.querySelector('#charging').textContent = battery.charging ? 'charging' : 'not charging'; }; battery.onlevelchange = function () { document.querySelector('#level').textContent = battery.level; }; battery.ondischargingtimechange = function () { document.querySelector('#dischargingTime').textContent = battery.dischargingTime / 60; }; </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>
The group is deeply indebted to Mounir Lamouri, Jonas Sicking, and the Mozilla WebAPI team in general for their invaluable feedback based on prototype implementations. Many thanks to the people behind the System Information API and Device Orientation Event specification for the initial inspiration. Also thanks to the nice folks bringing us the Page Visibility specification, which motivated the editor of this specification to write the introduction chapter discussing some real-world high value use cases that apply equally to this specification. Special thanks to all the participants of the Device APIs Working Group and others who have sent in substantial feedback and comments, and made the Web a better place for everyone by doing so.