15. Cordova Development End to End

At this point in the book, I’ve shown you a lot about Cordova programming, but I’ve not done a complete walk-through of the process using a real application as an example. So, in this chapter, I show you the steps needed to create and test a complete application from start to finish (and cover some new topics as well).

About the Application

In PhoneGap Essentials, I created at least one complete sample application for each Cordova API; it was a great way to highlight all of the options for each API. For Apache Cordova 3 Programming, I took one of the applications from that book and built it into a more complete example in order to demonstrate the end-to-end process. The application was a simple one I created to demonstrate how to implement the Compass API into an application. In this edition of the book, I have updated the material for Cordova 4.

The application displays a simple screen showing an image representing a compass dial. As the user rotates the device along a horizontal axis, the compass image rotates and the heading is displayed on the page below the compass image. The original application’s screen is shown in Figure 15.1.

Image

Figure 15.1 Sample Compass Application

An interesting example, but not very pretty. In this chapter, I update the application’s UI using jQuery Mobile, plus I use the Cordova merges folder capability to use different compass graphics for Android and iOS. I added a custom icon for the application as well.

Creating the Application

To create the application, I opened a terminal window and navigated to the system’s dev folder, then issued the following command:

cordova create compass com.ac4p.compass Compass

The Cordova CLI will create the project folder, then download the default HTML project files for the www folder:

Creating a new cordova project with name "Compass" and id "com.ac4p.compass" at
location "C:Usersjwargodevcompass"
Downloading cordova library for www...
Download complete

If I’d used the --copy-to or --link-to command-line switch, the CLI would have used local project files I already had available, so nothing would have been downloaded from the Internet. The second time I ran this command, nothing would be downloaded since a copy of the web application files would already have been available in my system’s home folder.

Next, I need to change into the new project folder, then add the mobile device platforms I want to support:

cd compass
cordova platform add android ios

The Cordova CLI will connect to the NPM repository (www.npmjs.org), then pull down a mobile application project for each target platform. The project files are extracted to the project’s platforms folder.

npm http GET https://registry.npmjs.org/cordova-android/3.6.4
npm http 200 https://registry.npmjs.org/cordova-android/3.6.4
npm http GET https://registry.npmjs.org/cordova-android/-/cordova-android-3.6.4.tgz
npm http 200 https://registry.npmjs.org/cordova-android/-/cordova-android-3.6.4.tgz
Creating android project...
Creating Cordova project for the Android platform:
    Path: platforms/android
    Package: com.ac4p.compass
    Name: Compass
    Android target: android-19
Copying template files...
Project successfully created.
npm http GET https://registry.npmjs.org/cordova-ios/3.7.0
npm http 200 https://registry.npmjs.org/cordova-ios/3.7.0
npm http GET https://registry.npmjs.org/cordova-ios/-/cordova-ios-3.7.0.tgz
npm http 200 https://registry.npmjs.org/cordova-ios/-/cordova-ios-3.7.0.tgz
Creating ios project...

At this point, what I have is a new Cordova project with support for the Android and iOS mobile device platforms. Notice that even though I’m using the Cordova 4 CLI, the platforms have not yet been upgraded.

I know that the application is going to need to leverage at least one Cordova core plugin, perhaps more, so it’s time to start adding plugins. Knowing that I like to have my Cordova applications write content to the console as they run, at least during the initial testing phase, I know I will need to add the Console plugin to the project:

cordova plugin add org.apache.cordova.console

The Cordova CLI will connect to NPM, pull down the Console plugin code, and install it in the plugins folder:

Fetching plugin "org.apache.cordova.console" via plugin registry
npm http GET http://registry.cordova.io/org.apache.cordova.console
npm http 200 http://registry.cordova.io/org.apache.cordova.console
npm http GET http://cordova.iriscouch.com/registry/_design/app/_rewrite/org.apache
.cordova.console/-/org.apache.cordova.console-0.2.11.tgz
npm http 200 http://cordova.iriscouch.com/registry/_design/app/_rewrite/org.apache
.cordova.console/-/org.apache.cordova.console-0.2.11.tgz
Installing "org.apache.cordova.console" for android
Installing "org.apache.cordova.console" for ios

I will also have the application display alerts, as needed, during testing, so I will add the Dialogs plugin to the project:

