gamelan
Search EarthWeb
CodeGuru | Gamelan | Jars | Wireless | Discussions
Navigate developer.com
Architecture & Design  
Database  
Java
Languages & Tools
Microsoft & .NET
Open Source  
Project Management  
Security  
Techniques  
Voice  
Web Services  
Wireless/Mobile
XML  
Technology Jobs  

   Developer.com Webcasts:
  The Impact of Coding Standards and Code Reviews

  Project Management for the Developer

  Defining Your Own Software Development Methodology

  more Webcasts...




See the Winners!


Developer Jobs

Be a Commerce Partner
Server Racks
Auto Insurance Quote
Dental Insurance
Promote Your Website
Data Center Solutions
Compare Prices
Find Software
Imprinted Promotions
Disney World Tickets
Phone Cards
Shop Online
Rackmount LCD Monitor
Baby Photo Contest
Promotional Pens

 


  Managing the Modern Network
Sponsored by HP
In a global economy where information crosses the globe in an instant, and where Web-based applications power business, it's more important than ever to ensure your network is safe from threats and optimized to deliver the data your business needs. »
 
  Business Service Management: Generate Revenue Through IT
Sponsored by HP
IT must now help organizations attract, retain and grow customer relationships and increase customer satisfaction. Business service management (BSM) helps lay the foundation by managing services in dynamic support of business requirements. Learn more. »
 
  Evaluating Software as a Service for Your Business
Sponsored by Webroot
Is Software as a Service just hype, or is something really going on here? See if your company can benefit as SaaS tries to change the face of the enterprise. »
 
  Storage Networking: Configuration and Planning
Sponsored by HP
The most critical part of setting up a SAN is configuring each individual disk array. This guide examines configurations for SAN-attached servers and disk arrays, and looks at the future of IP storage. »
 
  Is Your Disaster Recovery Plan Good Enough?
Sponsored by HP
Preparing for a disaster is more often than not part of the storage planning process, and it is one of the most difficult tasks, since it includes local hardware and software, networking equipment, and a test plan. Learn how to get disaster recovery right. »
 
Developer News -
SaaS Tool Offers Custom Database Development    May 9, 2008
Microsoft’s Automated Agent: Can We Talk?    May 7, 2008
Borland Finally Sells CodeGear    May 7, 2008
Red Hat Heads For The JON 2.0    May 7, 2008
Free Tech Newsletter -

Best Practices for Developing a Web Site: Checklists, Tips, Strategies & More. Download Exclusive eBook Now.

Using Alerts, Images, Timers, and Gauges in MIDlets
By Richard G. Baldwin

Java Programming Notes # 2580


Preface

This is one in a series of tutorial lessons designed to teach you how to write programs using the Sun Java Wireless Toolkit for CLDC. The first lesson was titled Getting Started with MIDlets and the Sun Java Wireless Toolkit for CLDC. The previous lesson was titled Introduction to the MIDlet User Interface, Part 2 (see Resources).

A MIDlet development framework

For this lesson, you will need the updated version of the MIDlet development framework named WTKFramework03 that is provided in Listing 13. This is a minor update to the framework relative to the previous version, but it is required for the MIDlets presented in this lesson that use images. This version preserves image files when it is cleaning up after itself.

What you learned in the previous lesson

In Part 1 and Part 2 of the previous lesson, you learned:

  • The fundamentals of user interfaces for MIDlets.
  • How to instantiate user interface components.
  • How to cause user interface components to become visible on the cell phone screen.
  • The differences between a Screen and a Display.
  • About restrictive constraints and modifier flags.
  • About the MIDlet user interface class hierarchy.
  • About the methods of various classes that can be used to manipulate user input and output.
  • How to program MIDlet user interfaces that minimize the MIDlet's memory footprint while the MIDlet is paused making consistent use of the MIDlet class methods to satisfy the life-cycle requirements for MIDlets.

What you will learn in this lesson

In this lesson you will learn:

  • How to program an Alert for a MIDlet.
  • How to add an image to the Alert.
  • How to add a Gauge to the Alert to act as a progress or activity meter.
  • How to use a Timer to control when an Alert becomes visible on the screen.

Viewing tip

I recommend that you open another copy of this document in a separate browser window and use the following links to easily find and view the figures and listings while you are reading about them.

Figures

  • Figure 1. Partial class hierarchy for MIDP 2.0.
  • Figure 2. Sun cell phone emulator display of MIDlet named Alert01.
  • Figure 3. Sun cell phone emulator display of MIDlet named Alert02.
  • Figure 4. Selected methods of the Alert class as of MIDP 2.0.
  • Figure 5. Methods of the TimerTask class as of MIDP 2.0.

Listings

  • Listing 1. Beginning of the MIDlet class named Alert01.
  • Listing 2. Beginning of the startApp method in Alert01.
  • Listing 3. Schedule a TimerTask.
  • Listing 4. Remaining code in startApp method in Alert01.
  • Listing 5. The pauseApp and destroyApp methods in Alert01.
  • Listing 6. Beginning of the class named MyTimerTask in Alert01.
  • Listing 7. Create and program an Alert object in Alert01.
  • Listing 8. Create and service the Gauge in Alert01.
  • Listing 9. Make the Alert visible in the MIDlet named Alert01.
  • Listing 10. Create an Alert object for the MIDlet named Alert02.
  • Listing 11. Create a Gauge for the MIDlet named Alert02.
  • Listing 12. Set the current value of the Gauge to be count mod 3.
  • Listing 13. The updated MIDlet development framework named WTKFramework03.
  • Listing 14. Source code for the MIDlet named Alert01.
  • Listing 15. Source code for the MIDlet named Alert02.

