Open Source Software Technical Articles

Want the Best of the Wazi Blogs Delivered Directly to your Inbox?

Subscribe to Wazi by Email

Your email:

Connect with Us!

Current Articles | RSS Feed RSS Feed

Create mobile apps easily with GWT and PhoneGap

  
  
  

By using both GWT and PhoneGap, you can write portable, interactive mobile applications that can interact with your device's hardware. This article shows you how to use the two tools in tandem.

 


 

If you're planning to write a mobile application, a couple of development tools stand out. Google Web Toolkit (GWT) is well-known for enabling developers to build modern, highly interactive web applications. It work with Java and uses Eclipse for development. Meanwhile, PhoneGap (now Apache Cordova) can take any web application and directly build a mobile application out of it, ready for Android, iOS, and other platforms. To get the best of both worlds, use these tools together. Let's go over the basic steps needed for such a marriage, which, though not overtly difficult, has some few points to work out.

I'll assume you're working with the latest versions of all the software: Eclipse Kepler, GWT 2.5.1, and PhoneGap 2.9.0. For testing, I'm using Chrome – a good option because it's basically the same browser that runs on an Android smartphone. To test the software you also need the latest Android SDK. Installation procedures for each application are detailed on the projects' sites.

Though you can build the smartphone applications on your own, the simplest way to produce and distribute your app is by means of the PhoneGap Build service. With it, you just upload your source code, and the service automatically generates the necessary app files for end users to download. Get yourself an account; we'll be using it in this article.

A sample GWT application

To get started, use Eclipse to build a GWT project. Check the "Generate project sample code" box to get a fully functioning sample GWT application, including a server-side service. I named my project WaziGwt, and packaged it as com.kereki.wazigwt. Run the application to verify everything is correct; you should get a screen with a text field and a button, and upon clicking the latter, you should get some text results from the server.

The standard GWT sample application, which we'll turn into a smartphone app through PhoneGap
The standard GWT sample application, which we'll turn into a smartphone app through PhoneGap

Now, let's change some details. The PhoneGap Build service expects the main page of your application to be called index.html, so rename the WaziGwt/war/WaziGwt.html file to index.html. Edit the WaziGwt/war/WEB-INF/web.xml file and make the welcome-file point to the newly named file.

When you compile the GWT application, it generates specific versions for all web browsers, including Chrome, Firefox, and Internet Explorer, but PhoneGap just requires the Safari (Chrome) one. You can speed development time by editing the WaziGwt.gwt.xml configuration file and adding the line <set-property name="user.agent" value="safari" /> to it, so GWT will just produce just a single version of the final code. On the next compilation, you'll see messages similar to the following, showing that a single version of the code was produced.

Compiling module com.kereki.wazigwt.WaziGwt
   Compiling 1 permutation   Compiling permutation 0...
   Compile of permutations succeeded
Linking into /home/fkereki/workspace/WaziGwt/war/wazigwt
   Link succeeded
   Compilation succeeded -- 20.022s