cordova plugin add org.apache.cordova.dialogs

The Cordova CLI will connect to NPM, pull down the Dialogs plugin code, and install it in the plugins folder:

Fetching plugin "org.apache.cordova.dialogs" via plugin registry
npm http GET http://registry.cordova.io/org.apache.cordova.dialogs
npm http 200 http://registry.cordova.io/org.apache.cordova.dialogs
npm http GET http://cordova.iriscouch.com/registry/_design/app/_rewrite/org.apache
.cordova.dialogs/-/org.apache.cordova.dialogs-0.2.10.tgz
npm http 200 http://cordova.iriscouch.com/registry/_design/app/_rewrite/org.apache
.cordova.dialogs/-/org.apache.cordova.dialogs-0.2.10.tgz
Installing "org.apache.cordova.dialogs" for android
Installing "org.apache.cordova.dialogs" for ios

Notice that the versions are different between the two plugins; this is because plugins are released independently (they used to all be released in a bunch). Notice too that the plugin versions don’t align with the Cordova 4 release. Again, this is because plugins are on their own release schedule.

I am not going to show the CLI output for the remaining plugins as it’s more of what you’ve already seen. During troubleshooting, I like to write the Cordova version, which is exposed through the Device plugin API, to the console, so I’ll need the Device plugin added to the project as well:

cordova plugin add org.apache.cordova.device

And finally, since I want the application to use the compass, I will need to add the Device Orientation plugin to the project:

cordova plugin add org.apache.cordova.device-orientation

With my project in place and all of my plugins added, I’m ready to write some code. I will do all of my code editing in the project’s www folder shown in Figure 15.2.

Image

Figure 15.2 Compass Project www Folder

The first thing I should do, though, is populate the application’s config.xml file with important information about the application. At the top of the file list shown in Figure 15.2 is the config.xml; I opened the file in my text editor of choice and populated it with my information as shown in Figure 15.3.

Image

Figure 15.3 Compass Application config.xml File

The name element is populated automatically using the value provided when creating the project with the cordova create command; any additional values are added manually by the developer. The value defined in the name element is the name of the application as it will appear on the device home screen on each target platform. I used Compass here because it accurately describes the application and will easily fit within the available space on the home screen. The application’s name typically appears beneath the application’s icon on the home screen, and there is usually only a certain amount of space available before the device truncates the text. So, when you assign the application name, you will want to make sure it’s short enough to display correctly on all platforms.

Next, I changed the author information in the file so that it contained my information instead of the generic settings provided by the Cordova developers.

With the config.xml file updated, I saved my changes, and now it’s time to write some code.

The original version of this application had a very simple look to it, represented by the HTML code shown here:

<body onload="onBodyLoad()">
  <h1>Example 13-2</h1>
  <img src="compass.png" id="compass" />
  <br />
  <p id="headingInfo"></p>
</body>

When I wrote the original application, I didn’t make any effort to make it look nice; I simply plunked in the HTML code I needed and that was it. I didn’t do any styling of the page, nor did I do anything to center the compass graphic on the page.

For this version of the application, I wanted to spruce it up a little bit, so I decided to use jQuery Mobile to create a more mobile-phone-like look for the app. The first thing I did was download the latest versions of jQuery (www.jquery.com) and jQuery Mobile (www.jquerymobile.com) from their respective web sites. Once they were downloaded, I copied the files over to the Cordova project’s www folder, then added references to the jQuery and jQuery Mobile CSS and JavaScript files to the head portion of the application’s index.html:

<link rel="stylesheet" href="css/jquery.mobile-1.4.5.min.css" />
<script src="js/jquery-1.11.1.min.js"></script>
<script src="js/jquery.mobile-1.4.5.min.js"></script>


Note

For this project, I placed any CSS files into the Cordova project’s www/css folder and any JavaScript resources into the Cordova project’s www/js folder.


I could have easily used hosted versions of these files and pulled them down when the application first launched, but I prefer to have all of an application’s assets packaged with the Cordova application. This topic is discussed further in Chapter 17, “Using Third-Party UI Frameworks with Cordova.”

The application will need to be able to rotate the compass image; I accomplished this using jQuery Rotate, a free jQuery plugin I found at http://goo.gl/b3brTA. To add the plugin, I downloaded the plugin’s JavaScript file to the Cordova project’s www folder, then added a reference to the file in the application’s index.html file:

