How to Use the HTML5 Battery Status API

Craig Buckler
Share

If you’re lucky, you’ll get seven or eight hours usage from a smart phone or tablet before the battery dies. Expect around half that on a laptop. Battery technology has not kept pace with advances in mobile computing. A decade ago you could expect your Palm Pilot to last up to a month on a couple of AAA batteries. Now you’re feeding devices every night and your room lights up like a blinking red and green LED version of Las Vegas.

Few of us worry about battery life when developing web applications, but perhaps we should be more considerate now that mobile access has reached one in five users. Fortunately, the W3C Battery Status API has been implemented by both Mozilla and Google — and it’s very simple to use.

What’s Not So Simple…

We can detect when a battery reaches a critical level but what can we do about it? It will depend on your application, but the primary causes of power drainage are…

The screen
Your back-lit screen is the biggest juice glutton. There are a few options you could consider when the battery reaches a critical level:

  • switch to a light-on-dark theme
  • disable non-critical CSS3 and JavaScript animations
  • avoid DOM changes where possible

Network activity
Wi-fi and mobile networks require power-draining radio wave communications. Consider:

Audible and tactile output
Sound and vibration will kill a battery dead; you could use shorter effects or disable it completely.

Processing
Heavy-duty processing has a noticeable impact on battery life and handset heat! Other than fast-action games, few web applications should require complex on-going client-side calculations. I suspect there’s little you can practically do other than suggesting the user plugs-in to continue.

You should also note that many of these options may be applicable to the Page Visibility API. For example, if a game isn’t running in the active tab, it can be paused until the user returns.

Browser Support

At the time of writing, only Firefox desktop and mobile editions offer unprefixed support for the Battery API (versions 10 to 16 used the moz prefix). It is also available in recent editions of Chromium with a webkit prefix.

We can create a cross-browser battery object using:

var battery = navigator.battery || navigator.webkitBattery || navigator.mozBattery || navigator.msBattery;

if (battery) {
	// battery API supported
}

This is used in the Battery API demonstration…

Basic Properties

You can obtain the battery level using the navigator.battery.level property which returns a value between 0 and 1, e.g.

console.log( "battery level: ", Math.floor(battery.level * 100) + "%" );

However, the current level may not be so important if the device is being charged. We can check the status using the navigator.battery.charging property which returns true if charging or false if discharging:

console.log( "device is ", (battery.charging ? "charging" : "discharging") );

Therefore, you probably want to introduce power-boosting options when the battery level drops below, say, 25% and the device is not being charged, e.g.

var enableEffects = (battery.charging || battery.level > 0.25);

// vibrate for one second
if (enableEffects) navigator.vibrate(1000);

There are a couple of other properties you may find useful:

  • navigator.battery.chargingTime — the time, in seconds, until charging reaches 100%.
  • navigator.battery.dischargingTime — the time, in seconds, until the battery is completely discharged and the device will shut down.

Neither of these properties appear to work as you’d expect in current browsers. Firefox returns either zero or Infinity which isn’t particularly helpful.

Battery Status Events

Four events can be fired by the Battery object:

  • chargingchange — the device has changed from being charged to being discharged or vice versa
  • levelchange — the battery level has changed
  • chargingtimechange — the time until the battery is fully charged has changed
  • dischargingtimechange — the time until the battery is fully discharged has changed

For example, using our cross-browser battery object:

battery.onlevelchange = function() {

	var ee = enableEffects;
	enableEffects = (battery.charging || battery.level > 0.25);
	
	if (enableEffects != ee) {
		if (enableEffects) {
			console.log( "Battery power is OK." );
		}
		else {
			console.log( "Battery power is critical!" );
		}
	}

}

Some would say your web app should never needlessly drain the battery. However, the Battery API allows us to make more sophisticated decisions about when we can and cannot depend on animation, effects and Ajax calls.

View the Battery API demonstration… (Firefox and Chromium)