Chapter 46

PhoneGap

PhoneGap is perhaps the original alternative application framework for Android, arriving on the scene in early 2009. PhoneGap (www.phonegap.com/) is open source, backed by Nitobi, which traditionally offered a mix of open source and commercial products, along with consulting and training services. As of October 2011, Nitobi had agreed to be acquired by Adobe. To ensure the longevity of the PhoneGap code, Nitobi submitted the PhoneGap code base to the Apache Software Foundation, where the project is now named Apache Callback. Most people still know the project by its original name, and much of the documentation still refers to PhoneGap, so we'll stick to the traditional name.

What Is PhoneGap?

PhoneGap is a platform built around HTML5 that enables you to develop apps from one code base and deploy them to multiple platforms. Using PhoneGap is as easy as following these steps:

  1. Build your application using web standard languages such as HTML5 and JavaScript.
  2. Wrap your application with PhoneGap to gain access to native APIs.
  3. Deploy your application to multiple platforms.

Read more about PhoneGap and how it works at www.phonegap.com/about.

What Do You Write In?

A PhoneGap application is made up of HTML, CSS, and JavaScript, no different from a mobile web site or HTML5 application, except that in PhoneGap the web assets are packaged with the application rather than downloaded on-the-fly.

A preinstalled PhoneGap application, therefore, can contain comparatively large assets, such as complex JavaScript libraries, that might be too slow to download over slower EDGE connections. However, PhoneGap is still limited by the speed of mobile devices and how quickly the WebKit browser can load and process those assets.

Also, development for WebKit for mobile differs from development for WebKit for desktops, particularly with respect to touch versus mouse events. You may want to develop using mobile layers of JavaScript frameworks (e.g., jQTouch versus plain jQuery) where practical.

What Features Do You Get?

As with an HTML5 application, PhoneGap gives you the basic capabilities of a web browser, including AJAX support. Beyond that, PhoneGap adds a number of JavaScript APIs to allow you to get at the underlying features of the Android platform. At the time of this writing, that includes the following:

  • Accelerometer access, for detecting movement of the device
  • Audio recording
  • Camera access, for taking still pictures
  • Compass access, for orientation-based activities
  • Contacts access, for working with the built-in contacts provider
  • Database access, both to databases that you create (SQLite) and to others built into Android (e.g., contacts)
  • File system access, such as to the SD card or other external storage
  • Geolocation, for determining where the device is
  • Notification services, including alerts and sound effects
  • Storage, both on-device and SD card
  • Vibration, for shaking the phone (e.g., force-feedback)

Since some of these are part of the HTML5 specification (e.g., geolocation), you have your choice of APIs. Also, this list will change over time, but you'll see that the preceding list is a pretty comprehensive list of the native features on most contemporary Android devices.

What Do Apps Look Like?

PhoneGap apps look like web pages, more so than native Android apps, as shown in Figure 46–1, a screenshot of the example application that ships with PhoneGap. You can use CSS and images to mimic the Android look and feel to some extent, but only for those sorts of widgets that can be created in both Android and HTML. For example, the Android Spinner widget, which resembles a drop-down list, may be difficult to mimic in HTML.

images

Figure 46–1. The example application that comes with PhoneGap

How Does Distribution Work?

Distributing a PhoneGap application is pretty much identical to distributing any other standard Android application, with some additional options available. Using stand-alone PhoneGap, after testing, you create a standard APK file with the Android build tools, from an Android project generated for you by PhoneGap. This project will contain the Java, XML, and other necessary bits to wrap around your HTML, CSS, and JavaScript to make up your application. Then, you digitally sign the application and upload it to the Android Market or any other distribution mechanism you wish to use. Nitobi also makes available a hosted build service, called PhoneGap Build, which we'll discuss a bit later in the chapter.

What About Other Platforms?

PhoneGap is not just for Android. You can create PhoneGap applications for iPhone, Blackberry, some flavors of Symbian, Microsoft Windows Phone, Samsung Bada, and Palm's WebOS. In theory, at least, you can create one application using HTML, CSS, JavaScript, and the PhoneGap JavaScript APIs, and have it run across many devices.

