Tag Archives: mobile

Responsive is not just visual: Three useful web APIs

A mobile user using a laptop outside.Mobile users are on the go. They’re rushing to get a train or busy meeting people. They don’t have much time and they’re on a slow connection. Right?

The answer of course is not necessarily. So-called mobile browsing could include shopping online while tucked up in bed, sending messages while watching TV or giggling at silly photos while relaxing in a cafe. It could also include being out and about but not using a mobile device.

In reality we have no idea what the users of our website are doing or where they are, and it would be a huge invasion of privacy if we did! Our fancy responsive designs should therefore not only look good but also be flexible enough to handle a variety of situations.

In other words, responsive doesn’t mean responding to screen size or even device capabilities. It means responding to the user’s environment (as much as possible).

But enough chatter. How can we do this in practice?

There are three handy web technologies that take us part of the way there: the Battery Status API, the Network Information API and Ambient Light Events. Support for all of them is mostly Chrome and Firefox for now, but keep an eye on caniuse.com and mobilehtml5.org for the latest support info. And now, on to the APIs…


Battery Status API

Why use it

Knowing whether your user is plugged in or not and whether their battery has much juice left can influence how your site reacts. Battery-draining features such as repeated actions and animations can be reduced or disabled, for example. Or you could notify the user and offer to save the current state in case there’s a sudden shutdown.

How to use it

The spec had a rewrite recently and now uses shiny new promises. The advantage of this is that the API is asynchronous, meaning that when you call the getBattery() method the browser makes sure the BatteryManager object is ready before you try to read its attributes. Those attributes are:

  • charging (a boolean)
  • chargingTime (in minutes)
  • dischargingTime (in minutes)
  • level (a number between 0 and 1)

Each of these attributes has an event so you can listen for when they change. In practice, you could use the attributes and events like this:

// Prepare a function to display the battery status
function showStatus(battery) {
  battery.onchargingchange = function () {
    console.log('Charging: ' + battery.charging);
  };
  battery.onchargingtimechange = function () {
    console.log('Charging time remaining (mins): ' + battery.chargingTime);
  };
  battery.ondischargingtimechange = function () {
    console.log('Discharging time remaining (mins): ' + battery.dischargingTime);
  };
  battery.onlevelchange = function () {
    console.log('Battery level: ' + battery.level);
  };
}

// Check for browser support first
if (!!navigator.getBattery) { // The latest API is supported
  // Use the battery promise to asynchronously call showStatus()
  navigator.getBattery().then(function(battery) {
    showStatus(battery);
  });
} else if (!!navigator.battery) { // The old API is supported
  var battery = navigator.battery;
  showStatus(battery);
}

Guille Paz has made a nice battery status demo which includes code for the old and new versions of the spec.

Status

This API has the best support of the three with Opera, Chrome and Firefox having implemented it. In the case of Firefox, the implementation currently uses an old version of the spec so for the time being it’s best to allow for both versions in your code.


Network Information API

Why use it

You’re probably aware of the navigator.onLine HTML5 attribute and its wide browser support but that only tells us if the user is connected to a network or not. For more detailed information about the network we need the aptly-named Network Information API. With the data it provides you could opt to show smaller or lower-quality images to users on slow connections, or only show a video background when you know the network speed is fast. Be careful when making assumptions though — wifi doesn’t necessarily mean fast.

How to use it

When fully implemented this provides the type and speed of connection using two attributes (type and downlinkMax) on the global navigator object. Let’s jump straight into an example…

// Some browsers use prefixes so let's cope with them first
var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;

// Check for browser support
if (!!connection) {
  // Get the connection type
  var type = connection.type;

  // Get the connection speed in megabits per second (Mbps)
  var speed = connection.downlinkMax || connection.bandwidth;
}

So easy! The type values are a pre-defined selection of self-explanatory strings:

  • bluetooth
  • cellular
  • ethernet
  • none
  • wifi
  • wimax
  • other
  • unknown

Network speed, when available, is exposed as downlinkMax, previously called bandwidth, although in reality this is difficult for browsers to measure so it may be a while before we’re able to use it. You can also attach a change event listener to navigator.connection to be even more responsive.

For a more thorough look at this API and its background, Aurelio De Rosa has written a good tutorial and network information demo which I recommend.

Status

In the browsers I tested only connection.type was supported properly and that was only in Chrome for Android and Firefox Mobile/OS (you may need to ensure dom.netinfo.enabled is set to true). It’s still early days for this API but its simplicity means it could easily be incorporated into your website or app.

Note: There is a version of the spec hosted on w3.org that currently says work on it has been discontinued. This refers to an older version and current work is being done in the GitHub-hosted version, which should eventually migrate to the W3C site.


Ambient Light Events

Why use it

We’re probably all familiar with struggling to read a screen in bright sunlight. Increasing the contrast of what’s displayed on the screen or hiding distracting backgrounds can make content much easier to read in such cases. The opposite is true — reducing how vivid a design is can avoid users screaming and covering their eyes when in a dark environment.

How to use it

Tomomi Imura, AKA @girliemac, has the definitive lowdown on how to respond to differing levels of light. Eventually we’ll all be able to use CSS4 media queries so when the light-level is dim, for example, we can respond accordingly. In the meantime though, there’s the more precise JavaScript approach which gives you access to data from the device’s light sensor. You just listen for a devicelight event and use that event’s value attribute to get the brightness of the user’s surroundings measured in lux. For example:

window.addEventListener('devicelight', function(e) {
  var lux = e.value;

  if (lux < 50) {
    // ambient light is dim so show lower-contrast version
  }
});

See Tomomi's article for a more detailed example with added CSS and a link to her ambient light demo on CodePen.

Status

At the time of writing support is only available in Firefox and Chrome beta for Android but here's a short video of her code in action:


Of course, these are not the only web technologies that are part of responsive web design but if you want to show the world that you know more than just media queries, they're a good place to start.

Song: Waiting to Load ♪

A short song about the frustrations of slow websites, especially on mobile.

Go to the song’s SoundCloud page to download, leave a comment, etc.

Lyrics

My heart is pounding as I step off the train
So excited to finally see you again.
I forgot the address of our meeting place tonight
So I get out my phone and check the website.

But there's nothing on the screen, nothing at all
No words appear as I scroll
I picture you sitting alone
As I wait for this website to load
Tired and frustrated
Scared I won't make it
And still this website won't load

Credits

The icon in the cover image is from the wonderful iconmonstr.com.

Readability for Android

So you want Readability bookmarklets on your Android device, huh? Not so fast! At the time of writing, it’s not possible to access the official Readability bookmarklets on Android but there is a workaround. Here’s how to do it in three easy steps.

Step 1: Copy the Readability script

In Opera Mobile or Mini (I don’t think this works in other browsers), select and copy the code below:

javascript:((function()%7Bwindow.baseUrl%3D'http%3A//www.readability.com'%3Bwindow.readabilityToken%3D''%3Bvar%20s%3Ddocument.createElement('script')%3Bs.setAttribute('type'%2C'text/javascript')%3Bs.setAttribute('charset'%2C'UTF-8')%3Bs.setAttribute('src'%2CbaseUrl%2B'/bookmarklet/read.js')%3Bdocument.documentElement.appendChild(s)%3B%7D)())

Step 2: Create a bookmark

Open the Bookmarks menu and click on the Add button (don’t click Save yet).

Step 3: Edit the bookmark

Screenshot of Opera Mobile Readability bookmarklet

  1. Change the title to Readability (or something similar).
  2. Delete the address and paste in the code copied from above.
  3. Click Save.

Voila! You should now be able to go to any article or blog post, click the Readability bookmarklet and enjoy a better reading experience.

Just a phone?

I don’t get all this fuss about just another phone. Maybe if I sing a song it’ll help me understand…

Video URL (with captions): www.youtube.com/watch?v=LNTSR1oOzqw

Downloads

For your downloading pleasure, here are the video and audio–only files.

License is Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported. If you need a media player, I recommend VLC.

Lyrics:

My phone don’t give me presents
I know that Steve’s no peasant
Only ever has to give me
Apps for ever and for ever
My phone don’t give me presents
Turn it on when I get lonely
People tell me that it’s only a phone
I know it isn’t

My phone begins with an “i”
Lose it and I start to cry
I don’t care if it’s locked down
I just love those shiny round corners
So easy on the eye
It makes all my friends jealous
Makes them scream like girls as well as drool
Don’t ask me why

It’s a phone and I understand
It’s a phone that makes me feel like a man

My phone can cure disease
Fix social problems with ease
Global warming, it’s no biggie
World peace is not that tricky
My phone can cure disease
Vegetarians and feminism
It’s no match for fanboyism
Come on, why don’t you join me

It’s a phone
It’s a phone
It’s just a phone
It’s not just a phone
It’s a sexy phone
Oh, it’s more than a phone

It’s a phone
My life’s in this phone
My life IS this phone
Excuse me while I kiss this phone
It’s just a phone
So much more than a phone

How to watch videos on a Nokia smartphone

The Nokia N96 smartphoneMy new Nokia N96 (yes, and then they immediately released the N97!) may not be as intuitive as the iPhone but is packed with far more features and is so much more open to exploration that it’s a keeper. Not only that but clever @LonelyBob gave me some help last night to fix a problem I’d been battling with – video conversion.

Like him, I tried MEncoder which (unusually) didn’t do the trick and then gave FFmpeg a go. As usual, it requires a load of options and arguments that I don’t fully understand but converts almost any format into any other format – in this case an MP4 file. Trouble was, everything I tried resulted in a playback error on the phone. After exhaustive searching it seems the MP4 needs to be in a mobile-friendly wrapper for which I used MP4Box, found in the “gpac” package on Linux. That worked nicely but the extra step is a hassle. Enter @LonelyBob and his magic one-liner. I edited it a bit for my version of FFmpeg (3:0.svn20090303-1) and this is what’s left:

ffmpeg -y -i input.mkv -vol 256 -acodec libfaac -ac 2 -ar 44100 -ab 64000 -f 3gp -vcodec mpeg4 -s 320x240 -r 25 -b 256000 output.mp4

Of course, input.mkv can be almost any type of video file. The resulting output file is small but not great quality so you could try changing the bitrates, etc. to something like:

  • -ab (audio bitrate): 96000
  • -b (video bitrate): 384000
  • -s (dimensions): 320×176 (for widescreen)

N.B. If you get an “Unknown encoder: libfaac” message, try using “-acodec aac” instead.

Oh, and it’s worth the effort – the N96′s screen is fantastic.