Channels ▼


Developing Cross-Platform Mobile Apps with HTML5 and Intel XDK

You can easily change the workspace resolution and orientation by clicking on the device selection and device orientation icons located in the toolbar at the top of the workspace. There are three predefined resolutions to help you with the differences in devices: Phone, Phablet, and Tablet.

The following lines show the generated HTML5 code for index.html:

<!DOCTYPE html>
  * Please see the included file for license terms and conditions.

        <meta charset="UTF-8">
        <link rel="stylesheet" type="text/css" href="app_framework/2.1/css/af.ui.min.css">
        <link rel="stylesheet" type="text/css" href="app_framework/2.1/css/icons.min.css">
        <title>Robot Controller</title>
        <meta http-equiv="Content-type" content="text/html; charset=utf-8">

  * The "meta viewport" tag (below) helps your app size appropriately to a device's screen.
  * Note that the meta viewport approach is being phased out in favor of the @viewport CSS rule.
  * For a quick overview of both, see this article:
  * To see what happens, try the app on a real device with and without a "meta viewport" tag.

        <!-- <meta name="viewport" content="width=device-width, initial-scale=1"> -->
        <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
        <!-- <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes, minimum-scale=1, maximum-scale=2"> -->

            /* following three (cascaded) are equivalent to above three meta viewport statements */
            /* see */
            /* see */
                @-ms-viewport { width: 100vw ; zoom: 100% ; }                           @viewport { width: 100vw ; zoom: 100% ; }
                @-ms-viewport { user-zoom: fixed ; }                                    @viewport { user-zoom: fixed ; }
                /*@-ms-viewport { user-zoom: zoom ; min-zoom: 100% ; max-zoom: 200% ; }   @viewport { user-zoom: zoom ; min-zoom: 100% ; max-zoom: 200% ; }*/

        <link rel="stylesheet" href="css/app.css">
        <link rel="stylesheet" type="text/css" href="css/index_main.less.css" class="main-less">

        <!-- IMPORTANT: Do not include your weinre script tag as part of your release builds! -->
        <!-- Place your remote debugging (weinre) script URL from the Test tab here, if it does not work below -->
        <!-- <script src=""></script> -->

        <!-- Most third-party libraries should go here. References (below) are just examples to give you the general idea... -->
        <!-- <script src="lib/mc/hammer.js"></script> -->
        <!-- <script src="lib/ft/fastclick.js"></script> -->

        <script src="intelxdk.js"></script>
        <!-- phantom library, needed for XDK "legacy" container api calls -->
        <script src="cordova.js"></script>
        <!-- phantom library, needed for Cordova api calls -->
        <script src="xhr.js"></script>
        <!-- phantom library, needed for XDK "legacy" container CORS -->

        <script src="js/app.js"></script>
        <!-- for your event code, see README and file comments for details -->
        <script src="js/init-app.js"></script>
        <!-- for your init code, see README and file comments for details -->
        <script src="xdk/init-dev.js"></script>
        <!-- normalizes device and document ready events, see file for details -->
            You may substitute jQuery for the App Framework selector library.
        <script type="application/javascript" src="app_framework/2.1/appframework.js"></script>
        <script type="application/javascript" src="app_framework/2.1/appframework.ui.js" data-ver="1"></script>
        <script type="application/javascript" src="xdk/appdesigner/js/rest-of-space.js"></script>

    <body id="afui">

        <!-- IMPORTANT: Do not include your weinre script tag as part of your release builds! -->
        <!-- Place your remote debugging (weinre) script URL from the Test tab here, if it does not work above -->
        <!-- <script src=""></script> -->
        <header class="wrapping-col wrap-element uib_w_1" data-uib="app_framework/header" data-ver="2" id="af-header-0">
            <h1>Robot Controller</h1>
        <div id="content" class="uwrap">
            <div class="upage vertical-col left panel" id="mainpage" data-header="af-header-0" data-footer="none">

                <div class="uib-grid widget uib_w_2 grid-text grid-height d-margins" data-uib="layout/grid" data-ver="0">
                    <div class="uib-grid-row">
                        <div class="uib-grid-cell widget-container"></div>
                        <div class="uib-grid-cell widget-container">
                            <a class="button widget uib_w_3 d-margins icon up" data-uib="app_framework/button" data-ver="1" id="up">Up</a>
                        <div class="uib-grid-cell widget-container"></div>
                    <div class="uib-grid-row">
                        <div class="uib-grid-cell widget-container">
                            <a class="button widget uib_w_4 d-margins icon left" data-uib="app_framework/button" data-ver="1" id="left">Left</a>
                        <div class="uib-grid-cell widget-container"></div>
                        <div class="uib-grid-cell widget-container">
                            <a class="button widget uib_w_5 d-margins icon right" data-uib="app_framework/button" data-ver="1" id="right">Right</a>
                    <div class="uib-grid-row">
                        <div class="uib-grid-cell widget-container"></div>
                        <div class="uib-grid-cell widget-container">
                            <a class="button widget uib_w_6 d-margins icon down" data-uib="app_framework/button" data-ver="1" id="down">Down</a>
                        <div class="uib-grid-cell widget-container"></div>
                <div class="grid grid-pad urow uib_row_3 row-height-3" data-uib="layout/row" data-ver="0">
                    <div class="col uib_col_4 col-0_12-12" data-uib="layout/col" data-ver="0">
                        <div class="widget-container content-area vertical-col">

                            <div class="table-thing with-label widget uib_w_7 d-margins" data-uib="app_framework/textarea" data-ver="1">
                                <label class="narrow-control label-inline" for="accelerometer">Accelerometer read values:</label>

                                <textarea class="wide-control" rows="3" wrap="soft" id="accelerometer"></textarea>
                            </div><span class="uib_shim"></span>
                    <span class="uib_shim"></span>