Supplementary material

I recommend that you also study the other lessons in my extensive collection of online Java tutorials. You will find a consolidated index at www.DickBaldwin.com.

General background information

A partial class hierarchy

In the earlier lesson titled Introduction to the MIDlet User Interface, Part 1 (see Resources), I presented a partial class hierarchy for MIDP 2.0. Figure 1 shows an expanded version of that class hierarchy.

Figure 1. Partial class hierarchy for MIDP 2.0.
  • Object
    • Displayable
      • Screen
        • TextBox
        • Alert
        • Form
        • List
      • Canvas (abstract)
        • GameCanvas (abstract)
    • Display
    • Ticker
    • AlertType
    • Image
    • Item
      • Gauge
      • TextField
    • Timer
    • TimerTask

I discussed and explained the classes shown in bold Italics in earlier lessons. I will discuss and explain the classes shown in boldface (non Italics) in this lesson.I will discuss the remainder of the classes shown in Figure 1 (plus other classes) in future lessons.

The Alert class

You may recall from the earlier lessons that an object of the class Alert is one of four types of high-level user interface (UI) components that you can place on the cell phone screen to communicate with the user. The four high-level UI component classes are all subclasses of the Screen class shown in Figure 1.

A temporary screen display

An Alert is a Screen that takes over the cell phone display and shows some data for a specified time period. Then it disappears and the display reverts to the Screen that would normally be showing. The contents of the Alert on the screen can include a title, a string, an image, and a Gauge.

An AlertType

An Alert may optionally have an AlertType associated with it to indicate the nature of the alert. (If you pass null to the corresponding constructor parameter, there is no alert type associated with the alert.) The cell phone can use the AlertType value to play an appropriate sound when the Alert is displayed. According to Sun,

"The actual sound made by the device, if any, is determined by the device. The device may ignore the request, use the same sound for several AlertTypes or use any other means suitable to alert the user."

An Image

As mentioned above, an Alert can contain an Image in addition to the title, the string, and the Gauge. The Image data can come from a variety of sources including graphics files of types gif, png, and jpeg. At least that is true with regard to the Sun cell phone emulator.

In general, an Image used with a MIDlet can be either mutable or immutable. In this lesson, we will confine the discussion to immutable images only.

A Gauge

Optionally, an Alert can contain a Gauge object. The Gauge object must be operating in a non-interactive manner and must comply with some other restrictions as well. One use for a Gauge object that meets all of the restrictions is as an activity or progress indicator.

Sample screen shots

Figure 2 and Figure 3 show the Sun cell phone emulator output for the MIDlets named Alert01 and Alert02.

Figure 2. Sun cell phone emulator display of MIDlet named Alert01.

Explanation of the screen shots

In both images, the Alert title is shown in the gray bar across the top. The text string portion of the alert is on the left side of the cell phone screen slightly below the center. The red and blue balls are the images. The vertical bars in Figure 2 constitute the gauge in that MIDlet. The image of Duke in Figure 3 is one of three successive images of Duke that constitute the gauge in that MIDlet. I will explain the differences between these two MIDlets later.

Figure 3. Sun cell phone emulator display of MIDlet named Alert02.

Missing screen shots

When the Alerts are not showing on the cell phone screens in the two sample MIDlets in this lesson, a TextBox screen is showing. However, because the behavior of each MIDlet is dynamic and the TextBox screen doesn't stay on the display very long, I was unable to capture a screen shot of the TextBox screen.

This shouldn't be a problem, however. You have seen screen shots of TextBox objects before. The TextBox screens in these MIDlets look very much like the screen shown in Figure 1 of the earlier lesson titled Introduction to the MIDlet User Interface, Part 1 (see Resources).

The Alert class

The constructor for the Alert class

As of MIDP 2.0, there are two overloaded constructors for the Alert class. The constructor that I will use in this lesson takes four parameters:

  • String title
  • String alertText
  • Image alertImage
  • AlertType alertType

The first three of the parameters match three items in Figure 2 and Figure 3. However, as near as I can tell, the fourth parameter (alertType) doesn't have a visible manifestation in the Sun cell phone emulator. I will explain the audio manifestation of this parameter later when I explain the code.

The other overloaded constructor takes only two parameters and they match the first two parameters in the above list.

Methods of the Alert class

As of MIDP 2.0, the Alert class defines fourteen methods. Three of those methods are associated with interactive programming and commands, which I will be discussing in a future lesson. Six of the methods are relatively standard getter methods, which should not require any explanation or discussion. The remaining five methods are shown in Figure 4.

Figure 4. Selected methods of the Alert class as of MIDP 2.0.
  • setImage(Image img) - Sets the Image used in the Alert.
  • setIndicator(Gauge indicator) - Sets an activity indicator on this Alert.
  • setString(String str) - Sets the text string used in the Alert.
  • setTimeout(int time) - Set the time for which the Alert is to be shown.
  • setType(AlertType type) - Sets the type of the Alert.

