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.
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.
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.
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 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 +
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.
Click here to view this example live. The example works best on devices and browsers that support for the API.
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:
Creating a new PHP class that will handle the interactions with the CatAPI.
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.)
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.
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.
Battery API Class
Our main interaction with the CatAPI will be via the
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 check the error status and error code numbers with
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.
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-position CSS properties to give us perfectly square, fully responsive image elements.
This function displays the introductory text for users, telling them about this web page and how it works. Fairly standard.
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 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
We then call the
get_image_items() function, passing in our
$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.
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.
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.
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:
|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.
navigator.batteryvalue exists in older browsers and will directly return the
batteryMangerobject if we have it. If we have support, we set the
trueand start executing our functions.
navigator.getBatteryfunction exists only in newer browsers, and instead of directly giving you the
batteryManagerobject, it executes a
promiseto give you the object as soon as it can. Once we get back this promised value, we set the
trueand 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
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
batteryvariable 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
batteryvariable. if we do it uses the
levelproperty of the battery manager object to set our
battery_levelvariable. (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
statestring the device will be set to. This state is saved in our
battery_statusvariable, 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_levelto determine if the device will be in a
criticalstate. If we don't have access to the API we set this to
get_battery_charging(): if we support the API, we look at the
chargingproperty. This property lets us know if the device is charging or not. We set the value of
set_background_colour(): checks the current status in the
battery_statusvariable and sets a class to the
HTMLelement. 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_supportvariable, and if we have support, we then compare our
battery_statusvariable against our ranges. Depending on the battery status, we'll set our
api_action_interval_timevariable either to
false. If we have no support for the API, we set it to a default value of
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_timevariable to 100 (meaning it will update 10 times a second).
Displaying Battery Information Visually
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_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).
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.
levelchangeEvent: 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
chargingchangeEvent: 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
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
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:
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.