<script src="js/jQueryRotateCompressed.js"></script>

The application’s complete index.html file is shown in Listing 15.1.

Listing 15.1 index.html


<!DOCTYPE html>
<html>
<head>
  <title>Compass</title>
  <meta http-equiv="Content-type" content="text/html; charset=utf-8">
  <meta name="viewport" id="viewport" content="width=device-width,
    height=device-height, initial-scale=1.0, maximum-scale=1.0,
    user-scalable=no" />
  <link rel="stylesheet" href="css/jquery.mobile-1.4.5.min.css" />
  <script src="js/jquery-1.11.1.min.js"></script>
  <script src="js/jquery.mobile-1.4.5.min.js"></script>
  <script src="js/jQueryRotateCompressed.js"></script>
  <script src="js/index.js"></script>
  <script src="cordova.js"></script>
</head>

<body onload="onBodyLoad()">
  <div data-role="page">
    <div data-role="header">
      <h1>Compass</h1>
    </div>
    <div data-role="content">
      <div style="text-align:center;">
        <img src="images/compass.png" id="compass" />
        <br />
        <p id="headingInfo"> <strong>Heading:</strong> 0 Degrees</p>
      </div>
    </div>
    <div data-role="footer" data-position="fixed">
      <h3>www.cordova4programming.com</h3>
    </div>
  </div>
</body>
</html>


jQuery Mobile uses data-role attributes within elements to style those particular elements with the appropriate look. So, in Listing 15.1, I’ve created a header div on the page and assigned it a data-role of header and created a footer div on the page and assigned it a data-role of footer. The data-position="fixed" forces the footer to remain on the bottom of the application screen when scrolling.

Next, I moved the content for the page into a div assigned with a data-role of content. In order to have the compass graphic and heading text centered on the page, I added a new div and styled it with a style="text-align:center;" as shown in the code.

With that code in place, the look of the application is changed dramatically as shown in Figure 15.4. In this example, I haven’t packaged the application and deployed it to a mobile device; I’ve simply opened the application’s index.html page in the desktop browser so I can see how it looks. I could also have used the Ripple Emulator (described in Chapter 5, “The Mechanics of Cordova Development”) to quickly view how the application would look on multiple simulated devices, and I could have simulated the compass heading as well.

Image

Figure 15.4 The Compass Application with a jQuery Mobile Look

Now that I have the application’s user interface updated, it’s time to start taking a look at the application’s JavaScript code. In my original sample application, the JavaScript was embedded inside of the application’s index.html file. As I described in Chapter 5, it’s easier to work with some of the debugging tools if the HTML and JavaScript are in separate files, so I split out the JavaScript code into its own index.js file.

Since I know that my code isn’t going to work right away, and since a Cordova application fails silently most of the time, the first thing I did was add an onerror function to the application:

window.onerror = function (msg, url, line) {
  var idx = url.lastIndexOf("/");
  if (idx > -1) {
    url = url.substring(idx + 1);
  }
  //Build the message string we'll display to the user
  var errStr = "ERROR in " + url + " (line #" + line + "): " + msg;
  //Write the error to the console
  console.error(errStr);
  //Tell the user what happened
  alert(errStr);
  return false;
};

This function catches any errors encountered in the application’s JavaScript code, then writes the error to the console and displays an alert dialog with the same information. This allows me to quickly catch any syntax errors when the application is running and also allows me to quickly tell when I’ve called a plugin API without adding the plugin to my project (which I happen to do all the time).

Next comes the onDeviceReady function I’ve shown throughout the book. It is set up as an event listener for the Cordova deviceready event and fires after the Cordova container has finished initialization. In this function, I know that the Cordova container is ready, so I can create the compass watch needed for this application:

function onDeviceReady() {
  console.log("Entering onDeviceReady");
  console.log("Cordova: " + device.cordova);
  navigator.notification.alert("Cordova is ready");
  //Set up the watch
  //Read the compass every second (1000 milliseconds)
  var watchOptions = {
    frequency: 1000,
  };
  console.log('%s Creating watch: %s', appName, JSON.stringify(watchOptions));
  watchID = navigator.compass.watchHeading(onSuccess, onError, watchOptions);
  console.log("Leaving onDeviceReady");
}