Methods that I did or could have used

These are methods that I either did use, or could have used in the two sample MIDlets in this lesson. By this I mean that these are methods that I could have used to set the important properties of the Alert objects had I not elected to specify these property values using constructor parameters. Note, however that the setIndicator method does not have a constructor parameter counterpart and the method must be called to attach a Gauge to the Alert.

The six getter methods that I didn't list above can be used to get the current values of the same five properties as the setter methods in Figure 4, plus an additional property named defaultTimeout.

The AlertType class

An object of the AlertType class can be passed as the fourth parameter to the Alert constructor to establish the type of the Alert. Optionally, a value of null can be passed meaning that the Alert is of no specific type.

Five types of alerts

Alert objects may be used by a MIDlet to present various kinds of information to the user. The AlertType object can be used to cause the type of the alert to be more specific. The predefined types in MIDP 2.0 are:

  • INFO
  • WARNING
  • ERROR
  • ALARM
  • CONFIRMATION

One of the sample MIDlets in this lesson uses an alert of type ALARM. The other uses an alert of type CONFIRMATION.

Playing AlertType sounds without changing the display

Although this capability is not demonstrated by either of the sample MIDlets in this lesson, according to Sun,

"An AlertType may be used to directly signal the user without changing the current Displayable. The playSound method can be used to spontaneously generate a sound to alert the user. For example, a game using a Canvas can use playSound to indicate success or progress."

A very simple class

The AlertType class is a very simple class. It defines a public static final variable for each of the five alert types in the above list. It defines one constructor that takes no parameters, and it defines the playSound method mentioned above. That's about all there is to the AlertType class.

The Image class

An object of the Image class is used to hold graphical image data. Images can be placed within Alert, Choice, Form, or ImageItem objects. In this lesson, we will be concerned only with placing Image objects in Alert objects. I will discuss and explain the other types of objects in future lessons.

Mutable or immutable

Images may be either mutable or immutable depending upon how they are created. Immutable images are usually created by loading image data from various resources such as image files. Once they have been created, they cannot be modified.

Mutable images are created as blank images containing only white pixels. They may be modified after they are created. In this lesson, we will be concerned only with immutable images.will discuss mutable images in a future lesson on graphics and the Canvas class.

Image file formats

The Sun documentation for the Image class would lead one to believe that only image files of type PNG are supported.  However, I have confirmed experimentally that at least when using the Sun cell phone emulator, the sample MIDlets in this lesson will also work properly with GIF image files and JPEG image files in addition to PNG image files. In any event, there is a link in Resources to a free online image file conversion service that can be used to convert numerous image file formats to PNG format if you want to stick strictly with PNG image files.

No constructor and no fields

The Image class has no public constructor and no fields. What it does have is a set of six public static overloaded methods named createImage that can be called to create an object of type Image. In addition, there is a public static method named createRGBImage that can also be called to create an object of type Image.

Each of these methods lets you specify the source of the image data in a different way. I will use only one of the overloaded methods in this lesson. The version of the createImage method that I will use accepts the path and name of an image file (png, gif, or jpeg) and uses the image data in that file to produce the Image object.

Five additional methods

In addition to the overloaded methods mentioned above, the Image class defines five additional methods, most of which are probably most useful when dealing with graphics and the Canvas class.

The Gauge class

According to Sun, the Gauge class

"Implements a graphical display, such as a bar graph, of an integer value."

The vertical bars in Figure 2 and the image of Duke in Figure 3 are two different manifestations of a Gauge object.

The Gauge constructor

The Gauge class has a single constructor that requires the following parameters:

  • String label
  • boolean interactive
  • int maxValue
  • int initialValue

The first parameter is used to create a label for the Gauge. The second parameter specifies whether or not the Gauge is interactive. For example, an interactive Gauge could be used as an interactive volume control.

A graphical representation of numeric values

The purpose of a Gauge is to provide a graphical representation of integer values between zero and a maximum value specified by the third parameter to the constructor. The fourth parameter specifies the initial value that will be graphed.

At any point in time, the Gauge object contains a current value. That value must lie between zero and the specified maximum value, inclusive. Otherwise, the MIDlet will throw a runtime exception.

The maximum value and the current value are within the control of the MIDlet code. However, the display provided by the cell phone may be more granular than the data. In that case, a given display may represent more than one current value.

Restrictions for Gauge objects with Alerts

When a Gauge object is used as a progress or activity indicator for an Alert, it must satisfy the following restrictions:

  1. It must not be interactive.
  2. It must not be owned by another container (Alert or Form).
  3. It must not have any Commands.
  4. It must not have an ItemCommandListener.
  5. It must not have a label (that is, its label must be null).
  6. Its preferred width and height must both be unlocked.
  7. Its layout value must be LAYOUT_DEFAULT.

The Gauge objects that I will use with the sample MIDlets in this lesson will satisfy those requirements.

A non-interactive Gauge

The Gauge objects will be used in non-interactive mode in the sample MIDlets in this lesson. (I plan to illustrate the use of an interactive Gauge in a future lesson.) The non-interactive mode will be used in the sample MIDlets to provide progress or activity feedback to the user.

