Archive for the ‘HowTo’ Category

We have moved – Please update your bookmarks!

Warning

We have moved the site to mobdev.tknerr.de, please update your bookmarks!

How To Make J2ME Apps Work for the WAP Flat, Part II (Example: Google Maps Mobile)

Last week I posted a tool to “make J2ME apps work with the o2 WAP Flat”. All the magic it does is inserting some HTTP headers into a fully compiled (and often obfuscated) J2ME application.

Some users asked how to get the .jar and .jad files of the J2ME application to your desktop PC in order to patch them with the o2 WAP Flat Patcher. There are many possibilities to accomplish this, but here’s my recommendation:

  1. Use your J2ME devices native browser to download the application. For example, visit http://www.google.com/gmm to get the latest version of Google Maps Mobile. It is important to use the devices native browser because most J2ME apps are tailored for a specific device — and the native browser uniquely identifies the device using its User-Agent and Profile headers. In my case this leads me to a site which says “Download Google Maps for Nokia 6630” and links to the appropriate .jad file (note: the .jad file is a plain text file and contains amongst others the location of the .jar file).
  2. A caveat of my Nokia 6630’s native browser is that I can not download .jad files. When I click the link above, it will directly install the application. But this is ok, since the browser will download and store both files on the device before installation. Just go ahead and install the application (we will reinstall the patched version later).
  3. Now find the Google Maps Mobile .jar and .jad files on your devices file system. On my Symbian OS based Nokia smartphone the installed J2ME apps reside in a subfolder of either “C:/System/MIDlets” (if installed to phone memory) or “E:/System/MIDlets” (if installed to memory card). Navigate to this location and copy the .jar and .jad files to your Desktop PC, e.g. via Bluetooth or USB cable (note: you may need to use FExplorer, a pimped file explorer, to access these locations and copy the files).
  4. Once you have the .jar and .jad files on the desktop, use the o2 WAP Flat Patcher to patch the files.
  5. Copy the patched files back to the device, but DO NOT overwrite the files in “E:/System/MIDlets”. Just save them to a convenient location, e.g. “E:/myapps/”. Then use the devices native file manger to navigate to “E:/maypps/” and click the patched .jad file. This will trigger the installation of the patched Google Maps Mobile (note: this won’t work with FExplorer, as FExplorer v1.15 does not recognize .jad files). If you already installed the unpatched application (see step 2), you don’t need to uninstall first — you can safely overwrite/replace the existing version.

How To Make J2ME Apps Work for the WAP Flat

Because I am a big fan of networked J2ME applications, such as Google Maps Mobile, I want to use them with my WAP flatrate. The downside is that the WAP flat requires some special HTTP headers to be set, otherwise the HTTP requests get blocked by their gateway – and most of the J2ME apps don’t have these headers.

So what can you do?

If the application is open source, fine. Go ahead, add the headers to the sourcecode and recompile. With closed source applications, e.g. Google Maps Mobile, it gets a little tricky. Here are the basic steps you need to do:

  1. download j2me app (.jar + .jad)
  2. extract class files from .jar file
  3. decompile (*)
  4. search decompiled classes for networking code
  5. add special http headers to networking code
  6. recompile changed classes
  7. preverify changed classes
  8. update .jar file with changed classes
  9. update .jad file if necessary

(*) note: obfuscation and preverification of class files makes it hard to decompile the j2me app with a decompiler such as JAD Decompiler (http://www.kpdus.com/jad.html). It results in decompilation errors and thus you can not recompile the code, as the sources are full of errors.

Because the standard decompile/change/recompile procedure does not work if decompilation fails, the only way to add the required HTTP headers is to modify the application’s bytecode directly without decompiling the class files. For this purpose you could use the javassist bytecode engineering API (http://www.csg.is.titech.ac.jp/~chiba/javassist/):

if (m.getClassName().equals(“javax.microedition.io.Connector”)
&& m.getMethodName().equals(“open”)) {
m.replace(“{“
+ “$_ = $proceed($$);”
+ “$_.setRequestProperty(\”User-Agent\”,\”Profile/MIDP-2.0 Configuration/CLDC-1.0\”);”
+ “$_.setRequestProperty(\”X-WAP-Profile\”,\”foo\”);”
+ “}”);
}
powered by Java2html

The snippet above sets the User-Agent and X-WAP-Profile header directly after each call to Connector.open(). “$_ = $proceed($$)” inserts the original call to Connector.open(), with “$_” being the returned value (an object of type HttpConnection in this case) and “$$” being the parameters (the URL of the server in this case). After the connection has been opened, we use the returned HttpConnection object (“$_”) to set the User-Agent and X-WAP-Profile headers. See the complete source code here.

For more information about the javassist library you might want to check out their javassist tutorial or this article from IBM developerworks.