Browse DevX
Sign up for e-mail newsletters from DevX


Automate Your J2ME Application Porting with Preprocessing : Page 2

Got porting nightmares? If you're considering automating the porting your J2ME applications, you may want to think about using a preprocessor. Find out why it's the only technique open-ended enough to handle porting to multiple device models.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

In-house Porting Solutions
So, you've decided you do need to automate porting your application. Sure, you could outsource it, but if you're thinking about doing it in-house, you've basically got four methods from which to choose.
  1. Build one Version per Device Series: This approach is to simply develop an application for a specific series of models, for example, the Nokia Serie40 Edition 1. The problem here is that the more APIs you support, or the more your application stresses the device, the more you fragment the series since support for advanced APIs highlights the small differences within the series. For example, two similar devices will have wildly varying performance results due to the number of images on the screen.
  2. Dynamic Detection of the Handset: This option involves testing your application during execution. For example, suppose your model is a Nokia handset. Your application would detect the device model during execution and select the appropriate behaviour depending on the model.

    This allows you to call methods only available on specific handsets—like fullscreen mode. You have to create one class for each specific implementation (NokiaCanvas, SiemensCanvas, and StandardCanvas). The following code demonstrates:

    try { Class.forName("com.nokia.mid.ui.FullCanvas"); Class myClass = Class.forName("NokiaCanvas"); myCanvas = (ICanvas)(myClass.newInstance()); } catch (Exception exception1) { try { Class.forName("com.siemens.mp.color_game.GameCanvas"); Class myClass = Class.forName("SiemensCanvas"); myCanvas = (ICanvas)(myClass.newInstance()); } catch (Exception exception2) { myCanvas = (ICanvas) new StandardCanvas(); } }

    You basically create an interface, Icanvas, and three implementations, one for Nokia devices, one for Siemens devices, and another one for standard MIDP devices.

    Then you use Class.forName in order to determine whether a proprietary API is available. If no exception is thrown, you use the NokiaCanvas. Otherwise, it means the current device doesn't support this API. In this case, you test another API (for example, Siemens). If another exception is thrown, it means you have to use the standard canvas.

    Because this solution supposes the inclusion of the logic of the behavior of each the model of a device in each application, it quickly becomes impossible.

  3. Using Alteratives Like AOP or Extended Java: In his recent DevX article, Allen Lau discussed using AOP to solve the problem of fragmentation. His idea is to concentrate the application logic in one location and to modify the code of the application by adding or removing portions of code.

    This approach solves some problems, but having to adapt the structure of your application to different platforms may, in the end, force you to use another, complementary solution. This is because it can be very difficult to optimize the application to each device model—especially to support optional APIs.

    Additionally, this method does not solve the problem of adapting the content (images, sounds, etc.) to each device model. You can use Java extensions to automatically transform your source code, which is an interesting approach, but it really increases work load.

  4. Using a Preprocessor: Using a preprocessor, your source code will be automatically activated or deactivated depending on certain conditions.

    For example, to set the full screen mode on a Nokia device, you have to extend FullCanvas, not Canvas. On a MIDP 2 device, you have to call setFullScreenMode. On a MIDP 1 device, this isn't possible, so you stay in a non-fullscreen mode.

    //#ifdef NOKIA extends com.nokia.mid.ui.FullCanvas //#else extends Canvas //#endif { ... //#ifndef MIDP2 setFullScreenMode(true); //#endif

    A preprocessor processes this source code, then you set the directives. So, to generate the application for a Nokia device:

    //#define NOKIA

    The preprocessor produces:

    extends com.nokia.mid.ui.FullCanvas {

    For a MIDP 2 device, (“//#define MIDP 2”), it produces:

    extends Canvas { setFullScreenMode(true);

    This solution allows for one body of source code to be adapted to each device model. You need only develop to the reference source code, including the directives. All other modifications made to the processed files will be lost after the next preprocessing.

    Though this solution relies on the old concept of preprocessing, this is the only technique open-ended enough to solve all the problems you'll encounter trying to port to multiple device models.

Thanks for your registration, follow us on our social networks to keep up-to-date