Using the Battery Status API to Optimize Your Development

We teamed up with SiteGround
To bring you up to 65% off web hosting, plus free access to the entire SitePoint Premium library (worth $99). Get SiteGround + SitePoint Premium Now

battery icon

Imagine if you could program your app to adapt to the end user's device — such as turning off certain processes if the user's device has a low battery status. Well, you can.

The Device APIs Working Group is a series of specifications drafted to provide developers with access to additional information about a user's device, so that a more tailored experience can be created. This working group contains several evolving standards, including the Battery API which we will take a look at in this tutorial.

The Battery API is now supported on several desktop and mobile browsers, so now is a good time to look at the Battery API and see what it is, where it's supported, and why you should consider leveraging it in your upcoming projects.

The Battery API: A Brief Introduction

The Battery Status API (Battery API) is exactly what it sounds like: an interface that lets developers access information about the current user's battery.

It's a JavaScript-level API that enables developers to hook into various events and properties of the user's device. For example, if we have access to the API, we can get the current battery percentage and, based on that value, set good default settings. For example, if the user's device is in a low battery state, we can remove all background tasks and make them manual only.

Since early 2011, this API has been continually under development, moving back and forth from working draft to candidate recommendation status at the W3C. Over this period, several browsers have adopted support — though some more than others.

How Can the API Help Us?

Since the specification is not yet finalized, we can't count on developing websites or web apps that fully depend on the Battery API. What we can do, however, is provide additional functionality, or a more customized experience, if the current browser supports the API — i.e., using it in a progressive enhancement style.

What Information Can We Access?

Since we can access the user's battery state, we can determine their current battery level and whether the device is charging or discharging. In addition, we can sometimes get the device's approximate charge or discharge time (the time until the device is either charged or dead).

With this information, we can start to change the user experience to help the user.

What Could We Use This Information for Anyway?

Even though battery optimization generally isn't in the forefront of a developer's mind, it's a factor that should be considered, especially with everything moving towards mobiles.

Websites offer a range of useful but expensive operations that could be adjusted so that your users spend less of their battery on your website. (No one likes a website or web app that demolishes your battery.)

Let's look at some of the ways we could save some battery power:

  • We could customize the Geolocation elements so that they have a lower accuracy and don't request usage of the inbuilt GPS by default. We could have two options displayed to the user, one to request it normally and another with high accuracy.
  • We could set video streams or playback to lower quality levels by default, making data transfers are quicker (and thus requiring less work of the device). An option to download the high quality stream could be provided.
  • We could reduce complex CSS animations or interface elements and provide a more basic interface.
  • We could use the battery level to determine the default interval in which background tasks are run — such as Ajax and Web Workers. We could use the state to determine how frequently our tasks should be called, in order to minimize network usage. Providing an option or setting so users could set what they want is also a good idea.

Overall, the idea is that we can use the Battery API to provide some good defaults that save battery power, while providing more options for interacting with the website.

Browser Support

Since the Battery API is not finalized, it doesn't have universal support across all browsers yet.

On a positive note, a good number of browsers now support it (as of November 2015), so now's the perfect time to get up and running with this API.

Mobile Devices

Mobile browser support for battery status API

Mobile browsers are where support is most important. FireFox mobile has had the longest support, ranging back to early days of version 18 (January 2013). Opera followed suit in version 25 (October 2014) and finally Chrome in version 40 (April 2015).

  • Firefox 18+
  • Opera Mobile 25+
  • Chrome 42 +

Desktops

Desktop browser support for battery status API

While the Battery API makes the most sense for mobile devices (and their browsers), it's still important to have support for the API across the traditional browsers, as they're often used on laptops and other portable devices (where the API is useful).

Firefox, again, has the longest history of support, back to version 18 (launched in 2012). Chrome added support in version 39 (October 2014), closely followed by Opera with its 25th version (October 2014)

  • Firefox 18+
  • Chrome 39+
  • Opera 25+

A Practical Example: Reducing Background API Calls

You can go directly to the full code for this demo if you'd rather skip this section.

One good way of using the API is by detecting the user's current battery state and setting the default intervals for data- and processor-intensive tasks.

Websites will often request new information dynamically, using Ajax or other techniques to pull or push data while users go about their normal website interactions.

These events are often started by users, such as when they want to load additional content. Other times, they happen in the background without any user input.

By looking at the battery state, we can choose the best default experience for the user.

Example overview of the CatAPI and battery API. Showcases what the end user will see

Click here to view this example live. The example works best on devices and browsers that support for the API.

Example Overview

The website will display random images from The Cat API and show them to our users. Once the user loads the page, it will continually pull images from the API and replace our existing images.

