Implementing the MIDlet main class

The MIDlet main class controls the state changes between the MIDlet UI screens. It also owns the message connection and registers itself as a message listener waiting for incoming messages. When a message needs to be sent, the sendMessage method launches a new thread that takes care of sending the message. The application ID used for the connection in both ends is also defined in the MIDlet main class.

Note: On current Series 40 and Symbian devices, MMS messages are received in the inbox of the device's default messaging client. The MMSMIDlet cannot therefore display received messages.

To implement the MIDlet main class:

  1. Create the MMSMIDlet.java class file.

  2. Import the required classes.

    import java.io.IOException;
    import javax.microedition.io.Connector;
    import javax.microedition.lcdui.Display;
    import javax.microedition.lcdui.Displayable;
    import javax.microedition.midlet.MIDlet;
    import javax.wireless.messaging.*;

    For the Series 40 full touch version of the MIDlet, the required classes are as follows:

    import com.nokia.mid.ui.orientation.Orientation;
    import com.nokia.mid.ui.orientation.OrientationListener;
    import java.io.IOException;
    import javax.microedition.io.Connector;
    import javax.microedition.lcdui.Display;
    import javax.microedition.lcdui.Displayable;
    import javax.microedition.midlet.MIDlet;
    import javax.wireless.messaging.*;
  3. Set MMSMIDlet to extend MIDlet and implement MessageListener. The MIDlet uses the MessageListener interface to receive notifications of incoming messages.

    public class MMSMIDlet extends MIDlet implements MessageListener {

    The Series 40 full touch version of the MIDlet also implements OrientationListener.

    public class MMSMIDlet extends MIDlet implements MessageListener, OrientationListener {
  4. Create the required variables, and create the MMSMIDlet class constructor.

        private final String APPLICATION_ID = "mmsdemo";
        private CameraScreen cameraScreen = null;
        private ReceiveScreen receiveScreen;
        private SendScreen sendScreen;
        private InfoScreen infoScreen;
        private Displayable resumeDisplay = null;
        private MessageConnection messageConnection;
        private Message nextMessage = null;
    
        public MMSMIDlet() {
        }

    The MessageConnection interface defines the basic functionality for sending and receiving messages. It contains methods for sending and receiving messages, factory methods to create a new Message object, and a method that calculates the number of segments of the underlying protocol that are needed to send a specified Message object. Message is the base interface for derived interfaces that represent various types of messages.

  5. Define the mandatory lifecycle methods for starting, pausing, and destroying the MIDlet.

        public void startApp() {
            if (resumeDisplay == null) {
                // Start the MMS connection
                startConnection(this);
                // Create the user interface
                cameraScreen = new CameraScreen(this);
                infoScreen = new InfoScreen();
                sendScreen = new SendScreen(this);
                Display.getDisplay(this).setCurrent(cameraScreen);
    
                resumeDisplay = cameraScreen;
                cameraScreen.start();
            } else {
                Display.getDisplay(this).setCurrent(resumeDisplay);
            }
        }
    
        public void pauseApp() {
            if (Display.getDisplay(this).getCurrent() == cameraScreen) {
                cameraScreen.stop();
            }
        }
    
        public void destroyApp(boolean unconditional) {
            if (Display.getDisplay(this).getCurrent() == cameraScreen) {
                cameraScreen.stop();
            }
        }
    
        void exitApplication() {
            closeConnection();
            destroyApp(false);
            notifyDestroyed();
        }
  6. For the Series 40 full touch version of the MIDlet, in the startApp method, to detect display orientation changes, register an OrientationListener using the static Orientation.addOrientationListener method provided by the Orientation API.
        public void startApp() {
            Orientation.addOrientationListener(this);
            // Same startApp code as in the preceding step
    

    Note: The Orientation API is supported from Java Runtime 2.0.0 for Series 40 onwards.

  7. Create a method for receiving incoming messages.

        private synchronized void receive(Message incomingMessage) {
            if (receiveScreen == null) {
                receiveScreen = new ReceiveScreen(this);
            }
            receiveScreen.setMessage(incomingMessage);
            Display.getDisplay(this).setCurrent(receiveScreen);
        }
  8. Implement the notifyIncomingMessage callback method for incoming messages. This method starts a new thread for receiving the message.

        public void notifyIncomingMessage(MessageConnection conn) {
            // Callback for inbound message.
            // Start a new thread to receive the message.
            new Thread() {
    
                public void run() {
                    try {
                        Message incomingMessage = messageConnection.receive();
                        // this may be called multiple times if
                        // multiple messages arrive simultaneously
                        if (incomingMessage != null) {
                            receive(incomingMessage);
                        }
                    } catch (IOException ioe) {
                        showError("Exception while receiving message: "
                                + ioe.getMessage());
                    }
                }
            }.start();
        }
  9. Create a method for sending a message.

        void sendMessage(String recipientAddress, MessagePart imagePart,
                MessagePart textPart) {
            try {
    
                if (messageConnection != null) {
                    // The MMS message is constructed here.
                    // It is a multipart message consisting of two parts:
                    // image and text.
                    MultipartMessage mmsMessage
                        = (MultipartMessage) messageConnection.newMessage(MessageConnection.MULTIPART_MESSAGE);
                    mmsMessage.setAddress(recipientAddress);
                    mmsMessage.addMessagePart(imagePart);
                    mmsMessage.addMessagePart(textPart);
    
                    nextMessage = mmsMessage;
    
                    // Send the message in another thread
                    new Thread() {
    
                        public void run() {
                            try {
                                messageConnection.send(nextMessage);
                            } catch (IOException ioe) {
                                showError("Exception while sending message: "
                                        + ioe.getMessage());
                            } catch (SecurityException se) {
                                showError("SecurityException: " + se.getMessage());
                            }
                        }
                    }.start();
                } else {
                    showError("Sending failed");
                }
            } catch (SizeExceededException see) {
                showError("Message size is too big.");
            } catch (IllegalArgumentException iae) {
                showError("Phone number is missing.");
            }
        }

    The MultipartMessage interface represents a multipart message into which instances of the MessagePart class can be added. The newMessage method constructs a new message object of a given type. The setAddress method sets the destination ("To") address associated with the message. The addMessagePart method attaches a MessagePart to the multipart message.

  10. Create utility methods for retrieving the application ID and managing the different UI screens.

        // Return the application id, either from the
        // jad file or from a hardcoded value.
        String getApplicationID() {
            String applicationID = this.getAppProperty("Application-ID");
            return applicationID == null ? APPLICATION_ID : applicationID;
        }
    
        // Upon capturing an image, show the compose screen
        void imageCaptured(byte[] imageData) {
            cameraScreen.stop();
            resumeDisplay = sendScreen;
            Display.getDisplay(this).setCurrent(sendScreen);
            sendScreen.initializeComposeCanvas(imageData);
        }
    
        // Shows the screen capture camera
        void showCameraScreen() {
            resumeDisplay = cameraScreen;
            Display.getDisplay(this).setCurrent(cameraScreen);
            cameraScreen.start();
        }
    
        // Shows the incoming message screen
        void showReceiveScreen() {
            resumeDisplay = receiveScreen;
            Display.getDisplay(this).setCurrent(receiveScreen);
        }
    
        void showSendScreen() {
            resumeDisplay = sendScreen;
            Display.getDisplay(this).setCurrent(sendScreen);
        }
    
        void resumeDisplay() {
            Display.getDisplay(this).setCurrent(resumeDisplay);
        }
    
        // Displays the info screen
        void showInfo(String messageString) {
            infoScreen.showInfo(messageString, Display.getDisplay(this));
        }
    
        // Displays the error screen
        void showError(String messageString) {
            infoScreen.showError(messageString, Display.getDisplay(this));
        }
  11. Create methods for starting and closing the message connection. The setMessageListener method registers a MessageListener object that the platform can notify when a message has been received on this MessageConnection.

        // Closes the message connection when the applications
        // is stopped
        private void closeConnection() {
    
            if (messageConnection != null) {
                try {
                    messageConnection.close();
                } catch (IOException ioe) {
                    // Ignore errors on shutdown
                }
            }
        }
    
        // Starts the message connection object
        private void startConnection(final MMSMIDlet mmsmidlet) {
            if (messageConnection == null) {
                // Open connection in a new thread so that it doesn't
                // block if a security permission request is shown
                new Thread() {
    
                    public void run() {
                        try {
                            String mmsConnection = "mms://:" + getApplicationID();
                            messageConnection = (MessageConnection) Connector.open(mmsConnection);
                            messageConnection.setMessageListener(mmsmidlet);
                        } catch (IOException ioe) {
                            showError("Exception while opening message connection: "
                                    + ioe.getMessage());
                        }
                    }
                }.start();
            }
        }
  12. In the Series 40 full touch version of the MIDlet, implement the OrientationListener by defining the displayOrientationChanged method. The method is called every time the display orientation changes. Use the displayOrientationChanged method to set the UI orientation by calling the static Orientation.setAppOrientation method.

        public void displayOrientationChanged(int newDisplayOrientation) {
    
            // No Orientation when in camera screen
            if (Display.getDisplay(this).getCurrent() == cameraScreen) {
                return;
            }
    
            /**
             * Change MIDlet UI orientation to portrait
             */
            Orientation.setAppOrientation(newDisplayOrientation);
    
        }
    }

    Note: The Orientation API is supported from Java Runtime 2.0.0 for Series 40 onwards.

    Note: To adjust the MIDlet UI orientation using the Orientation API, declare the Nokia-MIDlet-App-Orientation JAD attribute with the value manual in the MIDlet JAD file:

    Nokia-MIDlet-App-Orientation: manual

Now that you have implemented the MIDlet main class, implement the UI elements.