The function defines a watchOptions object that is used to help set up a heading watch that will cause the application to update the heading periodically. The watchOptions object can have either a frequency property or a filter property assigned to it. Right now, the application is set up with the following:

var watchOptions = {
  frequency : 1000
};

A heading watch will cause the Compass API to report the device’s heading every 1000 milliseconds (every 1 second). The filter property is used to define the amount of heading change (in degrees) before the Compass API will report a heading. In the following example, the filter property is instructing the Compass API to deliver a heading every time the heading changes more than 1 degree:

var watchOptions = {
  filter : 1
};

You can specify both properties as shown below, but as soon as you specify a filter, the frequency property is ignored by the Compass API:

var watchOptions = {
  frequency : 1000,
  filter : 1
};

With watchOptions defined, the function makes a call to watchHeading to set up the heading watch as shown here:

watchID = navigator.compass.watchHeading(onSuccess, onError,
  watchOptions);

As with all of the other Cordova APIs you’ve learned so far, the onSuccess function is executed whenever the Compass API sends a heading value, and the onError function is executed whenever there is an error encountered by the Compass API.

Whenever the onSuccess function is executed, the Compass API passes it a heading object that contains properties indicating the device’s current heading as shown here:

{
  "magneticHeading": 39.87841796875,
  "trueHeading": 39.87841796875,
  "headingAccuracy": 0,
  "timestamp": 1416661340676
}

The onSuccess function uses the magneticHeading property of the heading object to determine the current heading, then uses that value to rotate the compass graphic by that number of degrees as shown in this function:

function onSuccess(heading) {
  console.log("Entering onSuccess");
  console.log('Received Heading'),
  console.log(JSON.stringify(heading));
  var hv = Math.round(heading.magneticHeading);
  $('#headingInfo').html('<b>Heading:</b> ' + hv + ' Degrees'),
  console.log('Rotating to ' + hv + ' degrees'),
  $("#compass").rotate(-hv);
  console.log("Leaving onSuccess");
}

Notice that the compass graphic is being rotated in the opposite direction of the device’s current heading. That is because the compass graphic has to rotate in the opposite direction from the device rotation so that the North point on the compass graphic always points to Magnetic North.

Finally, the application’s onError function is executed whenever the watch encounters an error. The function uses an object passed to the function to identify the cause of the error and display an appropriate error message for the user. Notice that the onError function also cancels the watch as it makes little sense to continue watching the heading when the application is not able to measure it.

function onError(err) {
  var msg;
  console.log("Entering onError");
  console.error('Error: ' + JSON.stringify(err));
  //Remove the watch since we're having a problem
  navigator.compass.clearWatch(watchID);
  //Clear the heading value from the page
  $('#headingInfo').html('<b>Heading: </b>None'),
  //Then tell the user what happened.
  switch (err.code) {
  case CompassError.COMPASS_NOT_SUPPORTED:
    msg = 'Compass not supported';
    break;
  case CompassError.COMPASS_INTERNAL_ERR:
    msg = 'Internal compass error';
    break;
  default:
    msg = 'Unknown heading error!';
  }
  console.error(msg);
  navigator.notification.alert(msg, null, "Compass Error", "Continue");
  console.log("Leaving onError");
}

Notice that I’m doing a lot of writing to the console, logging something every time the application enters or leaves a function. This enables me to better understand the flow of the application so I can more easily troubleshoot problems when they occur. As soon as the application is tested and found to be acceptable, I remove or comment out many of the places where the application writes to the console. You can even use capabilities provided by some build tools (described in Chapter 18, “Using Third-Party Tools with Cordova”) to strip console entries out of your application automatically when you switch over from debug to production.

Listing 15.2 shows the complete contents of the application’s index.js file.

Listing 15.2 index.js


var watchID;

window.onerror = function (msg, url, line) {
  var idx = url.lastIndexOf("/");
  if (idx > -1) {
    url = url.substring(idx + 1);
  }
  //Build the message string we'll display to the user
  var errStr = "ERROR in " + url + " (line #" + line + "): " + msg;
  //Write the error to the console
  console.error(errStr);
  //Tell the user what happened
  alert(errStr);
  return false;
};

function onBodyLoad() {
  console.log("Entering onBodyLoad");
  alert("onBodyLoad");
  document.addEventListener("deviceready", onDeviceReady);
  console.log("Leaving onBodyLoad");
}