Progress and activity indicators

In the MIDlet shown in Figure 2, the Gauge object is used to show progress toward a specific goal (six bars). In the MIDlet shown in Figure 3, the Gauge is used to show that the process is active, but there is no indication of percent of completion. In this case, the Gauge is represented by Duke cycling among three different images.

A definite or indefinite range

A non-interactive Gauge can have a definite or indefinite range, and this is where things get a little more complicated. For the easy case where a Gauge has definite range, it will have current value between zero and the maximum value set by the application, inclusive. The implementation will provide a graphical representation of this value similar to that shown in Figure 2.

Four states for an indefinite range

According to Sun, a non-interactive Gauge that has indefinite range will exist in one of four states:

  • CONTINUOUS_IDLE
  • INCREMENTAL_IDLE
  • CONTINUOUS_RUNNING
  • INCREMENTAL_UPDATING

These states are intended to indicate to the user that some level of activity is occurring.

The incremental-updating state can be used to indicate that progress is being made even though there is no known endpoint to the activity. For example, the MIDlet may be loading a file of an unknown size.

The continuous-running state can be used to indicate simply that the process is busy with no specific indication of progress, indefinite or otherwise.

The continuous-idle and incremental-idle states can be used to indicate that no activity is occurring.

Methods of the Gauge class

As of MIDP 2.0, the Gauge class defines eleven methods. However, primarily because of the restricted nature of a Gauge that is attached to an Alert, the sample MIDlets in this lesson use only one of the eleven methods: setValue. As you will see later, this method is used to set the current value of the Gauge each time the Alert is displayed.

The Timer class

An object of the Timer class has no special relationship with the Alert class. You may recall that in previous tutorials I have launched a Worker thread to do the work of a MIDlet and have launched a Toggler thread to control timing and to exercise the MIDlet. An object of the Timer class along with an associated object of the TimerTask class provides a quick and easy way to accomplish the same thing if the requirements aren't too demanding.

According to Sun, a Timer object provides:

"A facility for threads to schedule tasks for future execution in a background thread. Tasks may be scheduled for one-time execution, or for repeated execution at regular intervals."

How does it work?

Basically, you instantiate an object of the Timer class to control the timing. Then you use that object to schedule the run method of an object of the TimerTask class to be executed either once at some specified time in the future, or repeatedly with a specified repetition rate beginning at some specified time in the future.

A relatively simple class

The Timer class is a relatively simple class. As of MIDP 2.0 it has a single constructor that takes no parameters and seven methods. One of the methods is a cancel method that terminates the timer discarding any currently scheduled tasks.

The other six methods are overloaded schedule methods or overloaded scheduleAtFixedRate methods. As the names imply, all of these methods are used to schedule future tasks and the overloaded versions simply provide different ways to do that. Regardless of which method you use, you will need an object of the TimerTask class. That brings us to the next topic.

The TimerTask class

The TimerTask class has a single constructor that takes no parameters along with the three methods shown in Figure 5.

Figure 5. Methods of the TimerTask class as of MIDP 2.0.
  • cancel() - Cancels this timer task.
  • run() - The action to be performed by this timer task.
  • scheduledExecutionTime() - Returns the scheduled execution time of the most recent actual execution of this task

The names and the brief descriptions of the methods in Figure 5 are self-explanatory. We will be primarily interested in the abstract run method. We will extend the TimerTask class into a new class and override the run method to cause it to perform the desired action at the scheduled points in time.

That concludes the discussion and explanation of the boldface (non Italic) classes shown in Figure 1 that I promised earlier. Now it's time to examine the code that puts these classes to work.

Preview

In the remainder of this lesson, I will present and explain two MIDlets named Alert01 and Alert02. The primary differences between the two will be in the areas of alert type and Gauge mode.

Discussion and sample code

 
MIDlet testing
The MIDlets in this lesson were tested using a Java SE 6 compiler, targeted at a V1.4 virtual machine, and WTK 2.5.2 running under Windows XP.

The MIDlet named Alert01

The purpose of this MIDlet is to illustrate:

  • The use of an Alert user interface object.
  • The use of image files in conjunction with the Alert.
  • The use of a Timer to schedule the Alert for repeatedly becoming visible.
  • The use of a non-interactive Gauge as a progress meter.

Each time the Alert becomes visible, it obscures a TextBox object that is also being displayed by the MIDlet. When the Alert disappears, the TextBox reappears.

Requirements

This MIDlet requires:

  • The use of the newly updated MIDlet development framework named WTKFramework03.
  • An image file named redball.PNG in the source code directory.
  • An image file named blueball.PNG in the source code directory.

Image files

You can substitute any image files containing small images for the two image files listed above. You will have to make the names of your image files match the references to the image files in the code. Remember that file names referred to by Java code are case sensitive. The case of the reference to the image files in the code must match the actual case of the characters in the image file names.

The MIDlet will run properly in Sun's cell phone emulator for PNG, GIF, and JPEG image files so long as they are in the directory with the source code and they are properly referenced in the code. This restriction on location is imposed by the framework program named WTKFramework03 and is not imposed by MIDlet technology in general.

The alert type