Here's what we'll be doing:

  1. Creating a new PHP class that will handle the interactions with the CatAPI.

  2. Extending a new class that will be used to get a single image from the CatAPI and return it back to our browser for processing. (This process will be executed via Ajax.)

  3. Building our basic landing page. The page will initially get a few images from the CatAPI and display useful information about the battery state and battery API.

  4. Creating the JavaScript interactivity with the battery status API. It's here that the majority of the fun stuff will be happening — as we check for API support and how we can interact with it.

If you're new to cURL, it's probably best to read up on it first.

If you want to get straight to the code, feel free to fork a copy from the SitePoint GitHub account.

The CatAPI: a Quick Overview

The Cat API lets us pull random images of cats, which will work perfectly as all we need is a basic random image passed back to us every X seconds depending on the current battery state.

We'll be using the get method of the API to collect our images. This method outlines several options that you can use to modify your request. However, for our needs, we'll keep it pretty simple:

/api/images/get

CatAPI parameters

Note: Normally, you wouldn't need to use PHP to connect with your API; you'd just build your URL and connect to the API with JavaScript. However, the CatAPI currently doesn't support JSON, so we may as well just use cURL on the server to get our information.

Battery API Class

Our main interaction with the CatAPI will be via the battery_api_class.php file.

Inside the class we define several methods, which we'll use to interact with the CatAPI and display useful information about the Battery Status API. Let's quickly run through what these do.

get_image_items($method, $arguments = array())

This function initializes a cURL session with the CatAPI.

It takes in the method used for the API along with an array of arguments.

For our example, the method will be /api/images/get?, and our array will have our options (such as choosing the size of the image returned, the return format, the type of image etc.).

We now start our cURL request with curl_init(), and grab its content with curl_exec. We close the connection with curl_close once we're done.

We check the error status and error code numbers with curl_error and curl_errno. If we have no error messages, and we have content, we start processing the returned information. For our examples, we'll be getting our data back in XML, so we create a new SimpleXMLElement from our cURL content and then loop through each of the records.

Once we have the information we need, we return the images, or false, depending on how our cURL request goes.

display_image_items($images_array)

