Implementing the MIDlet main class

The EventSharingMIDlet class is the MIDlet main class. This class handles the following tasks:

  • Common startup events such as setting the default Display

  • Displaying the start-up screen as the MIDlet launches

  • Common MIDlet lifecycle tasks

  • Launching the EventCreationForm as the MIDlet starting view

  • Displaying error messages using the ErrorScreen

To implement the EventSharingMIDlet class:

  1. Create the EventSharingMIDlet.java class file.

  2. Import the required packages.

    import java.io.*;
    import javax.microedition.io.*;
    import javax.microedition.lcdui.*;
    import javax.microedition.midlet.*;
    import javax.wireless.messaging.*;
  3. Set EventSharingMIDlet to extend MIDlet and implement MessageListener. Create the required variables (note the hardcoded default port and the SMS prefix) and the class constructor.

    public class EventSharingMIDlet extends MIDlet implements MessageListener {
        private final static int DEFAULT_PORT = 6553;
        private final static String SMS_PREFIX = "sms://:";
    
        private final Image logo;
        private final EventCreationForm mainScreen;
    
        private int port;
        private MessageConnection conn;
        private OperationsQueue queue = new OperationsQueue();
        private final Display display;
    
        public EventSharingMIDlet() {
            // init basic parameters
            logo = makeImage("/logo.png");
            try {
                port = Integer.parseInt(getAppProperty("port"));
            } catch (Exception e) {
                // in case the property is missing or with a wrong format
                port = DEFAULT_PORT;
            }
            ErrorScreen.init(logo, Display.getDisplay(this));
            mainScreen = new EventCreationForm(this, port);
            display = Display.getDisplay(this);
        }
  4. Create a method for sending a message. The message is sent through a connection instance created with MessageConnection. Note the correct data types. The message content is sent as a byte[] data type and the destination address includes an sms:// prefix.

        void sendMessage(String number, byte[] text) {
            showMessage("Sending event " + "to number " + number);
            if (conn != null) {
                try {
                    // create a new message
                    BinaryMessage requestSMS = (BinaryMessage)conn.newMessage(MessageConnection.BINARY_MESSAGE);
                    String address = new StringBuffer("sms://").append(number).append(":").append(port).toString();
                    requestSMS.setAddress(address);
                    requestSMS.setPayloadData(text);
                    conn.send(requestSMS);
                } catch (IOException e) {
                    showMessage(e.getMessage());
                } catch (SecurityException e) {
                    showMessage(e.getMessage());
                }
            }
        }
  5. Handle the application startup duties in the startApp method. Use system property calls to verify that the PIM API is available on the device and to display the start-up screen while the MIDlet loads.

        public void startApp() {
            Displayable current = Display.getDisplay(this).getCurrent();
            if (current == null) {
                // check that the API is available
                boolean isAPIAvailable = (System.getProperty("microedition.pim.version") != null);
                // shows splash screen
                StringBuffer splashText = new StringBuffer(getAppProperty("MIDlet-Name")).append("\n")
                    .append(getAppProperty("MIDlet-Vendor")).append(isAPIAvailable ? "" : "\nPIM API not available");
                //Alert splashScreen = new Alert(null, splashText.toString(), logo, AlertType.INFO);
                //splashScreen.setTimeout(3000);
                if (!isAPIAvailable) {
                    //display.setCurrent(splashScreen, mainScreen);
                    display.setCurrent(mainScreen);
                } else {
                    //display.setCurrent(splashScreen, mainScreen);
                    display.setCurrent(mainScreen);

    Check if the class has been activated by an incoming message through PushRegistry. Continue to receive the message, display it, and close the connection after finished.

                    // List connections from PushRegistry
                    String smsConnections[] = PushRegistry.listConnections(true);
    
                    // Chech the connections. We'll assume only one is of interest
                    for (int i = 0; i < smsConnections.length; i++) {
                        if (smsConnections[i].startsWith(SMS_PREFIX)) {
                            try {
                                conn = (MessageConnection) Connector.open(smsConnections[i]);
                                BinaryMessage incomingMessage = (BinaryMessage)conn.receive();
                                showIncomingMessage(incomingMessage);
                                conn.close();
                            } catch (IOException e) {
                                showMessage(e.getMessage());
                            } catch (SecurityException e) {
                                showMessage(e.getMessage());
                            }
                        }
                    }
    
                    // Build the connection string
                    String connection = SMS_PREFIX + port;
                    try {
                        // Initiate the connection and add listener
                        conn = (MessageConnection) Connector.open(connection);
                        conn.setMessageListener(this);
                    } catch (IOException e) {
                        showMessage(e.getMessage());
                    } catch (SecurityException e) {
                        showMessage(e.getMessage());
                    }
                }
            } else {
                Display.getDisplay(this).setCurrent(current);
            }
        }
  6. Create the rest of the standard lifecycle methods: pauseApp and destroyApp.

        public void pauseApp() {
        }
    
        public void destroyApp(boolean unconditional) {
            try {
                // Close the connection on exit
                if (conn != null) {
                    conn.close();
                }
            } catch (IOException e) {
                // Ignore since we are closing anyway
            }
            queue.abort();
        }
  7. Create methods to notify the MIDlet when an inbound message is arriving through a MessageConnection and to display the IncomingEventForm when incoming event messages are received.

        // Asynchronous callback for inbound message.
        public void notifyIncomingMessage(MessageConnection conn) {
            if (conn == this.conn && conn != null) {
                try {
                    // Create a ReceiveScreen upon message removal
                    BinaryMessage incomingMessage = (BinaryMessage) conn.receive();
                    showIncomingMessage(incomingMessage);
                } catch (IOException e) {
                    showMessage(e.getMessage());
                } catch (SecurityException e) {
                    showMessage(e.getMessage());
                }
            }
        }
    
        void showIncomingMessage(BinaryMessage msg) {
            display.setCurrent(new IncomingEventForm(this, msg));
        }
  8. Create the rest of the MIDlet methods. These include methods for displaying errors with an ErrorScreen, a contacts list callback, and an image creation method called earlier in the class.

        void showMessage(String message) {
            ErrorScreen.showError(message, mainScreen);
        }
    
        void showMessage(String message, Displayable mainScreen) {
            ErrorScreen.showError(message, mainScreen);
        }
    
        // adds an operation the queue
        void enqueueOperation(Operation operation) {
            queue.enqueueOperation(operation);
        }
    
        // shows the main screen
        void showMain() {
            display.setCurrent(mainScreen);
        }
    
        // shows the contacts list screen
        void showContactsList() {
            display.setCurrent(new ContactListForm(EventSharingMIDlet.this));
        }
    
        // callback from contacts list when a particular
        // telephone number has been selected
        void contactSelected(String telephoneNumber) {
            mainScreen.setTargetPhoneNumber(telephoneNumber);
            showMain();
        }
    
        // loads a given image by name
        static Image makeImage(String filename) {
            Image image = null;
            try {
                image = Image.createImage(filename);
            } catch (Exception e) {
                // use a null image instead
            }
            return image;
        }
    }

Now that you have implemented the MIDlet main class, implement an operations queue for sending and receiving event messages.