This MIDlet uses an alert of type ALARM. This results in an audible alert that sounds like a telephone ringing when the MIDlet is run in the Sun cell phone emulator.

Different images are displayed

Each time the Alert becomes visible, it displays either a red ball or a blue ball, depending on whether the time in seconds is even or odd. A red ball is displayed for even values of time and a blue ball is displayed for odd values of time.

The Gauge

A Gauge is displayed with a definite range of zero to six bars as shown in Figure 2. A new bar changes from white to gray each time the Alert becomes visible.

Will discuss in fragments

As usual, I will discuss and explain this MIDlet in fragments. A complete listing of the MIDlet is provided in Listing 14.

The beginning of the MIDlet class named Alert01 including the constructor is shown in Listing 1.

Listing 1. Beginning of the MIDlet class named Alert01.
public class Alert01 extends MIDlet{
  Alert01 theMidlet;
  Image image;
  int count = 0;
  long baseTime;
  
  public Alert01(){
    System.out.println("Construct MIDlet");
    theMidlet = this;
    baseTime = new Date().getTime()/1000;
  }//end constructor

The baseTime variable is populated with the number of seconds that have elapsed since January 1, 1970.  This value will be used to compute elapsed time since the MIDlet started running at several locations in the MIDlet.  Otherwise, the code in Listing 1 is straightforward and shouldn't require further explanation.

Beginning of the startApp method in Alert01

The startApp method begins in Listing 2. Recall that this method is called by the Application Management Software (AMS) to cause the MIDlet to transition from the paused state to the active state. The MIDlet begins in the paused state when it is launched and constructed. Then the AMS calls the startApp method to cause the MIDlet to enter the paused state.

Listing 2. Beginning of the startApp method in Alert01.
  public void startApp(){
    System.out.println("Create and display a TextBox");

    TextBox textBox = new TextBox("TextBox Title",
                                  "TextBox contents",
                                  50,//width
                                  TextField.ANY);

    //Make the TextBox the current Displayable object.
    Display.getDisplay(this).setCurrent(textBox);

Create a TextBox and make it visible

The code in Listing 2 creates a TextBox object and causes it to be the current Displayable object.  The TextBox will be visible any time that the Alert is not visible.

Schedule a TimerTask

Listing 3 creates and schedules a TimerTask that will display and sound an alert repeatedly. The Alert first appears at two seconds (2000 milliseconds) in the future and repeats every three seconds (3000 milliseconds).

Listing 3. Schedule a TimerTask.
    Timer myTimer = new Timer();
    myTimer.schedule(new MyTimerTask(),2000,3000);

Remaining code in startApp method in Alert01

Then the startApp method sleeps for twenty seconds, following which it cancels the TimerTask and calls the destroyApp method to cause the MIDlet to transition to the destroyed state.

Listing 4. Remaining code in startApp method in Alert01.
    //Sleep for 20 seconds.
    try{Thread.currentThread().sleep(20000);
    } catch(Exception e){}

    //Cancel the timer.
    myTimer.cancel();

    //Enter the destroyed state.
    this.destroyApp(true);
  }//end startApp

The Alert will be displayed several times on a different thread during the twenty seconds that the thread containing the startApp method is sleeping.

The pauseApp and destroyApp methods in Alert01

The pauseApp and destroyApp methods are shown in Listing 5.

Listing 5. The pauseApp and destroyApp methods in Alert01.
  public void pauseApp(){
  }//end pauseApp

  public void destroyApp(boolean unconditional){
    System.out.println("Destroy MIDlet");
    notifyDestroyed();
  }//end destroyApp

For the sake of simplicity, this MIDlet makes no provisions for dealing with the possibility that the pauseApp method might be called by the AMS. Therefore, the pauseApp method is empty.

The destroyApp method displays a terminating message on the standard output device and calls the notifyDestroyed method to signal to the AMS that the MIDlet is entering the destroyed state.

Beginning of the MyTimerTask class

Listing 6 shows the beginning of the class named MyTimerTask, which extends the class named TimerTask including the beginning of the overridden run method. The run method in an object of this class is scheduled to run repeatedly by the code in Listing 3.

Listing 6. Beginning of the class named MyTimerTask in Alert01.
  class MyTimerTask extends TimerTask{
    long time;

