Implementing the main MIDlet

EventSharingMIDlet class

This is the main class of the MIDlet; it initializes the MIDlet and handles transitions between different screens. All SMS handling is done in this class as well, including MessageConnection creation, reception of incoming messages, and sending of new messages. At startup, this class also checks if it has been awakened via PushRegistry because of an incoming message.

The class contains an OperationsQueue instance, which is used by other classes to execute PIM-related operations in a separate thread.

To create this class:

  1. Create the EventSharingMIDlet class file.

  2. Import the required classes.

    import java.io.*;
    import java.util.*;
    import javax.microedition.io.*;
    import javax.microedition.lcdui.*;
    import javax.microedition.midlet.*;
    import javax.microedition.pim.*;
    import javax.wireless.messaging.*;
  3. Set the EventSharingMIDlet class to extend MIDlet and to implement MessageListener. Create a new OperationsQueue instance (see class OperationsQueue). Initialize basic parameters.

    // Main class of the EventSharing MIDlet
    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 Message nextMessage;
      private OperationsQueue queue = new OperationsQueue();
      private final static int CONTACTS_LIST_OP = 0;
      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 the logic for sending new messages.

      void sendMessage(String number, byte[] text)
      {
        showMessage("Going to send the mgs " + text + " " + conn);
        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. Implement the functionality for the startApp() method. At startup, the class checks whether it has been awakened via PushRegistry because of an incoming message.

    The system property microedition.pim.version is checked in order to verify that the PIM API is actually available on the device. If the package is available, this property will contain the version of the API available, currently version 1.0, otherwise it will be null.

      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);
          }
          else
          {
            display.setCurrent(splashScreen, mainScreen);
            // List connections from PushRegistry
            String smsConnections[] = PushRegistry.listConnections(true);
    
            // Check 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);
        }
      }
    
      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();
      }
  6. Create the logic for handling incoming messages.

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