You can switch to the EMULATE tab at any time to test the app on the emulator based on the Apache Ripple Emulator. The emulator makes the hybrid app run in a webview that won't be 100% accurate, so you need to either test the app on the emulator provided with each platform's SDK or on the device to really measure performance and make sure that things work as expected. However, this tab is useful to test and debug your hybrid app with different resolutions and test specific scenarios such as the app response when the accelerometer values change. In addition, you can get the gist of how the layout will appear on different devices because App Framework matches the native UI for each device and the emulator does its best to display the same UI that would be visible on the selected device.

A very interesting feature that can boost your productivity when designing the layouts is Live Layout Editing. If you have an Android, iOS, or Windows Phone device connected to your WiFi network, you can install the Intel App Preview app on your devices. The following list provides the shortcuts for the app in the different app stores:

You can have many devices with the app installed and use the Live Layout Editing feature. So, for example, you can have an iPad, an iPhone, a Windows Phone 8, and a Samsung Galaxy Tab S 10.5 tablet and all the devices running the app and displaying the layout at the same time. If you have targeted multiple mobile platforms from a single source before, you know that sometimes what you see in your local IDE is not exactly what you get in your real device. In this case, the Live Layout Editing feature uses the same webview that the hybrid app will launch to render the preview, so you will be able to make the layout compatible with your most important target devices while you make changes to the UI.

Go back to the DEVELOP tab and make sure the CODE view is activated. Click Live Layout Editing and then click View on Device over WiFi. Click Confirm to start the test local Web server.

Then, you can scan the QR code displayed on the IDE or just start the Intel App Preview app and tap Live Layout. The app will render the view you are editing and the IDE will display Viewing on Device over WiFi at the right-hand side. You can do this in all the devices you want to render the UI.

