Monday, April 30, 2012

GWT RequestFactory and Phonegap

After being asked a lot of times if RequestFactory works with Phonegap, I finally decided to write my answer down.

The short answer is yes, but you need to do one thing.

If you are writing a mobile website with mgwt it works out of the box, of course!
This only applies if you are building apps with gwt-phonegap and RequestFactory as your RPC mechanism.

By default RequestFactory knows the url of your server (the script got loaded from there), but if your script runs inside an app on a phone, it does not know your server. 
To fix this you need to set the RequestTransport for your Factory and give it the url, which would look something like this:


EmployeeRequestFactory factory = GWT.create(EmployeeRequestFactory.class);

DefaultRequestTransport requestTransport = new DefaultRequestTransport();
if(phoneGap.isPhoneGapDevice()){
 requestTransport.setRequestUrl("http://yourserver/rf-servlet");
}
factory.initialize(eventBus, requestTransport);


This is actually all you need to do. This is much easier if you compare it to GWT RPC and Phonegap.
Because it is much harder to configure GWT RPC for Phonegap there are utility methods in GWT Phonegap.

GWT RPC with Phonegap revisited

This post is part of a series of blog post that show the usage of  some mgwt / gwt-phonegap components.

As some of you may know I posted a very popular blog post about a year ago about how to get Phonegap  and GWT RPC working together.

A few weeks ago John Gentillin brought the issue up again on the mgwt user group.

He rightly suggested that this could be fixed by just changing the client and without touching the server at all. So today I decided to revisit the issue and see if I can find a nice way to handle it on the client.

To fix this you need some basic knowledge of how GWT RPC works on the client.
The compiler generates some classes around the RPC interface which do the actual communication.

We need to do two things:
  • set the url for the entry point
  • set the url for the gwt module base

Both parameters are passed with our request and help the server code find the serialization policy. With gwt-phonegap 1.7 I decided to introcude a utility method that handles all those things directly on the client. You just pass in your service, your module url (where you GWT app is deployed) and the relative path to your service.

The code would look like this:

GreetingServiceAsync service = GWT.create(GreetingService.class);
  
PhonegapUtil.prepareService(service, "http://www.yourserver.com/", "greet");


If you want to see how this is implemented take a look here: PhonegapUtilImplDevice.java

There is also an article on RequestFactory & Phonegap. 

Sunday, April 15, 2012

GWT & Phonegap 1.6 - Issues with loading on android

Some of you might be experiencing issues while loading your GWT App in a phonegap environment.

The app might not be starting at all if you are using android 4.x with phonegap and you simply see a white screen instead. A suggested workaround (that many use) is to change to the cross site iframe linker in your gwt compile, which would mean that you would be using a different bootup mechanism for your gwt app. Which is a workaround for this situation and can help, but causes other issues.

So I did a little digging the last weekend and took a close look at the boot load of a GWT app in a phonegap environment. The standard GWT linker creates an iframe in which it loads the content of the GWT Compiler (a html file with javascript). This page is actually what you see in your phonegap app as a blank white page.

By default phonegap on android thinks that all local navigation (urls which start with file://) should be handled by phonegap and should load the url in the browser. This is fine for apps that need navigation like jquerymobile apps, but its not a good idea for GWT apps since it interferes with GWT bootup.

This is what happens in the CordovaWebClient by default:

// If our app or file:, then load into a new Cordova webview container by starting a new instance of our activity.
// Our app continues to run.  When BACK is pressed, our app is redisplayed.
if (url.startsWith("file://") || url.indexOf(this.ctx.baseUrl) == 0 || ctx.isUrlWhiteListed(url)) {
                this.ctx.loadUrl(url);
}


So we need to prevent this by implementing our own web client:


package de.kurka.cordova;

import org.apache.cordova.CordovaWebViewClient;
import org.apache.cordova.DroidGap;
import android.webkit.WebView;

public class GWTCordovaWebViewClient extends CordovaWebViewClient {

public GWTCordovaWebViewClient(DroidGap ctx) {
super(ctx);
}
@Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
       if(url.startsWith("file://"))
       {
       return false;
       }
       
       return super.shouldOverrideUrlLoading(view, url);
       
    }

}

And we need to override the init method of our man activity to use it like this:
package de.kurka.cordova;

import org.apache.cordova.CordovaChromeClient;
import org.apache.cordova.DroidGap;

import android.os.Bundle;
import android.webkit.WebView;

public class HelloCordovaActivity extends DroidGap {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        super.loadUrl("file:///android_asset/www/index.html");
    }
    
    @Override
    public void init() {
    super.init(new WebView(this), new GWTCordovaWebViewClient(this), new CordovaChromeClient(this));
    }
}


This fixes the white screen issue with phonegap 1.6 and GWT apps.


Sunday, April 1, 2012

gwt-phonegap 1.5 released

It's been a while since phonegap was updated to 1.5.0. Due to the change to cordova namespace in javascript I had to make some changes to gwt-phonegap to ensure a correct working version. A new version is now available on google code or from maven central:
<dependency>
      <groupId>com.googlecode.gwtphonegap</groupId>
      <artifactId>gwtphonegap</artifactId>
      <version>1.5.0.0</version>
</dependency>
The release contains an adjusted start up mechanism to fit the new cordova javascript object, as well as some minor bug fixes. This release is the only release working with phonegap 1.5, due to the changed javascript objects.