There are a couple of limitations that will hamper your progress to that goal:

  • The web browsing component used by PhoneGap across all those platforms is not identical. Even multiple platforms using WebKit will have different WebKit releases, based on what was available when WebKit was integrated into a given device's firmware. Hence, you will want to test to ensure that your CSS, in particular, works as you expect on as many devices as possible.
  • Not all PhoneGap JavaScript APIs are available on all devices yet, due to a variety of factors (e.g., not exposed in the platform's native APIs, lack of engineering time to hoist the capability into the PhoneGap APIs, etc.). The PhoneGap wiki can keep you apprised of what works and what does not across the devices. You will want to restrict your feature use to match your desired platforms, or restrict your platforms to match your desired features.

Using PhoneGap

Now, let's look at more of the mechanics for using PhoneGap. PhoneGap's installation and usage, as of the time of this writing, normally requires an expert in Java-based Android development. You need to install a whole bunch of tools, edit configuration files by hand, and so forth. If you want to do all of that, documentation is available on the PhoneGap web site and we'll cover it briefly below. If you are reading this chapter, there's a decent chance that you would rather skip all of that. Once again, you can use the PhoneGap Build service (http://build.phonegap.com/), which we'll cover shortly.

Installation

You can download the latest PhoneGap tools as a ZIP archive from the PhoneGap web site, which acts as a redirect to the Apache Callback incubator repository at the Apache Software Foundation. Unpack those tools wherever it makes sense for your development machine and platform. For Android development, that is all the PhoneGap-specific installation you will need. However, you will need the Android SDK and related tools (e.g., Eclipse, if you wish to use Eclipse) for setting up the project.

Creating and Installing Your Project

A PhoneGap Android project is, at its core, a regular Android project, which you can create following the instructions outlined earlier in this book. To convert the standard generated “Hello, World” application into a PhoneGap project, you need to do the following:

  1. From the Android/ directory of wherever you unzipped the PhoneGap ZIP file, copy the PhoneGap JAR file to the libs/ directory of your project. If you are using Eclipse, you also need to add it to your build path.
  2. Create an assets/www/ directory in your project. Then, copy over the PhoneGap JS file from the Android/ directory of wherever you unzipped the PhoneGap ZIP file.
  3. Adjust the standard “Hello, World” activity to inherit from DroidGap instead of Activity. This requires you to import com.phonegap.DroidGap.
  4. In your activity's onCreate() method, replace setContentView() with super.loadUrl("file:///android_asset/www/index.html");.
  5. In your manifest, add all the permissions that PhoneGap requests, listed later in this chapter.
  6. Also in your manifest, add a suitable <supports-screens> element based on what screen sizes you want to test and support.
  7. Also in your manifest, add android:configChanges="orientation|keyboardHidden" to your <activity> element, as DroidGap handles orientation-related configuration changes.

At this point, you can create an assets/www/index.html file in your project and start creating your PhoneGap application using HTML, CSS, and JavaScript. You need to include a reference to the PhoneGap JavaScript file (e.g., <script type="text/javascript" charset="utf-8" src="phonegap.1.2.0.js" />). When you want to test the application, you can build and install it like any other Android application (e.g., ant clean install if you are using the command-line build process).

For somebody experienced in Android SDK development, setting this up is not a big challenge.

PhoneGap Build

PhoneGap Build is a tools-as-a-service (TaaS) hosted approach to creating PhoneGap projects. All of the Android build process is handled for you by PhoneGap-supplied servers. You just focus on creating your HTML, CSS, and JavaScript as you see fit.

When you log into PhoneGap Build, you are first prompted to create your initial project, by supplying a name and the web assets to go into the app, as shown in Figure 46–2.

images

Figure 46–2. Creating your first project in PhoneGap Build

You will be able to add new projects later via a New App button, which gives you the same set of options.

Your choices for supplying the assets are to upload a ZIP file containing all of them or to specify the URL to a public GitHub repository that PhoneGap Build can pull from. The latter method tends to be more convenient, if you are used to using Git for version control and your project is open source (and therefore has a public repository).

Once you click the Upload button, the PhoneGap Build server immediately starts building your application for Android, plus Blackberry, Symbian, and the other supported platforms, or platforms you have chosen, as shown in Figure 46–3.

images

Figure 46–3. Building your first project in PhoneGap Build

Each of the targets has its own file extension (e.g., apk for Android). Clicking that link will let you download that file. Or, click the name of the project, and you get Quick Response (QR) codes to enable downloads straight to your test device, as shown in Figure 46–4.

images

Figure 46–4. Your project's QR codes in PhoneGap Build

This page also gives you a link to update the app from its GitHub repository (if you chose that option). Or, you can click Edit to specify more options, such as the version of your application or its launcher icon, as shown in Figure 46–5.

images

Figure 46–5. Your project's settings in PhoneGap Build

All in all, if you do not otherwise need the Android SDK and related tools on your development machine, PhoneGap Build certainly simplifies the PhoneGap building process.

Nitobi launched PhoneGap Build as a commercial service for non–open source applications, with rates available from the PhoneGap Build web site.

PhoneGap and the Checklist Sample

The beauty of PhoneGap is that it wraps around HTML, CSS, and JavaScript. In other words, you do not have to do much of anything PhoneGap-specific to be able to take advantage of PhoneGap delivering to you an APK suitable for installation on an Android device. That being said, PhoneGap does expose more stuff to you than you can get from the standards, if you need them and are willing to use proprietary PhoneGap APIs for them.

Sticking to the Standards

Given an existing HTML5 application, all you need to do to make it an installable APK is wrap it in PhoneGap. For example, to convert the HTML5 version of Checklist (from Chapter 45) into an APK file, you need to do the following:

  1. Follow the steps to create an empty PhoneGap project, as outlined earlier in this chapter.
  2. Copy the HTML, CSS, JavaScript, and images from the HTML5 project into the assets/www/ directory of the PhoneGap project (note that you do not need anything unique to HTML5, such as the cache manifest).
  3. Make sure that your HTML entry point file name matches the path you used with the loadUrl() call in your activity (e.g., index.html).
  4. Add a reference to the PhoneGap JavaScript file from your HTML.
  5. Build and install the project.

Here is the DroidGap activity for our app, from the PhoneGap/Checklist project:

package com.commonsware.pg.checklist;

import android.app.Activity;
import android.os.Bundle;
import com.phonegap.DroidGap;

public class Checklist extends DroidGap {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    super.loadUrl("file:///android_asset/www/index.html");
  }
}

Here is the manifest, with all of the PhoneGap-requested settings added:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.commonsware.pg.checklist"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:label="@string/app_name" android:icon="@drawable/cw">
        <activity android:name="Checklist"
                  android:configChanges="orientation|keyboardHidden"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    <supports-screens
        android:largeScreens="true"
        android:normalScreens="true"
        android:smallScreens="true"
        android:resizeable="true"
        android:anyDensity="true"
    />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.RECEIVE_SMS" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.WRITE_CONTACTS" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>

And here is the HTML, which is almost identical to the HTML5 original, but with some HTML5 offline stuff removed (e.g., iPhone icons) and the reference to PhoneGap's JavaScript file added:

<!DOCTYPE html>
<html lang="en" manifest="checklist.manifest">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Checklist</title>
    <meta name="viewport"
      content="width=device-width; initial-scale=1.0; maximum-scale=1.0;
 user-scalable=0;" />
    <link rel="stylesheet" href="styles.css" />
    <script type="text/javascript" charset="utf-8" src="phonegap.1.2.0.js"></script>
</head>
<body>
    <section>
        <header>
          <button type="button" id="sendmail">Mail</button>
          <h1>Checklist</h1>
        </header>
        <article>
          <form id="inputarea" onsubmit="addNewItem()">
              <input type="text" name="name" id="name" maxlength="75"
                     autocorrect placeholder="Tap to enter a new item&hellip;" />
              <button type="button" id="add">Add</button>
            </form>
            <ul id="maillist">
            <li class="empty"><a href="" id="maillink">Mail remaining items</a></li>
          </ul>
            <p id="totals"><span id="tally1">Total: <span id="total">0</span></span>
            <span id="tally2">Remaining: <span id="remaining">0</span></span></p>
          <ul id="checklist">
            <li class="empty">Loading&hellip;</li>
          </ul>
        </article>
        <fieldset>
          <button type="button" id="deletechecked">Delete Checked</button>
          <button type="button" id="deleteall">Delete All</button>
        </fieldset>
    </section>
    <script src="main.js"></script>
</body>
</html>

For many applications, this is all you will need. You are simply looking at PhoneGap to give you something you can distribute on the Android Market, on the iOS App Store, and so on.

Adding PhoneGap APIs

If you want to take advantage of more device capabilities, you can augment your HTML5 application to use PhoneGap-specific APIs. These run the gamut from telling you the device's model to letting you get compass readings. Hence, their complexity will vary. For the purposes of this chapter, we will look at some of the simpler ones.

Set Up Device-Ready Event Handler

For various reasons, PhoneGap will not be ready to respond to all of its APIs right away when your page is loaded. Instead, you need to look for a deviceready event to confirm that it is safe to use PhoneGap-specific JavaScript globals. The following is the typical recipe:

  1. Add an onload attribute to your <body> tag, referencing a global JavaScript function (e.g., onLoad()).
  2. In onLoad(), use addEventListener() to register another global JavaScript function (e.g., onDeviceReady()) for the deviceready event.
  3. In onDeviceReady(), start using the PhoneGap APIs.
Use What PhoneGap Gives You

PhoneGap makes a number of methods available to you through a series of virtual JavaScript objects. Here, “virtual” means that you cannot check to see if the objects exist, but you can call methods and read properties on them. So, for example, there is a device object that has a handful of useful properties, such as phonegap to return the PhoneGap version and version to return the OS version. These virtual objects are ready for use in or after the deviceready event.

For example, here is a JavaScript file (props.js from the PhoneGap/ChecklistEx project) that implements an onLoad() function (to register for deviceready) and an onDeviceReady() function (to use the device object's properties):

// PhoneGap's APIs are not immediately ready, so set up an
// event handler to find out when they are ready

function onLoad() {
  document.addEventListener("deviceready", onDeviceReady, false);
}

// Now PhoneGap's APIs are ready

function onDeviceReady() {
  var element=document.getElementById('props'),

  element.innerHTML='<li>Model: '+device.name+'</li>' +
                    '<li>OS and Version: '+device.platform +' '+device.version+'</li>' +
                    '<li>PhoneGap Version: '+device.phonegap+'</li>';
}

The onDeviceReady() function needs a list element with an id of props. That, plus loading this JavaScript in the first place, will require some minor modifications to our HTML:

<!DOCTYPE html>
<html lang="en" manifest="checklist.manifest">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Checklist</title>
    <meta name="viewport"
      content="width=device-width; initial-scale=1.0; maximum-scale=1.0;
 user-scalable=0;" />
    <link rel="stylesheet" href="styles.css" />
    <script type="text/javascript" charset="utf-8" src="phonegap.1.2.0.js"></script>
    <script type="text/javascript" charset="utf-8" src="props.js"></script>
</head>
 <body onload="onLoad()">
    <section>
 <header>
 <button type="button" id="sendmail">Mail</button>
 <h1>Checklist</h1>
 </header>
 <article>
    <form id="inputarea" onsubmit="addNewItem()">
    <input type="text" name="name" id="name" maxlength="75"
                  autocorrect placeholder="Tap to enter a new item&hellip;" />
    <button type="button" id="add">Add</button>
  </form>
  <ul id="maillist">
    <li class="empty"><a href="" id="maillink">Mail remaining items</a></li>
  </ul>
  <p id="totals"><span id="tally1">Total: <span id="total">0</span></span>
        <span id="tally2">Remaining: <span id="remaining">0</span></span></p>
  <ul id="checklist">
    <li class="empty">Loading&hellip;</li>
  </ul>
 </article>
 <fieldset>
  <button type="button" id="deletechecked">Delete Checked</button>
  <button type="button" id="deleteall">Delete All</button>
 </fieldset>
    <footer>
        <h2>Device Properties</h2>
        <ul id="props"></ul>
    </footer>
    </section>
    <script src="main.js"></script>
 </body>
</html>

Figure 46–6 shows what the resulting app looks like.

images

Figure 46–6. The PhoneGap Checklist application with device properties

Obviously, reading a handful of properties is far simpler than, say, taking a picture with the device's camera. However, the difference in complexity is mostly in what PhoneGap's virtual JavaScript objects give you and how you can use them, more so than anything peculiar to Android.

Issues You May Encounter

PhoneGap is a fine choice for creating cross-platform applications. However, it is not without its issues. Some of these issues may be resolved in time; some may be endemic to the nature of PhoneGap.

Security

Android applications use a permission system to request access to certain system features, such as making Internet requests or reading the user's contacts. Applications must request these permissions at install time, so the user can elect to abandon the installation if the requested permissions seem suspect.

A general rule of thumb is that you should request as few permissions as possible, and make sure that you can justify why you are requesting them.

PhoneGap, for a new project, requests quite a few permissions:

  • CAMERA
  • VIBRATE
  • ACCESS_COARSE_LOCATION
  • ACCESS_FINE_LOCATION
  • ACCESS_LOCATION_EXTRA_COMMANDS
  • READ_PHONE_STATE
  • INTERNET
  • RECEIVE_SMS
  • RECORD_AUDIO
  • MODIFY_AUDIO_SETTINGS
  • READ_CONTACTS
  • WRITE_CONTACTS
  • WRITE_EXTERNAL_STORAGE
  • ACCESS_NETWORK_STATE

Leaving this roster intact will give you an application that can use every API that PhoneGap makes available to your JavaScript...and an application that will scare away many users. After all, it is unlikely that your application will be able to use, let alone justify, all of these permissions.

It is certainly possible for you to trim down this list, by modifying the AndroidManifest.xml file in the root of your PhoneGap project. However, you will then need to thoroughly test your application to make sure you did not get rid of a permission that you actually need. Also, it may be unclear to you which permissions you can safely remove.

Eventually, the PhoneGap project may have tools to help guide you in the choice of permissions, perhaps by statically analyzing your JavaScript code to see which PhoneGap APIs you are using. In the meantime, though, getting the proper set of permissions will involve a lot of trial and error.

Screen Sizes and Densities

Normal web applications primarily focus on screen resolution and window sizes as their primary variables. Mobile web applications do not have to worry about window sizes, as browsers and apps typically run full-screen. Mobile web applications need to deal with physical size and density, though—issues that are off the radar for traditional web development.

Netbooks can have screens that are 10 inches or smaller, whereas desktops can have screens that are 24 inches or larger. So physical screen size would seem to be something web developers need to address. However, screen resolution (in pixels) generally tracks well with physical size in the netbook/notebook/desktop realm. That is because screen density is fairly consistent across their LCDs, and that density is fairly low.

Smartphones, on the other hand, have several different densities, causing the connection between resolution and size to be broken. Some low-end phones, particularly with small (e.g., 3 inch) LCDs, have densities on par with nice monitors. Midrange phones have twice the density (240 dpi versus 120 dpi). Apple's iPhone 4 has even higher density, and there likely will soon be some Android devices with so-called retina displays as well. Hence, an 800×480 resolution could be on a screen ranging anywhere from 4 inches to 7 inches, for example. Tablets add even more possible sizes to the mix.

This is compounded by the problems caused by touchscreens. A mouse can get pixel-level precision in its clicks. Fingers are much less precise. Hence, you may need to make your buttons and such bigger on a touchscreen, so that it is finger-friendly. This causes some problems with scaling of assets, particularly images. What might be finger-friendly on a low-density 3-inch device might be entirely too small for a high-density 4-inch device.

Native Android applications have built-in logic for dealing with this issue, in the form of multiple sets of resources (e.g., images) that can be swapped in based on device characteristics. Eventually, PhoneGap and similar tools will need to provide relevant advice to their users for how to create applications that can similarly adapt to circumstances.

Look and Feel

A web app never quite looks like a native one. This is not necessarily a bad thing. However, some users may find it disconcerting, particularly since they will not understand why their newly installed app (made with PhoneGap, for example) looks so different from any other similar app they may already have.

As HTML5 applications become more prominent on Android, this issue should decline in importance. However, it is something to keep in mind. If you are creating your own graphic elements (icons, etc.) you will almost certainly benefit from using Android Asset Studio, covered in Chapter 43, to take on some of the chores: crafting icons in the necessary sizes, creating web images sympathetic to your icon and other styles, and so forth.

For More Information

At the time of this writing, there are no books available dedicated to PhoneGap development. At the moment, the best information on PhoneGap can be found on the PhoneGap web site, including its API documentation, and in a number of other publicly available tutorials on other web sites.

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

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