GraniteDS and AIR for mobile


In this article I will briefly show how to resolve some obstacles I came across when I developed my first application with AIR for mobile and GraniteDS. The most noteworthy reason of using AIR to create mobile applications is of course the multi-platform deployment using a single codebase. Furthermore, with Granite you are able to disclose the services of an existing Java backend to a mobile platform without significant changes to the backend. This offers great potential for enterprises who are struggling with the fragmented mobile market and don’t want to completely rewrite their existing Java backend.

I will assume you have some familiarity with AIR for mobile and Granite. It’s mostly the same as for Flex but there are some things you have to take into account.

1. Get the right version of Granite

The latest version of Granite is 2.2.1 GA. However, in the most recent version of AIR and Flex Adobe made some changes in the API which breaks backwards compatibility for some features of Granite. Therefore this release of Granite won’t work using the newest SDK. Refer to this post on the Granite form for more info on how to make these changes yourself. If you don’t want be bothered with building Granite yourself just download this version of GraniteDS to get started immediately.

2. Connecting to the right server

A problem for AIR applications in general (both desktop and mobile) is setting the right server settings. It is quite simple when running within the browser: The server address is changed with a single reconfiguration of the swf-file and all clients are using the new address on a browser refresh. With AIR it is a bit different and you’re not always at liberty to ‘hardcode’ the service settings in the AIR distribution package.
Granite offers a method for dynamic server configuration using the server initializer component:

Tide.getInstance().addComponentWithFactory(
  "serviceInitializer",
  DefaultServiceInitializer, {
    contextRoot: '/my-app',
    serverName: “10.0.0.1”,
    serverPort: “8080});

Note that once a connection is made, it is not possible to reconnect with another configuration, because the service initializer is only used once. You have to restart the application to enable the new connection settings or reset Tide’s RemoteObject. Unfortunately Tide’s API doesn’t support this reset. I came up with a small workaround which requires you to extend the EJB class with an extra reset method with the following body:

public class Ejb extends org.granite.tide.ejb.Ejb {
  /**
   * Reset the Tide Connection to allow new server settings
   */
  public function resetConnection():void {
    if (_ro) {
      _ro.disconnect();
    }
    _ro = null;
  }
 
}

This method resets Tide’s RemoteObject so the next remote call will force a reinitialization using the current settings of serviceInitializer. Refer to Granite’s issue tracker or forum thread for more details.

3. Automatic logout

Applications running on mobile platforms are always susceptible to unpredictable interruptions. For example when a phone call or text is received. Mobile AIR applications provide a deactivate event which is dispatched when the application is halted somehow. The application I wrote was using Tide’s Identity class for user login. Therefore I added an event handler to automatically logout the user and push the LoginView on top of the navigator stack:

private function deactivateHandler(event:Event):void {
  if (identity.loggedIn) {
    identity.logout();
  }
  navigator.popAll(); // Purge the navigator history to disable back button usage
  navigator.pushView(LoginView);
}

4. Build, build, build!

This isn’t directly related to Granite or AIR for mobile. But since they can both be used for enterprise scale applications I thought I’d mention it shortly: Make sure you have a proper build script. Now, I’ve got an example from Chris Black which provides a good starting point. I’ve only added the metadata compiler options required for Tide and of course a reference to the Granite libraries and generated Actionscript classes.

 
 <mxmlc ... >
 
  <!-- .... -->
 
  <!-- location of generated as classes with gas3 -->
  <source-path path-element="${gen.src.dir}" />
 
  <compiler.library-path dir="${basedir}/libs" append="true">
    <include name="granite-essentials.swc" />   
    <include name="granite.swc" />
  </compiler.library-path>
 
  <keep-as3-metadata name="Bindable" />
  <keep-as3-metadata name="ChangeEvent" />
  <keep-as3-metadata name="Destroy" />
  <keep-as3-metadata name="Id" />
  <keep-as3-metadata name="In" />
  <keep-as3-metadata name="Inject" />
  <keep-as3-metadata name="Managed" />
  <keep-as3-metadata name="ManagedEvent" />
  <keep-as3-metadata name="Name" />
  <keep-as3-metadata name="NonCommittingChangeEvent" />
  <keep-as3-metadata name="Observer" />
  <keep-as3-metadata name="Out" />
  <keep-as3-metadata name="PostConstruct" />
  <keep-as3-metadata name="Transient" />
  <keep-as3-metadata name="Version" />
 
</mxmlc>

One plus one

I can imagine one must be thinking: ‘Everyone could have figured that out!’ And I totally agree, because that’s exactly what this article is about. With some experience with Flex, a developer can write a mobile application on top of a Java EE backend. It doesn’t take much to utilize an existing backend from a mobile platform. Since the latest release of AIR the performance for iOS and Android is pretty good and together with the Granite Enterprise Platform the barrier to emerge an enterprise application to a mobile platform has become much lower.

, , , , , , ,

  1. #1 door marc slack om 27 oktober 2011

    thanks for the article … the part i am stuck on is how all the configuration information is picked up when building a mobile app. When using granite in the context of a web app the services-config and the granite-config define the AMF channel, etc.

    Building a Mobile app with Granite does not have a Web-inf so how do you set up this config information>

    My tide is not initializing properly as Ejb.getInstance() is null.

    willing to post your project framework?

  2. #2 door Walter Treur om 1 november 2011

    The mobile client doesn’t have any special configuration, since we use a runtime setup for connecting to the server.

    The server part is configured just like you would do when creating a normal Flex web application using Granite.
    I suggest you take a look at HelloWorld sample in the Granite documentation. It describes all the necessary steps from client to server to setup a working configuration. Especially the sample ant build script where the war is build should be helpful: http://www.graniteds.org/confluence/pages/viewpage.action?pageId=16875661

(wordt niet gepubliceerd)
  1. Nog geen trackbacks.