    public void run(){
      System.out.println("Display an Alert");

      try{
        //Select among two image files on the basis of
        // whether the current time in seconds is odd
        // or even.
        time = new Date().getTime()/1000 - baseTime;

        //Note that the following file names are case
        // sensitive.
        if((time % 2) == 0){//Even value
          image = Image.createImage(
                                  "/Alert01/redball.PNG");
        }else{//Odd value
          image = Image.createImage(
                                 "/Alert01/blueball.PNG");
        }//end else

Listing 6 begins by computing and saving the time in seconds that have elapsed since the MIDlet object was first constructed when the MIDlet was launched.

Select an image file based on even or odd time value

Then, depending on whether that time value is even or odd, the code in Listing 6 creates an Image object based on one or the other of two image files of type PNG. If the time is even, the Image is created from the data in the file named redball.PNG. Otherwise, the Image is created from the data in the image file named blueball.PNG. It is important at this point to note that the file names used in the code are case sensitive and must match the actual file names.

Create and program an Alert object

Listing 7 creates an Alert object of type ALARM. This alert type results in an audible alarm that sounds like an old-fashioned telephone ringing when the MIDlet is executed in the Sun cell phone emulator.

Listing 7. Create and program an Alert object in Alert01.
        Alert alert = new Alert("Alert Title",
                                "",
                                image,
                                AlertType.ALARM);

        //Cause the alert to display the time in seconds.
        alert.setString("Time in seconds:" + time);

        //Cause the alert to be visible for two seconds.
        alert.setTimeout(2000);

After creating the Alert object, Listing 7 calls the setString method to set the text value displayed by the Alert to include some text plus the elapsed time since the MIDlet was constructed. Thus, each time the Alert becomes visible and the run method is executed, the time that is displayed is different.

Finally, Listing 7 calls the setTimeout method to establish the amount of time that the Alert will remain visible to 2000 milliseconds or two seconds.

The visible/non-visible cycle

Referring back to Listing 3, the Alert will be made visible every three seconds following an initial visibility at two seconds. Referring to Listing 7, the Alert will remain visible for two seconds each time it is made visible.

The TextBox object should initially be visible for two seconds. Then there should be a repeating pattern of the Alert being visible for two seconds followed by the TextBox being visible for one second.

At the end of twenty seconds:

  • The thread containing the startApp method will wake up.
  • The Timer will be cancelled
  • The MIDlet will enter the destroyed state.

If you run the MIDlet and watch closely, you should see time values of 2, 5, 8, 11, 14, and 17 displayed by the text in the Alert.

Create and service the Gauge

Listing 8 begins by creating a Gauge that shows six bars as shown in Figure 2.

Listing 8. Create and service the Gauge in Alert01.
        Gauge gauge = new Gauge(null,false,6,0);

        //Set the number of Gauge bars to be illuminated.
        gauge.setValue(++count);

        //Attach the Gauge to the alert.
        alert.setIndicator(gauge);

The variable named count is used to count the number of times that the run method of the TimerTask object has been executed. Each time the method is executed, it increments the counter by one and calls the setValue method on the Gauge to set the number of vertical bars that should be displayed in gray instead of white as shown in Figure 2.

Finally, Listing 8 calls the setIndicator method on the Alert object to attach the Gauge to the Alert object, producing the visual output shown in Figure 2.

Make the Alert visible

Listing 9 calls the setCurrent method on the Display object (that represents the cell phone display) to cause the Alert object to become the current Displayable object. This causes the Alert to be displayed on the cell phone screen.

Listing 9. Make the Alert visible in the MIDlet named Alert01.
        Display.getDisplay(theMidlet).setCurrent(alert);
      }catch(Exception e){
        e.printStackTrace();
      }//end catch
    }//end run
  }//end class MyTimerTask
}//end class Alert01

Listing 9 also signals the end of the run method, the end of the member class named MyTimerTask, and the end of the MIDlet class named Alert01.

The MIDlet named Alert02

As mentioned earlier, this MIDlet is very similar to the MIDlet named Alert01. Therefore, I will confine my explanation to the code that is different between the two and the results imparted by those code differences.

The purpose of this MIDlet is to illustrate:

  • The use of an Alert user interface object.
  • The use of image files in conjunction with the Alert object.
  • The use of a Timer to schedule the Alert for repeatedly becoming visible.
  • The use of a non-interactive Gauge as an activity meter.

A progress meter versus an activity meter

The big difference between the purpose of this MIDlet and the earlier MIDlet named Alert01 is in the difference between a progress meter and an activity meter. Whereas a progress meter shows progress toward a known goal as in Figure 2, an activity meter simply shows that the MIDlet is active toward reaching an undefined goal as in Figure 3.

A CONFIRMATION alert

This MIDlet uses an alert of type CONFIRMATION whereas the MIDlet named Alert01 uses an alert of type ALARM. When run in the Sun cell phone emulator, an alert type of type CONFIRMATION results in an audible alert consisting of a series of three chimes whereas an alert type ALARM results in the sound of an old-fashioned telephone ringing.

The GAUGE

For this MIDlet, a Gauge is displayed as:

Gauge.INDEFINITE, Gauge.INCREMENTAL_UPDATING

This requires that a maximum value of three be passed to the setValue method because only three graphics are displayed and they need to repeat for values greater than three. A new graphic is displayed each time the alert becomes visible. The first graphic has Duke doing a cartwheel. The second graphic has Duke rendered in black, white, and red. The third graphic has Duke rendered in gray, white, and red as shown in Figure 3.

Create an Alert object for the MIDlet named Alert02

The first major difference between the code in this MIDlet and the code in the earlier MIDlet named Alert01 occurs in Listing 10.

Listing 10. Create an Alert object for the MIDlet named Alert02.
        //Create an Alert object of type CONFIRMATION.
        // This results in an audible alert that is three
        // chimes.
        Alert alert = new Alert("Alert Title",
                                "",
                                image,
                                AlertType.CONFIRMATION);

As you can see in Listing 10, this MIDlet sets the alert type to CONFIRMATION. This results in an audible alert produced by the Sun cell phone emulator being a series of three chimes.

