J2ME: Alert followed by Alert

I have been working on a J2ME application. There is an instance where a message box appears so as to confirm an action with the user, if the user confirms the action then a subsequent alert may be shown. Whilst in theory this should have been straightforward the application just kept throwing an IllegalArgumentException.

In the API documentation for J2ME I found that the Display.setCurrent(alert, nextDisplayable) function will throw such an exception when nextDisplayable is an Alert instance. However, I was not using this function. The alert was being displayed using Display.setCurrent(displayable), and upon selecting “Confirm” was simply displaying another alert again with Display.setCurrent(displayable).

James Mernin’s blog post Alert after Alert in J2ME shows that this is in fact a result of the same limitation within J2ME. For my purposes I found that the simplest solution was to create a blank canvas, and upon the first paint event switch to the intended alert. This essentially breaks the chain into Alert > Canvas > Alert.

In light of this I amended my DisplayManager so that it deals with this issue transparently. My DisplayManager.setCurrent(displayable) method was replaced with the following:

public static final void setCurrent(Displayable d) {
    // Switch to new displayable.
    current = d;
    if (current instanceof javax.microedition.lcdui.Alert &&
            display.getCurrent() instanceof javax.microedition.lcdui.Alert) {
        // Switch to a black canvas temporarily!
        display.setCurrent(new BlackCanvas());
    }
    else {
        display.setCurrent(current);
    }
}

If an alert is about to be displayed, the above code will show a blank canvas if an alert is already shown. The blank canvas will then show the alert as soon as it is first painted. I implemented this blank canvas as shown below:

public final class DisplayManager {
    ...

    private static class BlackCanvas extends Canvas {
        protected void paint(Graphics g) {
            // Paint canvas to black to reduce flicker.
            // Note: You may decide to change this to suite your needs.
            g.setColor(0x000000);
            g.fillRect(0, 0, getWidth(), getHeight());

            // Now show the alert that we really wanted!
            DisplayManager.setCurrent(DisplayManager.getCurrent());
        }
    }
}