Next you should test your application, which implies deploying the compiled GWT code to Apache Tomcat. A make script or Apache Ant job could do that, but using symlinks is easier. In your Tomcat deployment directory (for openSUSE it's /srv/tomcat7/webapps/WaziGwt but paths vary among distributions; for CentOS it could be /usr/tomcat7/webapps/WaziGwt, for example) add a META-INF directory, and within it a content.xml file with the contents below, so Tomcat will follow symlinks, which by default it won't do. Then add symlinks from the Tomcat deployment directory to all files and directories at the top level of the war directory in the Eclipse workspace, and you'll be set.

<?xml version="1.0" encoding="UTF-8"?>
<Context override="true" allowLinking="true"> </Context>

If all went well, you should be able to open http://127.0.0.1:8080/WaziGwt/index.html in your browser and see your sample application. We're not done with GWT code changes, but let's get the PhoneGap part of our application going, then come back and put everything together.

Preparing the PhoneGap side

To use PhoneGap, we have to set up a project, then get it into Eclipse. Go to the Eclipse workspace directory and execute the commands below. The first command is for Android SDK configuration. The next three create a basic PhoneGap project, with Android support included. The last two build and run the sample project itself.

> export PATH=${PATH}:~/bin/android-sdk-linux/tools:~/bin/android-sdk-linux/platform-tools
> cordova create WaziPhoneGap com.kereki.waziPhoneGap WaziPhoneGap
> cd WaziPhoneGap/
> cordova platform add android
> cordova build
> cordova emulate android

Now go back to Eclipse, go to File -> New -> Other -> Android -> Android Project from existing code, and select the just created /home/fkereki/workspace/WaziPhoneGap project. Leave the "Import into workspace" checkbox cleared, since the project already resides there. To verify that everything is right so far, try to "Run As..." "Android Application"; you should get a screen as below.

A basic PhoneGap project, which we'll connect to GWT
A basic PhoneGap project, which we'll connect to GWT

Now you have a GWT project and a PhoneGap project. If you link them up, the latter will use the GWT-generated files, and you'll be home!

Getting GWT and PhoneGap to work together

Modify the index.html file to include the code below, just before the <script type="text/javascript" language="javascript" src="wazigwt/wazigwt.nocache.js"></script> line. This code processes the "device ready" PhoneGap event, which lets your application know that everything is set up and you can start using PhoneGap functions.

<script type="text/javascript">
  var app = { cordovaReady : false;          
    initialize: function() {   
      document.addEventListener('deviceready', this.onDeviceReady, false);   
     // other events: "load", "offline", "online" },

     onDeviceReady: function() {   
       app.cordovaReady = true;   
       console.log("onDeviceReady event"); },
     };
  app.initialize();
</script>

You also need to copy some files from the PhoneGap assets/www directory to the GWT war directory: copy config.xml, cordova_plugins.js, cordova_plugins.json, and cordova.js. The latter file should be renamed phonegap.js because that's what the PhoneGap Build system expects. After having done all this, remove the ~/workspace/WaziPhoneGap/platforms/android/assets/www file, and substitute a symlink to $HOME/workspace/WaziGWT/war instead. The complete sequence of commands is as follows.

> cd $HOME/workspace/WaziPhoneGap/platforms/android/assets
> cp www/config.xml $HOME/workspace/WaziGwt/war/
> cp www/cordova_plugins.js $HOME/workspace/WaziGwt/war/
> cp www/cordova_plugins.json $HOME/workspace/WaziGwt/war/
> cp www/cordova.js $HOME/workspace/WaziGwt/war/phonegap.js
> rm -rf www
> ln -s $HOME/workspace/WaziGwt/war www

If you were to build and install the application as is, in some versions of Android you might get a blank screen, because the URL for your application starts with file://. Fortunately, Daniel Kurka provides a solution at his blog; add the following code to override the init() method in the src/WaziPhoneGap.java file:

@Override
public void init() {
  super.init(
    new CordovaWebView(this), 
    new CordovaWebViewClient(this) 
    { 
      @Override 
      public boolean shouldOverrideUrlLoading(WebView view, String url) {   
        return url.startsWith("file://")? false: super.shouldOverrideUrlLoading(view, url); }
      }, 
    new CordovaChromeClient(this));
}

We still have one final problem to solve. If you compile (in GWT) and run (with PhoneGap) the application, when you click on "Send," instead of the expected message, you'll get an error. Why? The hitch is that typically you run a GWT application by opening a URL, from which the application is downloaded to your browser. With PhoneGap, the application really resides in the smartphone. When GWT tries to call the remote service at the server, it examines the current URL and decides that the server is at the smartphone. The fix, also provided by Daniel Kurka, hinges upon dynamically changing the service proxy. Run the code below in your GWT application before attempting to use RPC; MY_HOST and MY_PATH should refer to your server.

final String MY_HOST= "http://192.168.1.200";
final String MY_PATH= "/WaziGwt";

if (GWT.getHostPageBaseURL().startsWith("file://")) {
  final String newUrl= GWT.getModuleBaseURL().replace("file:///android_asset/www", MY_HOST + ":8080" + MY_PATH);

  ((ServiceDefTarget) greetingService).setServiceEntryPoint(newUrl + ((ServiceDefTarget) greetingService).getServiceEntryPoint().replace(GWT.getModuleBaseURL(), ""));

  ((ServiceDefTarget) greetingService).setRpcRequestBuilder(new RpcRequestBuilder() { 
    @Override protected void doFinish(RequestBuilder rb) {   
      super.doFinish(rb);   
      rb.setHeader(MODULE_BASE_HEADER, newUrl); 
    }
  });
} 

Now, if you compile the application and run it with PhoneGap, it will perform perfectly. Finally, building the application is simplicity itself. Just zip the complete contents of the assets/www directory, excluding WEB-INF (which is meant for Tomcat) and phonegap.js (which the build service will provide by itself), upload it to the PhoneGap build service, and wait a while; you are done!

In conclusion

We have seen how to make GWT and PhoneGap work together, and built a basic sample application for smartphones. Next time we will go further, delving into the PhoneGap APIs, to see how to work with the smartphone features so your app can really behave like a native one, interacting with the smartphone, accessing GPS and contacts, making phone calls, storing data locally, and more.




This work is licensed under a Creative Commons Attribution 3.0 Unported License
Creative Commons License.

Comments

Mind to add the word 'slow' to the article's title.
Posted @ Wednesday, July 31, 2013 2:36 AM by Tiago Franco
Some people consider phonegap to be a slow tool, but I think it totally depends on the developer and the language. You can seamlessly generate apps for different mobile platforms using one single code base. This tool is quite easy to use.
Posted @ Thursday, August 08, 2013 6:53 AM by PhoneGap Developers
This is an excellent article. Is there any reason why why the above suggested approach for RPC calls would not work in the following scenario? 
GWT 2.5.1 
Cordova 3.3 
Android Platform(Simulated) using Android SK 
 
My RPC calls are failing with StatusCodeException=0. No explanation. 
 
Appreciate any suggestions 
Posted @ Thursday, January 02, 2014 12:11 PM by Mohan
Post Comment
Name
 *
Email
 *
Website (optional)
Comment
 *

Allowed tags: <a> link, <b> bold, <i> italics