Referring back to Listing 7, you can see that the alert type for the previous MIDlet was ALARM. This results in an audible alert produced by the Sun cell phone emulator that sounds like an old-fashioned telephone ringing.

Create a Gauge for the MIDlet named Alert02

The next major difference in code between the two MIDlets is shown in Listing 11.

Listing 11. Create a Gauge for the MIDlet named Alert02.
        Gauge gauge = new Gauge(
                              null,
                              false,
                              Gauge.INDEFINITE,
                              Gauge.INCREMENTAL_UPDATING);

Whereas the previous MIDlet created a Gauge with a definite maximum value of 6 (see Listing 8), this MIDlet creates a Gauge object with a maximum value of INDEFINITE. This makes it possible to specify one of the values in the earlier list for the final parameter.

The last two parameters passed to the constructor for the Gauge class in Figure 11 cause a Gauge to be constructed that shows three repeating images of Duke when the MIDlet is run in the Sun cell phone emulator. The first image has Duke doing a cartwheel. The second image has Duke in black, white, and red. The third image has Duke in gray, white, and red as shown in Figure 3. Then the sequence repeats.

Set the current value of the Gauge to be count mod 3

The final difference in the code between the two MIDlets is shown in Listing 12. Whereas the code in the run method in the earlier MIDlet simply set the current value of the Gauge to be the value of count (see Listing 8), Listing 12 sets the current value to be count mod 3. This causes the current value to count from 0 to 2 and then repeat the sequence each time the value reaches 3.

Listing 12. Set the current value of the Gauge to be count mod 3.
        gauge.setValue(++count % 3);

The remaining code in the MIDlet named Alert02 is the same as the code in the MIDlet named Alert01.

Run the programs

I encourage you to copy the code from Listing 13, Listing 14, and Listing 15. Run the two MIDlets in the updated MIDlet development framework named WTKFramework03 that is provided Listing 13. Experiment with the MIDlet code, making changes and running your modified MIDlets in the framework program. See if you can explain the results produced by your changes.

Don't forget that you will need to download and install the latest version of the Sun Java Wireless Toolkit for CLDC (see Resources). As of the date this lesson is being written, the latest version of the toolkit is WTK2.5.2.

You will also need two small image files. You can substitute any image files containing small images for the two image files listed above. You will have to make the names of your image files match the references to the image files in the code (see Listing 6).

Summary

In this lesson you learned

  • How to program an Alert for a MIDlet.
  • How to add an image to the Alert.
  • How to add a Gauge to the Alert to act as a progress or activity meter.
  • How to use a Timer to control when an Alert becomes visible on the screen.

What's next?

In the next lesson, you will learn about the Choice interface and the List class, which implements the Choice interface. You will learn about the composition of a Choice object. You will learn about implicit, exclusive, and multiple Choice types. You will learn about the selected state of a Choice element of each of the different types. Finally, you will learn how to create a List, how to display it in the Sun cell phone emulator, and how to determine which elements in the List are selected.

Resources

Complete program listings

Complete listings of the programs discussed in this lesson are shown in Listing 13, Listing 14, and Listing 15 below:

Listing 13. The updated MIDlet development framework named WTKFramework03.
/*WTKFramework03.java
Copyright 2007, R.G.Baldwin

Updated: December 17, 2007

Version: WTKFramework03.java
Upgraded to prevent the deletion of image files and other 
resource files when the program cleans up after itself.
This results in resource files being included in the JAR 
file.  The resource files should be in the same directory 
as the source files.

Version: WTKFramework02.java
Upgraded to capture and display standard output and error
output from child processes.

Also upgraded to allow user to enter MIDlet name on the
command line.  This is particularly useful when repeatedly
running this program from a batch file during MIDlet
development.

Version: WTKFramework01.java
The purpose of this program is to provide a framework that
makes it easy to experiment with Java MIDlets written to
run on small mobile devices using the Sun Java Wireless
Toolkit (WTK2.5.2).  The framework not only makes such
experimentation easy, it also cleans up after itself by
automatically deleting all of the extraneous files created
during the development of the JAR and JAD files, which
are required for the deployment of the MIDlet program.

Given a file containing the source code for the MIDlet,
a single click of the mouse causes this framework to
automatically cycle through the following steps:

Compilation (targeted to Java v1.4 virtual machine)
Pre-verification
Creation of the manifest file
Creation of the JAR file
Creation of the JAD file
Deletion of extraneous files, saving the JAR and JAD files
Deployment and execution in Sun's cell phone emulator

The MIDlet being processed must be stored in a folder
having the same name as the main MIDlet class.  The
folder containing the MIDlet must be a child of the
folder in which the framework is being executed.

Note: When you transfer control to a new process window by
calling the exec method, the path environment variable
doesn't go along for the ride.  Therefore, you must
provide the full path for programs that you call in that
new process.

Tested using Java SE 6 and WTK2.5.2 running under
Windows XP.
*********************************************************/

