Advertisement

HTML5: Battery Status API

by
Student iconAre you a student? Get a yearly Tuts+ subscription for $45 →

The number of people browsing the web using mobile devices grows every day. It's therefore important to optimize websites and web applications to accommodate mobile visitors. The W3C (World Wide Web Consortium) is well aware of this trend and has introduced a number of APIs that help with this challenge. In this article, I will introduce you to one of these APIs, the Battery Status API.

Introduction

One of the most irritating limitations of the current generation of mobile devices is their limited battery life. It drives me crazy when the battery of my mobile phone dies when I'm out and about. No matter how small and convenient modern smartphones are, you need to remember to carry an adapter with you in case your phone or tablet runs out of juice.

As developers, we can help remedy this issue, but we usually prefer to ignore it. Until recently, developers had a good excuse as there wasn't an API to get information about the device's battery status. That excuse, however, is no longer valid thanks to the introduction of the Battery Status API. Let's take a few minutes to explore what the Battery Status API is all about.

1. What is it?

The Battery Status API, sometimes referred to as the Battery API, is an API that provides information about the system's battery level. It also defines events that are fired when changes of the battery level or status take place. Even though the Battery Status API is a W3C Candidate Recommendation, the specification hasn't changed since May 2012 so it is likely that the current API won't change much in the future.

There are several actions developers can take thanks to the availability of the Battery Status API. For example, a web application could temporarily pause a long-running process when it detects the battery level is low or critical. It's up to the developer to decide what is best for the user given the circumstances and battery level.

This may seem disruptive to the user, but by acting proactively it is possible to prevent, for example, the loss of data. If you're developing an application that manages content, then it may be useful to save the user's data more frequently when the battery is running low on power. Your users will thank you for it. It happens all too often that people lose data due to a dead battery.

Even though this may seem a bit far-fetched, but it's even possible to switch to a light-on-dark theme when the battery is running low on power. This causes the screen to draw less power from the battery and it may result in a few extra minutes of battery power.

I hope it's clear that we can take a number of precautions simply by being notified of the battery level of the device. It's time to take a look at the Battery Status API to see how all this works in practice.

2. Properties

The Battery Status API exposes four, read-only properties on the window.navigator.battery object.

  • charging: A boolean value that specifies whether the battery is charging or not. If the device doesn't have a battery or the value cannot be determined, the value of this property is set to true.
  • chargingTime: A number that specifies the number of seconds that remain until the battery is fully charged. If the battery is already fully charged or the device doesn't have a battery, then this property is set to 0. If the device isn't charging or it's unable to determine the remaining time, the value is Infinity.
  • dischargingTime: A number value that represents the number of seconds that remain until the battery is completely discharged. If the discharge time cannot be determined or the battery is currently charging, then the value is set to Infinity. If the device doesn't have a battery, then dischargingTime is also set to Infinity.
  • level: A number that specifies the current level of the battery. The value is returned as a float ranging from 0 (discharged) to 1 (fully charged). If the level of the battery cannot be determined, the battery is fully charged, or the device doesn't have a battery, then the value of level is equal to 1.

One element that surprised me when I was browsing the specification is that the chargingTime property holds the number of seconds until the battery is fully charged and not the number of seconds until the battery is fully discharged. Keep this in mind when working with the Battery Status API.

3. Events

The Battery Status API allows us to listen for four events, each of which can be mapped to the change of a property on window.navigator.battery.

  • chargingchange is fired when the device's charger is activated or deactivated.
  • chargingtimechange is fired when the remaining charging time changes.
  • dischargingtimechange is fired when the remaining time until the battery is fully discharged changes.
  • levelchange is fired when the battery level has changed.

It's important to note that you need to attach an event listener to window.navigator.battery if you wish to listen for the aforementioned events. Let's take a look at an example.

navigator.battery.addEventListener('levelchange', function(event) {
   // Do something...
});

The available events of the Battery Status API give developers a lot of flexibility to alter the behavior of websites and web applications. What about support? That's a good question.

4. Detecting Support

Detecting support for the Battery Status API is easy. However, as I'll discuss in the next section on browser compatibility, it's important to detect support of the API due to the low number of browsers that currently support the Battery Status API. Take a look at the following code snippet to see how easy it is to test whether the Battery Status API is supported.

if (window.navigator && window.navigator.battery) {
   // Grab the battery's information!
} else {
   // Not supported
}

5. Browser Compatibility

