A quick look at the Network Information API

UDPATE : this article is now out of date. Please read the latest spec at http://w3c.github.io/netinfo/ and a very interesting summary of the use cases at http://w3c-webmob.github.io/netinfo-usecases/

UPDATE : the W3C working draft has been updated and the categories (unknown, ethernet, wifi, 2g, 3g, 4g and none) are gone. For now it's bandwidth in Megabytes/second as detailed below but doubts are expressed about the viability of that with the possibility of very-slow, slow, fast and very fast mooted.

If you were to ask developers with an interest in mobile today what one feature they would like above all others, there’s a good chance a lot of them would say bandwidth detection.

The Network Information API represents the first steps down that road, and there is a working draft at the W3C dated June 2011. As we can see from Maximiliano Firtman‘s excellent mobile support tables, it is supported on Android 2.2 and up, and on the Kindle Fire’s Silk browser.

As APIs go it couldn’t be much simpler — we just get the value of navigator.connection.type which will be one of unknown, ethernet, wifi, 2g, 3g, 4g and none. In practice Android deviates from the specification and returns 0, 1, 2, 3 or 4. (I don’t know what Silk does, but it’s a custom Android so it’s as likely as not that it’s the same).

Value Connection type
Fig. 1 The values returned by navigator.connection.type and their corresponding network types in the Android BOM.

So a simple alert(navigator.connection.type); will give us something like the screenshot shown in figure 2. Demo (Android only)

A screenshot from an Android device showing an alert box with the number 2
Fig. 2 An Android device on a wifi connection.

That’s the current version of the Network Information API as it exists in the wild today, and although not totally useless it doesn’t give us much to go on. We can really only make inferences from CELL_2G and NONE. We know 2g is definitely slow — ethernet, wifi and 3g can be fast or slow. As far as NONE is concerned we could maybe listen for clicks on links/buttons and present our own “Network down” message instead of a browser or router error page if there is no network.

Personally, I wouldn’t be comfortable drawing any conclusions about network speed if the returned value represented ethernet, wifi or 3g but I might consider something like:

if(navigator.connection && navigator.connection.type !== 3){ //not 2g
    document.write('<link rel="stylesheet" href="hi-res-backgrounds.css" media="only screen and (-webkit-min-device-pixel-ratio:1.5),only screen and (min--moz-device-pixel-ratio:1.5),only screen and (-o-device-pixel-ratio:3/2),only screen and (min-device-pixel-ratio:1.5), only screen and (min-resolution:1.5dppx)">');

Faced with developer apathy and little interest from vendors a new direction was sought, and an Editor’s Draft is now up at the W3C which looks more promising.

Like the old version it uses the navigator.connection object but the type attribute is gone. Instead we have the rather exciting bandwidth and be-nice-to-your-users metered attributes.

There is a third onchange attribute which is a function that fires a change (for when bandwidth changes), online or offline event.

Using navigator.connection.bandwidth returns an integer value of the current bandwidth in megabytes per second. (Note how this is different to how ISPs report their bandwidth achievements in megabits per second.) It is to return infinity if the bandwidth is unknown, and 0 if there is no connection.

The metered attribute is a boolean that is true if the user is on something like a pre-pay or capped data plan. The spec suggests that the information necessary to know if metered is true or false should come from the ISP, carrier or the user.

There are a couple of examples using the change event in the draft spec: one to update navigator.connection.bandwidth in the console as it changes, the other that uses it in conjunction with the metered attribute to prevent automatic polling.

On to implementation. Unsurprisingly it’s even less widespread than type. Mozilla have a prefixed version using mozConnection that’s in Firefox 12 and up, but I’m getting fairly useless results in Firefox 13 on Windows 7. On my home wifi the bandwidth is reported as Infinity, which according to the spec means it’s unknown. I can assure you the kids’ Buzz Lightyear toys are far closer to infinity than my home broadband will ever be.

WebKit also has a prefixed implementation webkitConnection but it’s undefined in Canary and Chromium that I’ve tested.

Either way I’ve put up a demo using the Mozilla and WebKit prefixed versions (run in Firefox with the console open).

The fact that Mozilla and WebKit are off the mark already has them ahead of IE and Opera. It could well be in the next version of Chrome (don’t hold your breath for Safari) and I’m looking forward to making good use of it in production.

I’m glad the type attribute isn’t being used any more — it’s likely to be misunderstood and misused. Misunderstood in that some devs may make assumptions about network speed based on the network type; misused in that some devs may make assumptions about users’ context.

Nevertheless it’s still going to be hard to use bandwidth sensibly. Here are a few potential problems I can think of.

There are probably many other issues that I haven’t thought of but I’m sure the benefits will outweigh them, and I’m looking forward to working out the best approaches and seeing what sort of consensus the community arrives at when the spec stabilizes.