Optimizing for high and low network speeds

This article is in need of a technical review.

Network connectivity is a big issue for mobile apps, and network usage has many costs associated with it: battery life, performance and in some cases actual data transfer costs. These aspects should always be considered when designing and building cross platform web apps. This article explores a technology that facilitates optimization for high and low network speeds in the context of open web apps: The Network Information API.

The Network Information API

The Network Information API provides information about the system's connection. The specification defines a connection object, a type property and a typechange event.

navigator.connection
navigator.connection.type  // "cellular", "bluetooth", "ethernet", "wifi", "other", "none", "unknown"
navigator.connection.ontypechange

At the moment it's been implemented in Firefox OS, Firefox for Android and Chromium: more information in this living document.

Demo: Net Pics

Net Pics is a photo-sharing web application that enables users to take pictures and sync them with online services. The demo is going to cover the use case of synchronizing media data (photos in this case) in order to give the user control to whether large uploads should happen over cellular. The source code is published on GitHub, and a live demo is available here.

Net Pics combines the Network Information API with the Battery Status API in order to let the user make smarter decisions about when to sync: only when the battery is charging or fully charged, for instance. For a comprehensive article on the Battery Status API please refer to the MDN page Retrieving Battery status information.

HTML & CSS

The Network Information API is a JavaScript API, so showing the HTML and CSS might be considered out of scope here, however it can be useful to understand better the elements composing the page on which JavaScript operates.

Settings

The settings are basically a list of <options> inside a <select> element:

            <section id="settings">
                <article>
                    <p>Sync over</p>
                    <div>
                        <select id="sync-picker">
                            <option>Choose...</option>
                            <option>Wifi-only & battery charging or full</option>
                            <option>Wifi-only</option>
                            <option>Wifi & carrier network</option>
                            <option>Never</option>
                        </select>
                    </div>
                </article>
            </section>

Photogallery

The photogallery is a <section> consisting of a set of articles containing the images and sync indicators:

            <section id="gallery">
                <article>
                    <img alt="roma" src="img/roma.jpg" />
                    <div class="sync-status"></div>
                </article>
                …
            </section>

Action box

The action box contains a button for taking photos.

        <section id="action">
            <div id="take-photo">
                <div class="camera">
                    <div class="lens"></div>
                </div>
            </div>
        </section>

The button is done using CSS. You can find the CSS code in shapes.css.

JavaScript and WebAPIs

Net Pics implements the following JavaScript files:

<script src="scripts/network-manager.js"></script>
<script src="scripts/energy-manager.js"></script>
<script src="scripts/sync-manager.js"></script>
<script src="scripts/settings.js"></script>
<script src="scripts/gallery.js"></script>
<script src="scripts/action-bar.js"></script>
<script src="scripts/app.js"></script>
<script src="scripts/start.js"></script>

Note: This demo is built using Object Oriented Programming. Read our Introduction to object-oriented JavaScript for more details.

Each JavaScript file represents a component that executes specific tasks in the application. The Network Manager is the component that retrieves network information, so the most interesting code for the purposes of this tutorial is inside network-manager.js. However, in order to understand how the app works, we’ll briefly have a look at all the JavaScript files. Feel free to skip to the Network Manager section if you are mainly interested in the Network Information API.

Start

The app.js file contains the initializations of the JavaScript objects the Net Pics web app needs to work.

NetworkManager.init(this.updateNetInfo);
EnergyManager.init();
Gallery.init();
SyncManager.init();
Settings.init();
ActionBar.init();

This is done when the window object is loaded.

The updateNetInfo parameter passed to the NetworkManager constructor is a function called by the NetworkManager at the beginning and when the connection changes. The updateNetInfo function updates network information printed on the top right of the screen and re-initializes the SyncManager when the function is called on connection change.

function updateNetInfo(netInfo, isOnConnectionChange) {
    /* Log */
    document.querySelector('#net-info-label').innerHTML = netInfo.label;
    document.querySelector('#net-info-value').innerHTML = netInfo.value;

    /* If connection changed */
    if (isOnConnectionChange) {
        /* Check synchronization */
        SyncManager.init();
    }
}