Notice that you cannot switch to DESIGN, you have to edit the HTML5 code while you are using the Live Layout Editing. When you select a DOM element, it will be highlighted in the rendered view on the connected devices. The changes you make in the HTML5 code will be rendered on all the connected devices. For example, go to the following line that defines a label:

<label class="narrow-control label-inline" for="accelerometer">Accelerometer read values:</label>

Replace the text Accelerometer read values: with Accelerometer data: and see how the changes are rendered in real time on all the connected devices.

Making Changes to the Code

I'll now add some JavaScript code to interact with the included plugins. The following lines show the code for the callbacks, added to the www/js/app.js file. It will be used to retrieve values from the accelerometer and change the text of the buttons based on these values. The code doesn't interact with any REST API yet. The code doesn't represent the best way to work with the accelerometer, it is just an example that will allow me to show how to use the tools included in the IDE.

function accelerometerSuccess(acceleration) 
    var accelerationX = Math.round(acceleration.x * 10) / 10;
    var accelerationY = Math.round(acceleration.y * 10) / 10;
    var accelerationZ = Math.round(acceleration.z * 10) / 10;

    var leftButton = $("#left");
    var rightButton = $("#right");
    var upButton = $("#up");
    var downButton = $("#down");
    if (accelerationX > 0) {
    else if (accelerationX < 0) {

    if (accelerationY > 0) {
    else if (accelerationY < 0) {

        'X: ' + accelerationX + '\n' +
        'Y: ' + accelerationY + '\n' +
        'Z: ' + accelerationZ + '\n');

function accelerometerError() {
    alert("Accelerometer Error");

The following lines show the new version of app.initEvents in www/js/init-app.js. I've just added the lines that call methods of intel.xdk.device and navigator.accelerometer.

app.initEvents = function() {
    "use strict" ;
    var fName = "app.initEvents():" ;
    app.consoleLog(fName, "entry") ;

    // NOTE: initialize your third-party libraries and event handlers
        { frequency:1000 }) ;

    app.initDebug() ;           // for debug only, not required
    app.hideSplashScreen() ;    // after init is good time to remove splash screen; using a splash screen is optional

    // app initialization is done
    // app event handlers are ready
    // exit to idle state and wait for app events...

    app.consoleLog(fName, "exit") ;
} ;

Save changes, go to the EMULATE tab, and the selected device will render the view. Move the accelerometer and notice that the accelerometer data is updated in the text view and only two buttons display text (see Figure 3). In this case, the app is designed to provide continuous movement in two directions for the robot that is going to be controlled with calls to a REST API.

Figure 3: Using the EMULATE tab to test how the accelerometer changes work with the app.

Running the Project on Different Devices with the Intel App

Now, go to the TEST tab and click the WIFI button at the upper-left corner. You can easily run the app on the different devices connected to your WiFi network with the previously introduced Intel App Preview app.

Launch the app on your device and go to Local Apps. If you followed the previous steps, the Intel XDK local server is already running. The app will display a list with the available projects. Tap RobotController and then tap Launch This App. The IDE will ask you permission to share your project files with the connected device. After you grant permission in the IDE, the app will run within the Intel App Preview app. You can follow the same procedure on any device connected to your WiFi network and test how your app works on each device. When you want to stop testing your app, you just need to make a three-finger tap.

If your devices aren't connected to your WiFi network, you can click on the MOBILE button at the upper-left corner and push the files to the testing servers. You will be able to launch your app by tapping on Server Apps instead of Local Apps in the Intel App Preview app.


In this article, I focused on the usage of many of the tools that facilitate developing and testing HTML5 hybrid mobile apps with Intel XDK. The ability to easily run your app in multiple devices with a few clicks and taps is extremely useful. In the next article, I'll provide details of the different tools that enable you to debug apps in Intel XDK with a more complex version of the RobotController app that interacts with a REST API.

Gastón Hillar is a senior contributing editor at Dr. Dobb's specializing in exploring emerging developer tools and technologies.

Related Reading

More Insights

Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.