J2ME

Come to think about it, quite a few personal projects I’ve worked on over the years came about because I felt I needed to go against the grain in terms of conditions or expectations. In this particular case, I started working on J2ME because a certain university professor said you can do this project with any mobile technology, which led to a conversation along the lines of:

Me: So I can go with any mobile technology I want, correct?

Him: Yes, most people do Android projects, but I've seen a few successful ones for iOS.

Me: I have a Nokia 3310 refurbished and it should be possible to write apps for that, _somehow_.

It took me a couple evenings to set things up correctly and once I got a reliable environment going, everything got much easier. (Or at least as easy as things can be when developing things for a 10-year-old platform with a heavily limited API.) So here’s a quick intro to writing your own apps for Nokia 3310 2017. This tutorial assumes a basic level of knowledge when it comes to Java.

Installation steps

These steps work for Windows and have been tested on a Windows 10 VM. I strongly recommend following them on a virtual machine, as there’s going to be a certain amount of outdated software involved.

  1. Download and install Java 6.
  2. Download and install Java ME Platform SDK 3.0.

Using Eclipse / Netbeans etc for development

Can you use Eclipse, Netbeans or any other IDE? Possibly. However, after spending a considerable amount of time trying to set it up reliably I gave up. The IDE shipped with the J2ME SDK 3.0 was good enough for me.

Setup steps

Start the Java ME Platform SDK 3.0 app (henceforth: IDE). From now on, you need to create your new project,

Creating a new project

Go to file -> New Project. Choose “MIDP Application” from the list. Set your project name to something (e.g. HelloWorld) and change the project location if you so desire. Leave “Set as Main Project” and “Create Hello MIDlet” as is. On the final step, the emulator platform should be set to CLDC…SDK 3.0. The version of the device configuration and profile are left to you — I went with the defaults. Hit finish and wait a moment.

Running the project

Running is fairly simple - you have the big green Play button on the top bar.

Renaming your classes

What if you decided that you wanted to remain the autogenerated class from HelloMIDlet to, say, HelloWorld? Even if you change the class name and its definition, the project is not going to run. In such a case right-click your project, select Properties and go to Application Descriptor. There, under MIDlets, you still have your old class (by now probably marked in red). Select it to remove it from the list, then click Add and confirm the choice of the new MIDlet class. Now the app should start without any issues.

J2ME basics: creating a simple app

J2ME apps don’t have a main function; instead, one of the classes has to inherit from the MIDlet class and implement the CommandListener interface. The blueprint for that class has to include the following:

  • one or more fields; it has to at least contain a Display-type field if it’s to show anything on the screen;
  • the class constructor, which defines the elements used in the app, such as Forms (views), Fields, Commands and more;
  • three void methods: startApp, pauseApp and destroyApp, which define what happens on the application start, on pause (i.e. when you take a phone call while the app is running), and on exit;
  • the “main” void method commandAction that defines the logical flow of the application based on the actions of the user.

Let’s try to make a simple app that takes in the user’s name and puts it on screen.

Fields

We’re going to need the following fields:

private Display display;
private TextField field;
private TextField greeting;
private String name;
private Command writeName;
private Command exit;
private Form form;

View

Forms are the views of the app, so let’s start with the drawing out our form in the constructor. To create a new form, simply create a new Form object:

form = new Form("My first form");

To add new elements to a form, you define them and them append them to the form, for example

field = new TextField("Tell me your name", "", "30", TextField.ANY);
form.append(field);
greeting = new TextField("", "Hello, person!", 30, TextField.UNEDITABLE);
form.append(greeting);

and then append some actions to it

writeName = new Command("What's my name?", Command.OK, 0);
form.addCommand(writeName);
exit = new Command("Exit", Command.EXIT, 0);
form.addCommand(exit);

Finally, set the command listener to listen for any commands in the app:

form.setCommandListener(this);

and then set the display to show the form:

display = Display.getDisplay(this);
display.setCurrent(form);

Methods

We want the usual subjects: startApp(), pauseApp() and destroyApp(), but we’ll leave them as is. In the commandAction we’re going to read the name from the textField and then invoke the name-writing function, as well as define the exit:

public void commandAction(Command c, Displayable s) {
  if (c.getCommandType() == Command.OK) {
    name = field.getString();
    writeName(name);
  }
  if (c.getCommandType() == Command.EXIT) {
    destroyApp(false);
    notifyDestroyed();
  }
}

Finally, we need to define what writeName does behind the scenes, which is just a simple replacement:

private void writeName(String name) {
  greeting.setString("Hello, " + name + "!");
}

All in all, this should give us the following code.

Other stuff

Here are some things I’m not going to get into details here but might be worth your while.

Persisting data

If you need to keep data in-between application runs, use the RecordStore.

Adding third-party libraries

It is possible to import third-party libraries; you can add them by right-clicking the project, selecting Properties and going to the Libraries and Resources tab.

Note, however, that if the library is not extremely small you will have to manually take in the classes you might need for it to build and run on the emulator device, which is time-consuming and definitely not fun. (I’m looking at you, the “lightweight” BouncyCastle API.)

Running apps on a real device

It is possible to run J2ME on modern device; a good example is the 2017 Nokia 3310 Refurbished. Once you’ve built and tested the app on the emulator, copy the jar and jad files available at dist/ to your device (in the case of this Nokia you need a memory card), then navigate to that directory on the phone and install your app.

All in all, writing these apps for basic things is fairly easy, but gets insanely messy after a while. I can only imagine how hard it gets on really capped devices (Nokia 3310 2017 has a ~360MHz CPU; a lot of J2ME-running devices these days are micro-controllers with around 40-50MHz.)

Published 8 Oct 2020

Personal site; contains my incoherent ramblings, with trace amounts of code & dry jokes.
MK Mozgawa on Twitter