This function displays all the saved information we collected in the get_image_items() function. If we have images, we display a manual load button to fetch images. (This will be displayed when we're on critical battery and run no background tasks.)

We loop through the records and print the markup for each image. We're using several inner containers, as we're taking advantage of the object-fit and object-position CSS properties to give us perfectly square, fully responsive image elements.

display_battery_example_description()

This function displays the introductory text for users, telling them about this web page and how it works. Fairly standard.

display_battery_information_summary()

This function displays all the summary information about the device's support for the Battery API. It indicates if the device supports the API, the current charge percentage, if the device is charging, and, most importantly, the current interval in which the next call to the CatAPI will be made.

In addition, we also define the simulation buttons that can be used to trigger the other battery states (so you can simulate having a low battery state).

The Battery API Child Class

The battery_api_single.php class will be called periodically by our JavaScript, based on the current battery level of the device. A higher battery level will result in more frequent calls to this file.

The purpose of this class is to extend the parent battery_api class and use its constructor to fetch an image from the CatAPI. We start by loading our parent class and extending a new class based off it.

We start by defining an array of our options inside the $arguments variable. We set the data type to be XML and to pull a single small JPG from the CatAPI. We define the $method to be the get method of /api/images/get?

We then call the get_image_items() function, passing in our $method and $arguments. We'll be returned an array of image information. We then use the json_encode function to pass an encoded string of information back to our website.

Website Landing Page

index.php is the landing page we'll get to when we visit our example. The file itself is basic and acts as a wrapper for our different functions, so that we can display our example descriptions, information summary and grid of initial images from the CatAPI.

We load the battery_api_class.php file and then call the CatAPI to get our initial series of eight images to display on page load.

JavaScript Interactivity with the Battery Status API

Arguably the most important part of the example is the interactivity with the Battery Status API and the various other functions that help piece everything together.

The battery_api_scripts.js file contains several interconnected functions that provide connectivity with the Battery Status API and set up/update the various areas in our example.

Global Variables

At the very top of the file, we create all the variables we'll need. These variables will end up containing strings, booleans, objects etc. Here's a quick breakdown:

Variable Description
battery The battery object itself (either batteryManager object or false)
battery_support if we supports the battery API (true or false)
battery_level current battery level (out of 100)
battery_is_charging Is the device currently charging (true or false)
battery_status status of battery (use this state to determine other actions)
api_action_interval_item the variable which holds the setInterval function used to call the CatAPI
api_action_counter_item the variable used to count the time remaining till the next call to the CatAPI
api_action_interval_time The time that the system currently executes the call to the CatAPI (Either 3000ms, 5000ms, 8000ms or false)
api_action_counter_time The time that we will update the counter (displaying in X seconds we will call the CatAPI)

We use these extensively throughout the example, and most are used to trigger other actions.

Detecting Support for the Battery API

We execute the battery_start() function as soon as the page is ready. Its purpose is to test for Battery API support. Since the API is changing, we need to check two different ways to see if we have support.

  • The older navigator.battery value exists in older browsers and will directly return the batteryManger object if we have it. If we have support, we set the battery variable to true and start executing our functions.

  • The newer navigator.getBattery function exists only in newer browsers, and instead of directly giving you the batteryManager object, it executes a promise to give you the object as soon as it can. Once we get back this promised value, we set the battery variable to true and start executing our functions.

If there's no support, we set the battery variable to false and continue with our setup actions.

Setting/Updating the Battery Status Information

The update_status_information() function is called next in our flow. It calls a whole heap of other helper functions that will set our variables based on the support of the API.

Since there are many elements to track, we occasionally call this function to update values — such as when we move up a percentage in charging, or when we toggle our simulated battery states.

  • get_battery_support(): checks our battery variable to see if we have a Battery Manager object (we will if we have support for the API). If we have support we set this to true, else we set it to false.
  • get_battery_level(): checks to to see if we have our battery variable. if we do it uses the level property of the battery manager object to set our battery_level variable. (The level value represents a value between 0 and 1, so we multiply the value by 100 to get our percentage.)
  • get_battery_status(): this determines what state string the device will be set to. This state is saved in our battery_status variable, and is used in other areas of the website (such as our main Ajax function). If we have access to the API, we check against the current battery_level to determine if the device will be in a high, medium, low or critical state. If we don't have access to the API we set this to no_support.
  • get_battery_charging(): if we support the API, we look at the charging property. This property lets us know if the device is charging or not. We set the value of battery_is_charging accordingly.
  • set_background_colour(): checks the current status in thebattery_status variable and sets a class to the HTML element. This is mainly used for presentation, and each state sets a different color on the background.
  • get_api_action_interval(): this function is where we determine how often we'll be calling our Ajax function to pull a new image from the CatAPI. We check the battery_support variable, and if we have support, we then compare our battery_status variable against our ranges. Depending on the battery status, we'll set our api_action_interval_time variable either to 3000,5000,8000 or false. If we have no support for the API, we set it to a default value of 3000.
  • get_api_counter_interval(): this is a helper function used to determine, in milliseconds, how quickly we will update our visual counter (the element that says we have X seconds until our next Ajax call). We set the api_action_counter_time variable to 100 (meaning it will update 10 times a second).

Displaying Battery Information Visually

The display_status_information() function is what we call when we need to display or update the battery information to the user. We collect our variables — such as the battery_level, battery_support and so on — and then update our information. This function is often called when various battery events happen (such as when our battery level changes).

Battery status crucial information

If we have support for the Battery API, we also display our buttons to simulate the battery state (so you can see the update interval change to different values).

Handling Battery API Events

If we have support for the Battery API, we also want to hook onto the various battery events so that we can react when things change. The battery_event_handlers() function is called and looks for two specific events.

  • The levelchange Event: this is called whenever our device increases or decreases in charge. When we change this state, we call the update_status_information() function again, as the level may change the state the device is now in (which will affect how often our Ajax is called etc). Afterwards, we update the front end with display_status_information().
  • The chargingchange Event: this is called when the device either stops or starts charging. We call the get_battery_charging() function to get the new state, and then update the front end with display_status_information().

Creating the Main Loop Function

The last step in this sequence is to call the start_ajax_api_task() function. Inside here, we check for the battery_status and see if it's critical. If it is, we won't be having any Ajax calls (it's a manual update only).

If we're not in a critical state, we then create two loops. The first loop will be assigned to the api_action_interval_item variable, and it will be used to call the replace_grid_image() function every X seconds (where the time is determined based on your battery state). The second loop is used to act as a counter, so visually you can see when the next update will be happening.

Calling the CatAPI to Replace an Image

The replace_grid_image() function is called every X seconds so that we can pull a new image from the CatAPI.

We use jQuery's $.ajax function to send a request to our PHP file and return a single image from the CatAPI. This is then added into our gallery. We use a few neat functions so that a random image will be replaced and that it will fade in nicely (this is all for presentation).

Here's a GIF representation of the API in action:

the API in action, dynamic images

You could modify the example so that you do something else. However, the main point is that you're now executing this function conditionally on the battery state.

Wrapping It All Up

Now that you've seen how you can use the additional information from the Battery Status API, you can customize each user's experience to match their device's available power.

You could do subtle things such as setting conservative default settings on low battery, or you may opt to change a user's experience entirely.

Once again, you can check out the GitHub repository to see all the code used in this demo.

And you can also view a working demo to see it in action. (Try it out on various devices, at various battery levels, to compare results!)

Let us know in the comments if you've used the Battery API, or if you plan to use it to build something exciting! I'd love to know what you think of it.

We teamed up with SiteGround
To bring you up to 65% off web hosting, plus free access to the entire SitePoint Premium library (worth $99). Get SiteGround + SitePoint Premium Now