Activing Alerts in MIDP 2.0

By Eric Giguere

During a lengthy operation, it is good to report the operation's progress, and reassure the user that the application hasn't stopped. You can add a gauge component to any alert, which will act as an activity or progress indicator as long as the gauge meets specific criteria: It must be non-interactive, it must not be associated with any other container, its label must be null, it must have no commands or command listener, its preferred sizes must be unlocked, and it must have a default layout. Fortunately, it's easy to create such a gauge; just construct a non-interactive Gauge instance with a null label:

	
        int max = ... // maximum value
	int initial = ... // initial value
	Gauge gauge = new Gauge( null, false, max, initial );
Calling the setIndicator() method associates the gauge with an alert:
	Alert a = new Alert( "My alert" );
	a.setIndicator( gauge ); 

You can update the gauge's value at any time — and from any thread, because the MIDP user interface classes are thread-safe. Simply invoke the gauge's setValue() method and the alert will repaint itself accordingly. Alternatively, you can use a continuously running gauge, which automatically updates itself to indicate that activity is occurring. The example at the end of this tip demonstrates both types of gauges.

Alerts support user-defined commands: you can explicitly add commands to the alert, as you do to other screens. The implicit command is suppressed whenever commands are added to an alert, and reactivated when all explicit commands are removed. Note that an alert with two or more commands is automatically given a FOREVER timeout.

For the alert to respond to commands properly, you must register a command listener with the alert using setCommandListener(). If no listener is registered, the default behavior is to dismiss the alert automatically and display the next screen — no matter which command the user selected. Registering a listener suppresses the default behavior; the application is entirely responsible for dimissing the alert, by calling Display.setCurrent().

The following code demonstrates the alert features. It's a simple MIDlet, suitable for running in the Sun Java Wireless Toolkit, version 2.0 or later, that lets you choose and activate any of several different sample alerts.

import java.io.\*;
import java.util.\*;
import javax.microedition.lcdui.\*;
import javax.microedition.midlet.\*;

// A simple MIDlet for testing various alerts.

public class AlertTest extends MIDlet
                 implements CommandListener {

    // An abstract class for our alert tests.

    public abstract class AlertRunner {
        protected static final int ONE_SECOND = 1000;
        protected static final int FIVE_SECONDS = 5000;

        public AlertRunner( String title ){
            _title = title;
        }

        public abstract Alert doAlert();

        public String getTitle(){ return _title; }

        public String toString(){ return getTitle(); }

        private String _title;
    }

    // An alert test for a simple timed alert.

    public class TimedAlert extends AlertRunner {
        public TimedAlert( String title ){
            super( title );
        }

        public Alert doAlert(){
            Alert a = new Alert( getTitle() );
            a.setString( "Times out after 5 seconds..." );
            a.setTimeout( FIVE_SECONDS );

            showAlert( a );

            return a;
        }
    }

    // An alert test for a simple modal alert.

    public class ModalAlert extends AlertRunner {
        public ModalAlert( String title ){
            super( title );
        }

        public Alert doAlert(){
            Alert a = new Alert( getTitle() );
            a.setString( "Waits to be dismissed" );
            a.setTimeout( Alert.FOREVER );

            showAlert( a );

            return a;
        }
    }

    // An alert test that displays an alert with
    // a gauge whose value is increased every second.
    // The alert can be dismissed only after the gauge
    // reaches its maximum value.

    public class ProgressAlert extends AlertRunner
                 implements CommandListener, Runnable {

        private static final int MAX = 10;

        public ProgressAlert( String title ){
            super( title );
        }

        public Alert doAlert(){
            _gauge = new Gauge( null, false, MAX, 0 );
            _gauge.setValue( 0 );
            _done = false;

            _alert = new Alert( getTitle() );
            _alert.setString( "Counts to " + MAX +
                " and then lets you dismiss it" );
            _alert.setCommandListener( this );
            _alert.setIndicator( _gauge );

            // Set a _very_ long timeout
            _alert.setTimeout( ONE_SECOND \* 3600 );

            showAlert( _alert );
            new Thread( this ).start();

            return _alert;
        }

        public void commandAction( Command c,
                                   Displayable d ){
            if( _done || _gauge.getValue() >= MAX ){
                showList();
            }
        }

        private void done(){
            _alert.addCommand(
                 new Command( "Done", Command.OK, 1 ) );
            _done = true;
        }

        // A thread that bumps the value of the counter
        // every second.

        public void run(){
            int val = _gauge.getValue();
            Thread thread = Thread.currentThread();

            try {
                while( val < MAX ){
                    thread.sleep( ONE_SECOND );
                    _gauge.setValue( ++val );
                }
            }
            catch( InterruptedException e ){
            }

            done();
        }

        private Alert   _alert;
        private int     _counter;
        private boolean _done;
        private Gauge   _gauge;
    }

    // An alert test that displays a continuously
    // running gauge before automatically timing out.

    public class BusyAlert extends AlertRunner {
        public BusyAlert( String title ){
            super( title );
        }

        public Alert doAlert(){
            _gauge = new Gauge( null, false,
                                Gauge.INDEFINITE,
                                Gauge.CONTINUOUS_RUNNING );

            _alert = new Alert( getTitle() );
            _alert.setString( "Runs for 5 seconds and " +
                   "times out automatically" );
            _alert.setIndicator( _gauge );
            _alert.setTimeout( FIVE_SECONDS );

            showAlert( _alert );

            return _alert;
        }

        private Alert   _alert;
        private Gauge   _gauge;
    }

    // Standard MIDlet code. Displays a list of
    // available alert tests and runs the test once
    // it's been chosen.

    private Display display;

    public static final Command exitCommand =
                         new Command( "Exit",
                                      Command.EXIT, 1 ); 

    public AlertTest(){
    }

    public void commandAction( Command c,
                               Displayable d ){
        if( c == exitCommand ){
            exitMIDlet();
        } else if( c == List.SELECT_COMMAND ){
            int index = _alertList.getSelectedIndex();
            _alertRunners[ index ].doAlert();
        }
    }

    protected void destroyApp( boolean unconditional )
                       throws MIDletStateChangeException {
        exitMIDlet();
    }

    public void exitMIDlet(){
        notifyDestroyed();
    }

    public Display getDisplay(){ return display; }

    protected void initMIDlet(){

        // The list of alert tests....

        _alertRunners = new AlertRunner[] {
            new TimedAlert( "Timed alert" ),
            new ModalAlert( "Modal alert" ),
            new ProgressAlert( "Progress alert" ),
            new BusyAlert( "Busy alert" )
        };

        _alertList = new List( "Alert Testing",
                               List.IMPLICIT );
        _alertList.setCommandListener( this );

        for( int i = 0; i < _alertRunners.length; ++i ){
            _alertList.append(
                 _alertRunners[i].toString(), null );
        }

        showList();
    }

    protected void pauseApp(){
    }

    private void showAlert( Alert a ){
        getDisplay().setCurrent( a, _alertList );
    }

    private void showList(){
        getDisplay().setCurrent( _alertList );
    }

    protected void startApp()
               throws MIDletStateChangeException {
        if( display == null ){ 
            display = Display.getDisplay( this );
            initMIDlet();
        }
    }

    private List          _alertList;
    private AlertRunner[] _alertRunners;
}
Eric Giguere is a software developer of Java technologies for handheld and wireless computing who has written extensively on computing topics.
Comments:

Post a Comment:
  • HTML Syntax: NOT allowed
About

Tips for developers who use Java technologies (Java SE, Java ME, JavaFX) for mobile and embedded devices.

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today