Support for the Battery Status API support is pretty poor at this point. At the moment, Firefox is the only browser that provides support for the API without the use of a vendor prefix. This is interesting since the API has several use cases that could really help in a world where mobile devices are becoming more and more dominant as devices to browse the web. A polyfill for the Battery Status API doesn't exist yet for obvious reasons. A JavaScript library, no matter how powerful, cannot access information of a hardware component without the browser's permission.

6. Demo

In this section, I'd like to show you a simple demonstration of how the Battery Status API can be used and to show some of its key features. In the demo, I've included a <div> tag with an id of bt-results in which we'll show the data retrieved from the device's battery. This element is hidden by default and only shown if the browser supports the Battery Status API, which is only Firefox at the time of writing. The demo also includes a <div> tag with an id of log in which we'll log the events fired by the Battery Status API.

With regards to the JavaScript code, the first line tests if the browser supports the Battery Status API. If the test fails, the message "API not supported" is shown. Otherwise, we attach a handler to all the events of the Battery Status API using a for loop. The handler injects the values of the properties of the battery object in the appropriate placeholder elements. You can also view a live demo.

<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
      <meta name="author" content="Aurelio De Rosa">
      <title>Battery Status API Demo by Aurelio De Rosa</title>
      <style>
         *
         {
            -webkit-box-sizing: border-box;
            -moz-box-sizing: border-box;
            box-sizing: border-box;
         }

         body
         {
            max-width: 500px;
            margin: 2em auto;
            padding: 0 0.5em;
            font-size: 20px;
         }

         h1
         {
            text-align: center;
         }

         .hidden
         {
            display: none;
         }

         .bs-info
         {
            font-weight: bold;
         }

         #log
         {
            height: 200px;
            width: 100%;
            overflow-y: scroll;
            border: 1px solid #333333;
            line-height: 1.3em;
         }

         .button-demo
         {
            padding: 0.5em;
            margin: 1em;
         }

         .author
         {
            display: block;
            margin-top: 1em;
         }
      </style>
   </head>
   <body>
      <h1>Battery Status API</h1>
      <span id="bs-unsupported" class="hidden">API not supported</span>

      <div id="bt-results" class="hidden">
         <h3>Current Status</h3>
         <div id="bs-status">
            <ul>
               <li>Is battery in charge? <span id="in-charge" class="bs-info">unavailable</span></li>
               <li>Battery will be charged in <span id="charging-time" class="bs-info">unavailable</span> seconds</li>
               <li>Battery will be discharged in <span id="discharging-time" class="bs-info">unavailable</span> seconds</li>
               <li>Current battery level: <span id="battery-level" class="bs-info">unavailable</span>/1</li>
            </ul>
         </div>
      </div>

      <h3>Log</h3>
      <div id="log"></div>
      <button id="clear-log" class="button-demo">Clear log</button>

      <small class="author">
         Demo created by <a href="http://www.audero.it">Aurelio De Rosa</a>
         (<a href="https://twitter.com/AurelioDeRosa">@AurelioDeRosa</a>)
      </small>

      <script>
         window.navigator = window.navigator || {};
         navigator.battery = navigator.battery ||
                             null;
         if (navigator.battery === null) {
            document.getElementById('bs-unsupported').classList.remove('hidden');
         } else {
            var log = document.getElementById('log');

            document.getElementById('bt-results').classList.remove('hidden');
            function updateInfo(event) {
               if (event !== undefined) {
                  log.innerHTML = 'Event "' + event.type + '" fired<br />' + log.innerHTML;
               }
               document.getElementById('in-charge').innerHTML = (navigator.battery.charging ? "Yes" : "No");
               document.getElementById('charging-time').innerHTML = navigator.battery.chargingTime;
               document.getElementById('discharging-time').innerHTML = navigator.battery.dischargingTime;
               document.getElementById('battery-level').innerHTML = navigator.battery.level;
            }

            var events = ['chargingchange', 'chargingtimechange', 'dischargingtimechange', 'levelchange'];
            for (var i = 0; i < events.length; i++) {
               navigator.battery.addEventListener(events[i], updateInfo);
            }
            updateInfo();

            document.getElementById('clear-log').addEventListener('click', function() {
               log.innerHTML = '';
            });
         }
      </script>
   </body>
</html>

Conclusion

In this article, we discussed the Battery Status API. As we've seen, it's pretty simple and offers developers the opportunity to improve the user experience of website and web applications. The Battery Status API exposes four properties and four events that we can use to change the behavior of websites and web applications by appropriately responding to changes of the device's battery status. Unfortunately, the only browser that supports the API is Firefox. However, we can expect a broader adoption in the near future. This means you can still prepare for broader support and adopt it in your next project.

Advertisement