function onDeviceReady() {
  console.log("Entering onDeviceReady");
  console.log("Cordova: " + device.cordova);
  navigator.notification.alert("Cordova is ready");
  //Set up the watch
  //Read the compass every second (1000 milliseconds)
  var watchOptions = {
    frequency: 1000,
  };
  console.log('Creating watch: %s', JSON.stringify(watchOptions));
  watchID = navigator.compass.watchHeading(onSuccess, onError,
    watchOptions);
  console.log("Leaving onDeviceReady");
}

function onSuccess(heading) {
  console.log("Entering onSuccess");
  console.log('Received Heading'),
  console.log(JSON.stringify(heading));
  var hv = Math.round(heading.magneticHeading);
  $('#headingInfo').html('<b>Heading:</b> ' + hv + ' Degrees'),
  console.log('Rotating to ' + hv + ' degrees'),
  $("#compass").rotate(-hv);
  console.log("Leaving onSuccess");
}

function onError(err) {
  var msg;
  console.log("Entering onError");
  console.error('Error: ' + JSON.stringify(err));
  //Remove the watch since we're having a problem
  navigator.compass.clearWatch(watchID);
  //Clear the heading value from the page
  $('#headingInfo').html('<b>Heading: </b>None'),
  //Then tell the user what happened.
  switch (err.code) {
  case CompassError.COMPASS_NOT_SUPPORTED:
    msg = 'Compass not supported';
    break;
  case CompassError.COMPASS_INTERNAL_ERR:
    msg = 'Internal compass error';
    break;
  default:
    msg = 'Unknown heading error!';
  }
  console.error(msg);
  navigator.notification.alert(msg, null, "Compass Error", "Continue");
  console.log("Leaving onError");
}


Using Merges

One of the things I haven’t done yet is show you how to use the merges capability of the Cordova CLI. In Chapter 5 I explained how it works, but here I’ll show you a real example.

The compass graphic in my original application was pretty lame; I created it in Microsoft Visio and simply wanted a circle with an arrow pointing north. I got what I wanted, but professional grade it wasn’t. For this upgraded version of the application, I wanted something with more panache and found a graphic that, while not technically accurate for my compass, implied a compass theme, so I decided to use it.

To leverage the merges aspect of the CLI, I decided to make two versions of the image, one for Android and the other for iOS, using graphics from the PhoneGap web site placed in the center of the compass face. You can see the Android version in Figure 15.5 and the iOS version in Figure 15.6.

Image

Figure 15.5 Updated Compass Image for Android

Once I had the different graphics, it was time to use them to create distinct versions of the application using the CLI. Notice in the application’s code that the compass image is being pulled from images/compass.png. To enable me to use the CLI and merges, I had to create an images folder in both the Cordova project’s merges/android and merges/ios folders. With those folders in place, all I had to do was copy the right image files to the right folders, making sure they had the same file name.

Image

Figure 15.6 Updated Compass Image for iOS

Assuming my project is in a compass folder, I copied the Android version of the compass image into compass/merges/android/images/compass.png and copied the iOS version into compass/merges/ios/images/compass.png. Since I could run this Cordova application on any supported platform, I left the original lame version of the compass graphic in the Cordova application’s www/images folder so that if the application ran on any platform beyond Android and iOS, it would still display a compass image.

During the build process, for the Android application, the Cordova CLI copies the file located at compass/merges/android/images/compass.png to compass/platforms/android/assets/www/images/compass.png. For the iOS application, the CLI copies the file located at compass/merges/ios/images/compass.png to compass/platforms/ios/www/images/compass.png. In both cases, the copied image overwrites the existing image I have in the project’s www/images folder. For any platform except Android and iOS, the original graphic file is left untouched.

The result of this is that I can still maintain one set of code and only switch in the right resource files as needed depending on the platform. This same approach applies to HTML, CSS, and JavaScript files, and more. Any application resource can be customized using the merges capability.

You can see the results of this process in the next section. The use case I used here isn’t perfect, but I hope you can see how, if you’ve themed your application differently for different platforms, this capability provides you with the means to easily manage the different resources for each platform.

Application Icons

