JSRs galore!!!

One of the things I had to learn about when I switched from programming Enterprise Edition Java to Mobile Edition was Java Specification Requests. Of course I was vaguely aware of JSRs and the Java Community Process as en Enterprise Edition programmer, but I didn’t really have to deal with them much in my daily life. (This was back in the old days when it was called “J2EE” 😉 )

But when you’re programming for mobile phones, as much as you’d like it to really be as simple as “write once, run anywhere,” devices unfortunately vary in implementation (behavior) as well as in terms of which standard (optional) APIs are available. So you get to know your JSRs, and keep track of which ones your program needs in order to run.

The very first new thing I wanted to try on my new Sagem my700x was to write a simple program to tell me which JSRs are available for me to play with. This info is probably available through everyone’s best friend (Google), but you’d probably have to dig around for it. Normally the specs you find on the Internet (like here) will tell you if the handset has Java, and whether it’s MDIP 1 or MIDP 2 and not much more. That’s okay, because it sets us up for a fun little exercise!!!

Let’s make a simple MIDlet to find out what JSR APIs are implemented on this handset!!!

It’s maybe not realistic to check for all possible JSRs, but at least we can check for the ones that are implemented in the WTK. Running the ktoolbar application and selecting the “Settings” button (after opening a new project), I get a window that lists the following optional JSRs: JSR 75 (PIM), JSR 75 (File Connection), JSR 82 (Bluetooth), JSR 135 (Mobile Media), JSR 172 (Web Services RMI), JSR 172 (Web Services SAX), JSR 184 (3D Graphics), (JSR 205 Wireless Messaging).

I looked them all up here and downloaded the final draft documentation for each one.

The next step was to write a MIDlet that attempts to load a class from each optional package. I assume that if one class is there, the whole package is probably there too. For fun I decided to check for MobileScope’s EGE API as well!!! 😀

The result on the WTK was exactly as expected: all of the above APIs are supported except MobileScope’s EGE API.

Here’s the result for the Sagem m700x:

JSR 75 PIM: supported,
JSR 75 File Connection: supported,
JSR 82 Bluetooth: not supported,
JSR 135 Mobile Media: supported,
JSR 172 Web Services RMI: not supported,
JSR 172 Web Services SAX: not supported,
JSR 184 3D Graphics: supported,
JSR 205 Wireless Messaging: not supported,
EGE: supported.

If you’d like to try the MIDlet on your own handset, I’ve put it on my site here: http://www.frog-parrot.net/hello.wml

Here’s the code:


package net.frog_parrot.test;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form ;
import javax.microedition.lcdui.List;
import javax.microedition.midlet.MIDlet;
/**
* A simple MIDlet to test which APIs are implemented.
*/
public class Test extends MIDlet implements CommandListener {
  
  private Command m_exitCommand = new Command("Done", Command.EXIT, 1);
  private List m_menu;
  private Form m_resultScreen;
  /**
   * The list of API labels.
   */
  private String[] m_jsrs = {
    "JSR 75 PIM",
    "JSR 75 File Connection",
    "JSR 82 Bluetooth",
    "JSR 135 Mobile Media",
    "JSR 172 Web Services RMI",
    "JSR 172 Web Services SAX",
    "JSR 184 3D Graphics",
    "JSR 205 Wireless Messaging",
    "EGE",
  };
  
  /**
   * The index constants for the label array.
   */
  private static final String SUPPORTED = "Supported";
  private static final String NOT_SUPPORTED = "Not Supported";
  private static final int JSR_75_PIM = 0;
  private static final int JSR_75_FC = 1;
  private static final int JSR_82_BLUETOOTH = 2;
  private static final int JSR_135_MOBILE_MEDIA = 3;
  private static final int JSR_172_WEB_SERVICES_RMI = 4;
  private static final int JSR_172_WEB_SERVICES_SAX = 5;
  private static final int JSR_184_3D_GRAPHICS = 6;
  private static final int JSR_205_WIRELESS_MESSAGING = 7;
  private static final int EGE = 8;
  
  /**
   * Empty constructor.
   */
  public Test() {
  }
  
  /**
   * Initialize the Displayables.
   */
  public void startApp() {
    m_menu = new List("Test Menu", List.IMPLICIT, m_jsrs, null);
    m_menu.addCommand(m_exitCommand);
    m_menu.setCommandListener(this);
    Display.getDisplay (this).setCurrent(m_menu);
    m_resultScreen = new Form("Results");
    m_resultScreen.addCommand(m_exitCommand);
    m_resultScreen.setCommandListener(this);
  }
  
  public void pauseApp() {
  }
  
  public void destroyApp(boolean unconditional) {
  }
  
