J2ME: Alert followed by Alert


I have been working on a J2ME application. There is an instance where a message box appears 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).

With thanks to James Mernin’s blog (Alert after Alert in J2ME) I found 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 new information I decided to amend my DisplayManager so that it deals with this issue transparently. The DisplayManager.setCurrent(displayable) method can be 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());
      }
   }
}
Advertisements

7 thoughts on “J2ME: Alert followed by Alert

  1. Hi, is there any complete source code packed for download.
    I get this problem too, for too much pieces UI in JavaME application

    1. I have merged the “DisplayManager” code from both of my posts and listed them below. The custom “Alert” source code is available from my original blog post here.

      Don’t forget, you will need to initialize the “DisplayManager” class as soon as the MIDlet is run. I recommend that it is the very first line of code that runs. The “DisplayManager” should then be used to switch between UI’s with its specialized “setCurrent” methods. The custom “Alert” class has a special “show” method which can be used for convenience, but this method simply invokes “DisplayManager.setCurrent”.

      Please let me know if you have any questions! I hope that you find this of use.

      public final class DisplayManager {
         // Helper "Black" canvas:
         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());
            }
         }
      
         // Fields:
         private static Display display;
         private static Displayable current;
      
         // Properties:
         public static final Display getDisplay() { return display; }
         public static final Displayable getVisible() { return display.getCurrent(); }
      
         public static final void setCurrent(Displayable d) {
            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);
         }
         public static final void setCurrent(Alert d, Displayable nextDisplayable) {
            d.next = nextDisplayable;
            setCurrent(d);
         }
      
         // Methods:
         public static final void initialize(Display display) {
            current = (DisplayManager.display = display).getCurrent();
         }
      }
  2. Hi.
    I’ve been having an issue.
    When displaying only an alert, and dismiss it, it doesn’t change back to the displayable that was visible before the alert.

    1. Hi Dimitrios,

      I usually store a reference to the previous display within a protected variable within my own custom Alert class. My DisplayManager class remembers this within the ‘setCurrent’ function:

      // Store next displayable item within protected variable of custom derived Alert object.
      d.next = nextDisplayable;
      // Adjust current display.
      setCurrent(d);

      So, to show an alert ‘myAlert’ and then return to the current display ‘restoreThisDisplay’:
      DisplayManager.setCurrent(myAlert, restoreThisDisplay);

      I hope that this helps, please feel free to ask further questions and I will try my best to assist.

      Kind regards,
      Lea Hayes

      1. Thank you so much for your response.
        In paint method of the Canvas class you have:
        DisplayManager.setCurrent(DisplayManager.getCurrent());
        However there is no getCurrent method definition in the DisplayManager class you provided.
        I assume it’s:
        public static Displayable getCurrent(){
        return current;
        }

        I am using both DisplayManager (wonderful code!!) and the custom Alert you provided.
        I use it almost exactly as you do.

        I found that I was using: setCurrent(Displayable d) with an alert as d. So when dismissing the custom alert the next member was not set.
        So I reconstructed the setCurrent method to be able to use setCurrent(Displayable d) as setCurrent(Alert a) without having to explicitly specify the displayable to switch to after dismissing the alert (it returns to the displayable visible before displaying the alert) so the method is modified:

        public static final void setCurrent(Displayable d) {
        if (d instanceof Alert){
        ((Alert) d).next = current; // After dismiss go to the displayable visible before displaying the alert.
        }
        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);
        }

        What do you think?

      2. Thank you for the complement, I am glad that you have found my code of use!

        Yes DisplayManager::getCurrent is very useful, I have had this in my revised class for quite some time now. I found it necessary to add synchronisation to my DisplayManager::getCurrent function (and all related functions) because I was getting some undesirable behaviours from some J2ME devices.

        With regards to your version of setCurrent. Obviously if this works for you then that is great you should stick with it. From a re-usability standpoint my concern is that the function doesn’t behave consistently for different types of displayables.

        For example, a custom Alert class supports automatic returning to a next display, yet any other type of displayable doesn’t. Splitting the function into two yields greater consistency because both functions can always be expected to behave in the same way each time they are invoked.

        In my projects I very rarely have the Alert box move back to the previous displayable, I usually switch to another. So I found it particularly beneficial to allow a manual override. I guess this depends on the kind of MIDlets that you are creating though.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s