import java.io.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class WTKFramework03{
  String toolkit = "M:/WTK2.5.2";//Path to toolkit root
  String vendor = "Dick Baldwin";//Default vendor name
  String midletVersion = "1.0.0";
  String profile = "MIDP-2.0";
  String profileJar = "/lib/midpapi20.jar";
  String config = "CLDC-1.1";
  String configJar = "/lib/cldcapi11.jar";
  //Path to the bin folder of the Java installation
  String javaPath = "C:/Program Files/Java/jdk1.6.0/bin";
  String prog = "WTK001";

  int initialCleanupOK = 1;//Success = 0
  int compileOK = 1;//Compiler success = 0
  int preverifyOK = 1;//Preverify success = 0
  int deleteClassFilesOK = 1;//Delete success = 0
  int moveFilesOK = 1;//Move success = 0
  int manifestFileOK = 1;//Manifest success = 0
  int jarFileOK = 1;//Jar file success = 0
  int jadFileOK = 1;//Jad file success = 0
  int cleanupOK = 1;//Cleanup success = 0

  long jarFileSize = 0;

  JTextField progName;
  JTextField WTKroot;
  JTextField vendorText;
  JTextField midletVersionText;
  JTextField javaPathText;

  JRadioButton pButton10;
  JRadioButton pButton20;
  JRadioButton pButton21;

  JRadioButton cButton10;
  JRadioButton cButton11;

  static WTKFramework03 thisObj;
  //----------------------------------------------------//

  public static void main(String[] args){
    //Allow user to enter the MIDlet name on the command
    // line.  Useful when running from a batch file.
    thisObj = new WTKFramework03();
    if(args.length != 0)thisObj.prog = args[0];
    thisObj.new GUI();
  }//end main
  //----------------------------------------------------//

  void runTheProgram(){
    //This method is called when the user clicks the Run
    // button on the GUI.
    System.out.println("PROGRESS REPORT");
    System.out.println("Running program named: " + prog);

    //This code calls several methods in sequence to
    // accomplish the needed actions. If there is a
    // failure at any step along the way, the
    // framework will terminate at that point with a
    // suitable error message.

    //Delete leftover files from a previous run, if any
    // exist
    deleteOldStuff();
    if(initialCleanupOK != 0){//Test for success
      System.out.println("Initial cleanup error");
      System.out.println("Terminating");
      System.exit(1);
    }//end if

    compile();//compile the MIDlet
    if(compileOK != 0){//Test for successful compilation.
      System.out.println("Terminating");
      System.exit(1);
    }//end if

    preverify();//Pre-verify the MIDlet class files
    if(preverifyOK != 0){
      System.out.println("Terminating");
      System.exit(1);
    }//end if

    //Delete the class files from the original program
    // folder
    deleteClassFilesOK = deleteProgClassFiles();
    if(deleteClassFilesOK != 0){
      System.out.println("Terminating");
      System.exit(1);
    }//end if

    //Move the preverified files back to the original
    // program folder
    movePreverifiedFiles();
    if(moveFilesOK != 0){
      System.out.println("Terminating");
      System.exit(1);
    }//end if

    //Make manifest file
    makeManifestFile();
    if(manifestFileOK != 0){
      System.out.println("Manifest file error");
      System.out.println("Terminating");
      System.exit(1);
    }//end if

    //Make Jar file
    makeJarFile();
    if(jarFileOK != 0){
      System.out.println("JAR file error");
      System.out.println("Terminating");
      System.exit(1);
    }//end if

    //Make Jad file
    makeJadFile();
    if(jadFileOK != 0){
      System.out.println("Terminating");
      System.exit(1);
    }//end if

    //Delete extraneous files
    cleanup();
    if(cleanupOK != 0){
      System.out.println("Terminating");
      System.exit(1);
    }//end if

    //Run emulator
    runEmulator();

    //Reset success flags
    initialCleanupOK = 1;//Success = 0
    compileOK = 1;//Compiler success = 0
    preverifyOK = 1;//Preverify success = 0
    deleteClassFilesOK = 1;//Delete success = 0
    moveFilesOK = 1;//Move success = 0
    manifestFileOK = 1;//Manifest success = 0
    jarFileOK = 1;//Jar file success = 0
    jadFileOK = 1;//Jad file success = 0
    cleanupOK = 1;//Cleanup success = 0

    //Control returns to here when the user terminates
    // the cell phone emulator.
    System.out.println(
      "\nClick the Run button to run another MIDlet.");
    System.out.println();//blank line

  }//end runTheProgram
  //----------------------------------------------------//

  //Purpose: Delete leftover files at startup
  void deleteOldStuff(){
    System.out.println(
           "Deleting leftover files from a previous run");

    //Delete subdirectory from output folder if it exists.
    int successFlag = deleteOutputSubDir();

    //Delete manifest file if it exists.
    File manifestFile = new File("output/Manifest.mf");
    if(manifestFile.exists()){
      boolean success = manifestFile.delete();
      if(success){
        System.out.println("   Manifest file deleted");
      }else{
        successFlag = 1;
      }//end else
    }//end if

    //Delete old JAR file if it exists.
    File jarFile = new File("output/" + prog + ".jar");
    if(jarFile.exists()){
      boolean success = jarFile.delete();
      if(success){
        System.out.println("   Old jar file deleted");
      }else{
        successFlag = 1;
      }//end else
    }//end if

    //Delete old JAD file if it exists.
    File jadFile = new File("output/" + prog + ".jad");
    if(jadFile.exists()){
      boolean success = jadFile.delete();
      if(success){
        Sy