Before I can deploy the fancy new Compass application I just created, I need to make some application icons for each supported platform. Now as this is a book about Apache Cordova and not native application development, I won’t go into the details about how to create application icons and what icon file resolutions are required. That is a topic that should be covered in native development books for each target platform. The Cordova team has done a pretty good job documenting the application icon requirements at http://goo.gl/wY6B3N, so you can find some good information there.

I’m not a graphic artist, I’m simply not wired that way, so I normally have to rely upon others for my application graphics (which is why there are so few of them in this book). Since I knew I needed an icon for this chapter, I fired up Microsoft Visio and created a rough graphic to use here. The graphic is a simple square with rounded corners; then I placed a compass image Visio provided me in the middle of the square with the book’s title underneath it. It’s nothing special, but at least it’s a custom image I can use; you can see the image in Figure 15.7.

Image

Figure 15.7 Compass Application Icon

Now that I had an icon I could use, I started looking for an easy way to convert this image to something I could use for my Cordova application. I quickly found a site called MakeAppicon (http://makeappicon.com); you drag an image file (1024 x 1024 pixels preferred) onto the site, provide an email address, and they will send you an archive with application icons for Android and iOS. Nice stuff.

For a Cordova project designed for multiple platforms, each platform has its own folder structure or project settings for application icons, so I didn’t want to deal with extracting the icons from the MakeAppicon .zip file and copying them into the appropriate place for each target platform. Instead, I started looking for something that was Cordova aware.

A quick search pointed me to several Node-based tools that could generate icons for me, but none of them had been updated in a while and none of them worked very well. A modified search pointed me to the cordova-icon project at http://goo.gl/D47cTz. This one worked quite well for me, although it only provides icon files for Android and iOS.

To use the tool, you must first install ImageMagick using the instructions provided at www.imagemagick.org. Next, you install the cordova-icon Node module using the NPM. On Windows you install the module by opening a terminal window and executing the following command:

npm install –g cordova-icon

On Macintosh and Linux, you may need to install the module using sudo:

sudo npm install –g cordova-icon

To use the module, you need to copy an application icon file to the Cordova project folder as icon.png. Next, in the terminal window, navigate to the Cordova project folder and issue the following command:

cordova-icon

The module will read the project’s config.xml file, determine which platforms are installed for the project, and generate the icon files:

Checking Project & Icon

  Image  platforms found: ios, android
  Image  icon.png exists
  Image  config.xml exists

 Generating Icons for ios

  Image  icon-40.png created
  Image  icon-50.png created
  Image  [email protected] created
  Image  icon-60.png created
  Image  [email protected] created
  Image  [email protected] created
  Image  icon-small.png created
  Image  icon-76.png created
  Image  icon-72.png created
  Image  [email protected] created
  Image  [email protected] created
  Image  [email protected] created
  Image  [email protected] created
  Image  [email protected] created
  Image  icon.png created

 Generating Icons for android

  Image  drawable-hdpi/icon.png created
  Image  drawable-ldpi/icon.png created
  Image  drawable-xhdpi/icon.png created
  Image  drawable/icon.png created
  Image  drawable-mdpi/icon.png created

That’s it; at this point the project has application icons for Android and iOS copied over into the correct locations within the Cordova project structure. For many projects you’ll likely need more than just icons for Android and iOS, but from looking at the code, I don’t think it would be very hard to enhance this module to add support for other platforms.

Testing the Application

With the project all coded and ready to go, it’s time to test the application. I usually start my testing with the device simulators, then switch to physical devices once I get the initial kinks out. So, with a terminal window open to the Compass project, issue the following command:

cordova prepare

The Cordova CLI will copy the web application content from the project’s www folder into each target platform project folder. The content in any merges folders (the compass image in this case) will be copied over to the appropriate project folders as well.

Starting with the Android emulator, in the terminal window execute the following command:

cordova run android

The CLI will churn for a while building the native application for Android, then launch the emulator and display the screen shown in Figure 15.8. That’s nice; the screen looks as I expect it to look, but how do I change the heading?

Image

Figure 15.8 Compass Application Running on an Android Emulator

In the Android Monitor (described in Chapter 7, “Android Development with Cordova”), there’s the Emulator Control option shown in Figure 15.9. There’s an option for simulating geolocation data but not compass heading. Turns out that there’s an Android SensorSimulator application you can run to simulate sensor data on an Android device or emulator. I didn’t try it out, but you can read more about it at http://goo.gl/WY36jB. I have Android devices I can test the application on, so I didn’t worry about that option.

Image

Figure 15.9 Android Monitor Emulator Control Tab

My next step is usually to test the application on an iOS simulator. When I ran the application on an iOS device simulator, the application displayed the error message shown in Figure 15.10.

Image

Figure 15.10 Compass Application Running on an iOS Simulator

The error is being displayed by the application’s onError function, so at least I know that part of the code is working. You can also see the output from the function in the console window in Xcode as shown in Figure 15.11.

Image

Figure 15.11 Application Console Output in Xcode

Well, that’s not good; I can’t test the application on either the Android emulator or iOS simulator. No worries; I have a bevy of devices here, so I’ll test on some of them. To test on an Android device, I connected my Samsung Galaxy SIII to the computer using a USB cable, then in the terminal window issued the following command:

cordova run android

The Cordova CLI will do its stuff, and 30 seconds to a minute later the application will launch on the device. Figure 15.12 shows the application running; I’ve cropped the image to cut away the blank portion of the application screen. Success!

Image

Figure 15.12 Compass Application Running on an Android Emulator

Next, to run the application on an iOS device, connect the device to the computer using a USB cable, then from terminal window, execute the following:

cordova run ios

The CLI will build the application, deploy it to the device, then launch it. As soon as the application starts, it tries to create the compass watch—this could potentially trigger the compass calibration process shown in Figure 15.13.

Image

Figure 15.13 Compass Calibration on an iOS Device

Before the application can use the compass, the device has to be rolled and tilted until the ball sweeps through the entire circle on the screen.

When the application finally loads, it will display a screen similar to the one shown in Figure 15.14; I’ve cropped the image to cut away the blank portion of the application screen.

Image

Figure 15.14 Compass Application Running on an iOS Device

Notice that the compass graphics differ between the two devices (Figures 15.12 and 15.14) although I didn’t code anything to make this happen; this is only one of the cool ways the Cordova CLI enhances cross-platform development.

Now Cordova development is about more than just Android and iOS development, so what about other platforms? To build the application for Windows, you’ll have to create a project on a Windows system and complete most of the steps highlighted here. Microsoft provided me with a test device to use for this book, so I immediately tried the application on that device. Unfortunately, the device I was using didn’t have a compass, so it didn’t work. The good news, though, is that the Device Orientation plugin fired the onError function and let me know the compass wasn’t supported (I had to go online to confirm the device didn’t have a compass).

I grabbed another Windows Phone device and tested the application and it worked great.

I do happen to have a Firefox OS device, so I opened Firefox using the instructions I provided in Chapter 8, “Firefox OS Development with Cordova,” and loaded the application. When I run the application on my device, I see the screen shown in Figure 15.15.

Image

Figure 15.15 Compass Application Running on a Firefox OS Device

Notice the compass graphic; it’s different from the ones shown in Figures 15.12 and 15.14. That’s because I didn’t provide a custom graphic for the Firefox OS platform, only Android and iOS, so any other platform gets the simple graphic from the original version of the application.

I noticed something interesting when I ran the application on the device: the heading did not update on the page, nor did the graphic rotate. I poked and prodded at the app, trying to figure out why it wasn’t working, until I finally figured out that the device didn’t have a compass. I had purchased a very limited-capability Firefox OS phone, and one of the limitations is that it didn’t have a compass.

Remember, though, that I had code in the application that is supposed to let me know when the Compass API returns an error. Well, in the case of Firefox OS, the Device Orientation plugin doesn’t expose that error, so there is no way for my application to know the API won’t work on this particular device.

To confirm this, take a look at Figure 15.16; it shows the console output from the application. As you can see, the application is dutifully creating the compass watch, but nothing happens afterward.

Image

Figure 15.16 Firefox OS Debugging Tools

Clearly some of the device manufacturers, Microsoft and Mozilla in this case, have some work to do on their implementations of the Cordova plugins.

Wrap-Up

This chapter wraps up the Cordova programming story by demonstrating how to do cross-platform Cordova development from start to finish. In this chapter, you saw how to create a single application that uses different resources depending on the mobile platform running the application. I also showed you a complete Cordova web application and described each component. You’ve also seen more details about how to use the Compass API in your applications.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset