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());
}
}
}