  /**
   * Change the display in response to a command action.
   */
  public void commandAction(Command command, Displayable screen) {
    if(screen == m_menu) {
      if(command == m_exitCommand) {
        destroyApp(false);
        notifyDestroyed();
      } else {
        m_resultScreen.deleteAll();
        int index = m_menu.getSelectedIndex();
        switch(index) {
        case JSR_75_PIM:
          m_resultScreen.append(m_jsrs[JSR_75_PIM] + ": ");
          try {
            Class.forName("javax.microedition.pim.PIMException");
            m_resultScreen.append(SUPPORTED);
          } catch(ClassNotFoundException e) {
            m_resultScreen.append(NOT_SUPPORTED);
          }
          Display.getDisplay(this).setCurrent(m_resultScreen);
          break;
        case JSR_75_FC:
          m_resultScreen.append(m_jsrs[JSR_75_FC] + ": ");
          try {
            Class.forName("javax.microedition.io.file.ConnectionClosedException");
            m_resultScreen.append(SUPPORTED);
          } catch(ClassNotFoundException e) {
            m_resultScreen.append(NOT_SUPPORTED);
          }
          Display.getDisplay(this).setCurrent(m_resultScreen);
          break;
        case JSR_82_BLUETOOTH:
          m_resultScreen.append(m_jsrs[JSR_82_BLUETOOTH] + ": ");
          try {
            Class.forName("javax.bluetooth.BluetoothConnectionException");
            m_resultScreen.append(SUPPORTED);
          } catch(ClassNotFoundException e) {
            m_resultScreen.append(NOT_SUPPORTED);
          }
          Display.getDisplay(this).setCurrent(m_resultScreen);
          break;
        case JSR_135_MOBILE_MEDIA:
          m_resultScreen.append(m_jsrs[JSR_135_MOBILE_MEDIA] + ": ");
          try {
            Class.forName("javax.microedition.media.MediaException");
            m_resultScreen.append(SUPPORTED);
          } catch(ClassNotFoundException e) {
            m_resultScreen.append(NOT_SUPPORTED);
          }
          Display.getDisplay(this).setCurrent(m_resultScreen);
          break;
        case JSR_172_WEB_SERVICES_RMI:
          m_resultScreen.append(m_jsrs[JSR_172_WEB_SERVICES_RMI] + ": ");
          try {
            Class.forName("java.rmi.RemoteException");
            m_resultScreen.append(SUPPORTED);
          } catch(ClassNotFoundException e) {
            m_resultScreen.append(NOT_SUPPORTED);
          }
          Display.getDisplay(this).setCurrent(m_resultScreen);
          break;
        case JSR_172_WEB_SERVICES_SAX:
          m_resultScreen.append(m_jsrs[JSR_172_WEB_SERVICES_SAX] + ": ");
          try {
            Class.forName("org.xml.sax.SAXParseException");
            m_resultScreen.append(SUPPORTED);
          } catch(ClassNotFoundException e) {
            m_resultScreen.append(NOT_SUPPORTED);
          }
          Display.getDisplay(this).setCurrent(m_resultScreen);
          break;
        case JSR_184_3D_GRAPHICS:
          m_resultScreen.append(m_jsrs[JSR_184_3D_GRAPHICS] + ": ");
          try {
            Class.forName("javax.microedition.m3g.CompositingMode");
            m_resultScreen.append(SUPPORTED);
          } catch(ClassNotFoundException e) {
            m_resultScreen.append(NOT_SUPPORTED);
          }
          Display.getDisplay(this).setCurrent(m_resultScreen);
          break;
        case JSR_205_WIRELESS_MESSAGING:
          m_resultScreen.append(m_jsrs[JSR_205_WIRELESS_MESSAGING] + ": ");
          try {
            Class.forName("javax.wireless.messaging.SizeExceededException");
            m_resultScreen.append(SUPPORTED);
          } catch(ClassNotFoundException e) {
            m_resultScreen.append(NOT_SUPPORTED);
          }
          Display.getDisplay(this).setCurrent(m_resultScreen);
          break;
        case EGE:
          m_resultScreen.append(m_jsrs[EGE] + ": ");
          try {
            Class.forName("com.infusio.ege.toolkit.TLV");
            m_resultScreen.append(SUPPORTED);
          } catch(ClassNotFoundException e) {
            m_resultScreen.append(NOT_SUPPORTED);
          } catch(Exception e) {
            m_resultScreen.append(e.getClass()
                                  + ": " + e.getMessage());
          }
          Display.getDisplay(this).setCurrent(m_resultScreen);
          break;
        default:
          break;
        }
      }
    } else {
      Display.getDisplay (this).setCurrent(m_menu);
    }
  }
}

3 comments so far

  1. Sdl on

    Hi Carol,

    Handset fragmentation yelds to a terrible mess to any J2ME programmer around.

    It’s true that you can try yourself to detect what JSRs are present on your phone, the one of your husbéand, the ones of your friends, etc. But frankly, you’ll be exhausted before you cover a single percent of what the market has to offer.

    Here is where http://mobilezoo.biz comes. It covers almost any handset on earth, and even those that have not yet reached the market (as for the Nokia N92 for example.

    For each handset model and even for each handset revision, mobilezoo.biz gives the list of the handset that are actually functionning, many properties ofthe phone, the tpe of connection you’ll get (TCP, UDP included), and far more.

    But that’s not all. You will also have access – when available – to operators related information (such as UAProfiles), MSISDN, type of bearer (Wap, TCP, GRPS, EDGE, etc.), type of gateway and software provider.

    And, to give a full coverage of what mobilezoo.biz has to offer, they also released a tiny jar that you can include in your own app, in order to track tons of statistics about your users, manufacturer market share related to YOUR application, realtime follow-up of your app version adoption, ant much more.

    The site is in alpha stage, many features improvedand/or are included over time, so give it a try, and let me know what you thing…

    Sdl

  2. carolhamer on

    Hi Sdl!

    That looks like a really good concept, and a valuable resource, especially for smaller companies and independent developers.

    Obviously I didn’t mean the above excercise to be a serious way for professional game providers to assess all of their target handsets. It’s just a fun little getting-to-know-your-new-handset warm-up. 😉

  3. […] The idea of MobileZoo appears to be the creation of a centralized database of all of the precise specs a Java developer might need to optimize an application for a given handset (including which JSRs are supported with version numbers if applicable, plus screen and canvas size and colors, etc.). All of this information is harvested by a MIDlet along the same lines as the MIDlet I posted the other day only more extensive, gathering up every bit of information about the handset that is accessible via Java. Then the MIDlet sends this information to MobileZoo. It looks like the revenue model is to offer a premium service and/or a stats-gathering library to registered developers. (Or maybe they’re just planning to get paid through putting ads on their site?) […]


Leave a comment