Settings

The Settings object handles the changes made on the sync picker:

/* Initialize DOM Objects */
this.picker = document.querySelector('#sync-picker');
this.syncSetting = this.picker.options[this.picker.selectedIndex].text;

/* Apply default settings */
this.apply();

/* Apply settings on change */
var _self = this;
this.picker.onchange = function(e) {
    _self.syncSetting = e.target.value;
    _self.apply();
};

The apply method initializes the SyncManager by calling:

SyncManager.init();

The SyncManager has access to the syncSetting property.

The ActionBar

The ActionBar handles the takePhoto button:

this.takePhotoButton = document.querySelector('#take-photo');

/* Call takePhoto() when the takePhoto button is clicked */
this.takePhotoButton.onclick = this.takePhoto;

and calls the Gallery to insert a static photo:

takePhoto: function() {
    Gallery.insertPhoto();
}

The Gallery handles the gallery section and the visibility of the synchronization status:

this.gallery = document.querySelector('#gallery');
this.items = this.gallery.querySelectorAll('article');
this.syncingStatusItems = this.gallery.querySelectorAll('.sync-status');

The insertPhoto method inserts a static photo into the gallery and re-initializes the SyncManager:

SyncManager.init();

The Sync Manager

The SyncManager manages the synchronization with the server.

The init method initialises the synchronization based on sync settings, network and battery information:

init: function() {
    if ((Settings.syncSetting === 'Wifi & carrier network')
            && (NetworkManager.isWifi() || NetworkManager.isCarrierNetwork()))
    {
        this.doSync();
    }
    else if ((Settings.syncSetting === 'Wifi-only')
            && NetworkManager.isWifi())
    {
        this.doSync();
    }
    else if ((Settings.syncSetting === 'Wifi-only & battery charging or full')
            && NetworkManager.isWifi()
            && (EnergyManager.isBatteryCharging() || EnergyManager.isBatteryFullyCharged()))
    {
        this.doSync();
    }
    else {
        this.stopSync();
    }
}

The doSync and stopSync methods emulate a file transfer to the server by using window.setInterval. For more information you can have a look at the source code.

For the purposes of this article, the most interesting part of the init function are the following calls:

NetworkManager.isCarrierNetwork()
NetworkManager.isWifi()

which will be described in detail, along with the Network Information API, in the Network Manager section.

The Energy Manager

The EnergyManager uses the Battery Status API to check if the battery is charging or fully charged:

EnergyManager.isBatteryCharging()
EnergyManager.isBatteryFullyCharged()

For a comprehensive article on the Battery Status API please refer to the MDN page Retrieving Battery status information.

The Network Manager

The NetworkManager uses the Network Information API to retrieve the network speed and let the SyncManager handle the synchronization with the server based on the settings provided by the user.

This is the code that updates network information on change:

navigator.connection.addEventListener('typechange', function() {
    updateCallback(_self.getNetInfo(), true);
}, false);

The isNetworkInfoAPISupported function checks whether the Network Information API is supported by the browser:

isNetworkInfoAPISupported: function() {
    if (navigator.connection) {
        return true;
    }
    return false;
}

The getNetInfo method returns network information as a JSON structure in order to be easily printed:

getNetInfo: function() {

    if (this.isNetworkInfoAPISupported()) {

            return {
                "label": "type",
                "value": navigator.connection.type
            };
        }
    }

    else {
        return {"label": "type", "info": "-" };
    }
}

The isWifi method checks whether the network connection is wifi:

isWifi: function() {

    if (navigator.connection.type === 'wifi') {
        return true;
    }

    return false;
}

The isCarrierNetwork method checks whether the network connection is 2G/3G/4G:

isCarrierNetwork: function {

    if (navigator.connection.type === 'cellular') {
        return true;
    }

    return false;
}

The control switches above will not be necessary as soon as the Network Information API specification stabilizes, and browser vendors implement the latest version of the spec.

Document Tags and Contributors

Contributors to this page: franciov, Ehsan, chrisdavidmills, Sheppy
Last updated by: franciov,