Implementing the UI elements

SendScreen class

This screen contains the form for composing the message to be sent. When the Send command is invoked, it creates the image and text parts of the message and delegates the sending to the main class.

  1. Create the SendScreen class file.

  2. Import the required classes.

    package mmsmidlet;
    import java.io.*;
    import javax.microedition.lcdui.*;
    import javax.wireless.messaging.*;
    
    
  3. Set the SendScreen class to extend Form and to implement CommandListener. Define the constants and Commands used by the application and create the constructor.

    // This form displays the content of the captured image
    // and fields to add the recipient address and the
    // text of the message
    class SendScreen
      extends Form
      implements CommandListener {
      private final MMSMIDlet midlet;
      
      private final Command commandSend =
        new Command("Send", Command.ITEM, 1);
      private final Command commandBack =
        new Command("Back", Command.BACK, 0);
      
      private TextField messageText;
      private TextField recipientPhone;
      private byte[] messageImage; 
      
      SendScreen(MMSMIDlet midlet) {
         super("MMS Message");
         this.midlet = midlet;
         addCommand(commandSend);
         addCommand(commandBack);
      
         setCommandListener(this);
      }  
      
    
  4. Create a method for initializing the message composing area.

      void initializeComposeCanvas(byte[] pngImage) {
        messageText = new TextField("Text: ",
            null,
            256,
            TextField.ANY);
        recipientPhone = new TextField("To: ",
            null,
            256,TextField.PHONENUMBER);
        messageImage = pngImage;
        Image tempImage = Image.createImage(pngImage,
            0,
            pngImage.length);
        ImageItem imageItem = new ImageItem(null,
            tempImage,
            Item.LAYOUT_CENTER,
            null);
     
        deleteAll();     
            append(messageText);
            append(recipientPhone);
            append(imageItem);
      
            midlet.showSendScreen();
      }
      
    
  5. Create a method for detecting the use of commands.

      public void commandAction(Command c, Displayable d) {
        if (c==commandBack) {
          midlet.showCameraScreen();
        }
      
        if (c==commandSend) {
          sendMMS();
        }
      }  
      
    
  6. Create a method that sends the MMS to the recipient. The SizeExceededException indicates that an operation is not executable due to insufficient system resources.

    For more information, see SizeExceededException in the WMAPI 2.0 specification.

      private void sendMMS() {
        String recipientAddress = "mms://"
          + recipientPhone.getString() + ":"
          + midlet.getApplicationID();
      
        try {
          // get the byte content of the message and 
          // the captured image
          byte[] textBytes = messageText.getString()
            .getBytes("UTF-8");
          byte[] imageBytes = messageImage;
      
          // Create the message part containing the image
          // and give the appropriate MIME-type and id
          MessagePart imagePart= new MessagePart(imageBytes,
            0,
            imageBytes.length,
            "image/jpeg",
            "id0",
            "snapshot image",
            null);
      
            // Create the message part containing the text
            // and give the appropriate MIME-type and id
          MessagePart textPart= new MessagePart(textBytes,
            0,
            textBytes.length,
            "text/plain",
            "id1",
            "message text",
            "UTF-8");
      
            midlet.showInfo("Sending message...");
            midlet.sendMessage(recipientAddress, imagePart, textPart);
        } catch (UnsupportedEncodingException uee) {
            midlet.showError("Encoding not supported. "
              + uee.getMessage());
         } catch (SizeExceededException see) {
            midlet.showError("Message part is too big. "
                + see.getMessage());
         }
      }
    }

ReceiveScreen class

This screen is activated when a new message arrives. The MMS message has already been read by the main class and passed to ReceiveScreen for parsing.

  1. Create the ReceiveScreen class file.

  2. Import the required classes.

    package mmsmidlet;
    import javax.microedition.lcdui.*;
    import javax.wireless.messaging.*;
    
    
  3. Set ReceiveScreen to extend Form and implement CommandListener. Define the constants, commands and classes used by the application and create the constructor.

    // Form used to display the contents of a received message
    class ReceiveScreen
      extends Form
      implements CommandListener {
      private String[] connections;
      private final MMSMIDlet midlet;
      private final Command commandClose =
        new Command("Close", Command.ITEM, 1);
      
      ReceiveScreen(MMSMIDlet midlet) {
        super(null);
        this.midlet = midlet;
      } 
      
    
  4. Create a method for initializing the Message object.

      public void setMessage(Message mmsMessage)  {
        if (mmsMessage != null) {
          createForm(mmsMessage);
        }
      }  
       
    
  5. Create a method for detecting the use of Commands.

      public void commandAction(Command c, Displayable d) {
        if (c==commandClose) {
          midlet.resumeDisplay();
        }
      }
      
    
  6. Create the method for building the form used by the message. The getAddress method returns the address associated with this message. The getTimestamp method returns the timestamp indicating when this message has been sent.

    For more information, see getAddress and getTimestamp in the WMAPI 2.0 specification.

      private void createForm(Message mmsMessage) {
        deleteAll();  
        setTitle("Received MMS Message");
      
        if (mmsMessage instanceof MultipartMessage) {
          MultipartMessage  multipartMessage =
            (MultipartMessage) mmsMessage;
      
          // Display message header.
          StringItem messageHeader = new StringItem(null,
              "From: " + mmsMessage.getAddress() + "\n" +
              "Sent: " + multipartMessage.getTimestamp().toString());
          messageHeader.setLayout(Item.LAYOUT_NEWLINE_AFTER);
          append(messageHeader);
      
    

    The getMessageParts method returns an array of all MessageParts of this message. The getMIMEType method returns the mime type of the MessagePart. The getContentLocation method returns content location of the MessagePart, whereas the getContent method returns the content of the MessagePart as an array of bytes.

    For more information about these methods, see the WMAPI 2.0 specification.

          MessagePart[] messageParts = multipartMessage.getMessageParts();
      
          // Display all parts of the message.
          for (int i = 0; i < messageParts.length; i++) {
            MessagePart messagePart = messageParts[i];
            String mimeType = messagePart.getMIMEType();
            String contentLocation = messagePart.getContentLocation();
     
            byte[] part = messagePart.getContent();
      
            if (mimeType.equals("image/jpeg")) {
              // Message contains an image.
              Image image = Image.createImage(part, 0, part.length);
              ImageItem imageItem = new ImageItem(null,
                  image,
                  Item.LAYOUT_CENTER + Item.LAYOUT_NEWLINE_AFTER,
                  contentLocation);
              append(imageItem);
            }
            if (mimeType.equals("text/plain")) {
              // Message contains text.
              StringItem stringItem = new StringItem(null,
                  new String(part));
              stringItem.setLayout(Item.LAYOUT_CENTER);
              append(stringItem);
            }
            // Unknown MIME-types are ignored
          }
        }
      
        addCommand(commandClose);
        setCommandListener(this);
      }

CameraScreen class

This class is for capturing the image. The actual capturing runs in its own thread. Once the image has been captured, the main class method imageCaptured is called.

  1. Create the CameraScreen class file.

  2. Import the required classes.

    package mmsmidlet;
    import javax.microedition.lcdui.*;
    import javax.microedition.media.*;
    import javax.microedition.media.control.*;
    import java.io.IOException;
    
    
  3. Set the CameraScreen class to extend Canvas and implement CommandListener. Define the constants, commands and objects used by the application and create the constructor.

    // The CameraScreen class shows the live view
    // of the camera using the MMAPI and gives
    // commands to capture the contents of the camera
    class CameraScreen
      extends Canvas
      implements CommandListener {
      private final MMSMIDlet midlet;
      private final Command exitCommand;
      private Player player = null;
      private Command captureCommand = null;
      private VideoControl videoControl = null;
      private boolean active = false;
      CameraScreen(MMSMIDlet midlet) {
        this.midlet = midlet;
      
        // Builds the user interface
        exitCommand = new Command("Exit", Command.EXIT, 1);
            addCommand(exitCommand);
            captureCommand = new Command("Capture", Command.SCREEN, 1);
            addCommand(captureCommand);
            setCommandListener(this);      
      }
      
    
  4. Paint the background of the Canvas black.

      // Paint the canvas' background in black
      public void paint(Graphics g) {
         // black background
         g.setColor(0x00000000); 
         g.fillRect(0, 0, getWidth(), getHeight());
      }
      
    
  5. Create a method for detecting the use of Commands.

      public void commandAction(Command c, Displayable d) {
        if (c == exitCommand) {
          midlet.exitApplication();
        } else if (c == captureCommand) {
          captureImage();
        }
      }
      
    
  6. Create a method for detecting key presses.

      public void keyPressed(int keyCode) {
        if (getGameAction(keyCode) == FIRE) {
          captureImage();
        }
      }
      
    
  7. Create a method for building and starting the video player.

      // Creates and starts the video player
      synchronized void start() {
        try {
           player = Manager.createPlayer("capture://video");
           player.realize();
      
           // Get VideoControl for the viewfinder
           videoControl = (VideoControl)player.getControl("VideoControl");
           if (videoControl == null) {
             discardPlayer();
             midlet.showError("Cannot get the video control.\n"
                 +"Capture may not be supported.");
             player = null;
           } else {
             // Set up the viewfinder on the screen.
             videoControl.initDisplayMode(VideoControl.USE_DIRECT_VIDEO,
                 this);
             int canvasWidth = getWidth();
             int canvasHeight = getHeight();
             int displayWidth = videoControl.getDisplayWidth();
             int displayHeight = videoControl.getDisplayHeight();
             int x = (canvasWidth - displayWidth) / 2;
             int y = (canvasHeight - displayHeight) / 2;
             videoControl.setDisplayLocation(x, y);
             player.start();
             videoControl.setVisible(true);
           }
        } catch (IOException ioe) {
          discardPlayer();
          midlet.showError("IOException: " + ioe.getMessage());
        } catch (MediaException me) {
          midlet.showError("MediaException: " + me.getMessage());
        } catch (SecurityException se) {
          midlet.showError("SecurityException: " + se.getMessage());
        }
      }
      
      // Stops the video player
      synchronized void stop() {
        if (player != null) {
          try {
            videoControl.setVisible(false);
            player.stop();
          } catch (MediaException me) {
            midlet.showError("MediaException: " + me.getMessage());
          }
          active = false;
        }
      }
      
      // this method will discard the video player
      private void discardPlayer() {
        if (player != null) {
          player.deallocate();
          player.close();
          player = null;
        }
        videoControl = null;
      }
      
      // captures the image from the video player
      // in a separate thread
      private void captureImage() {
        if (player != null) {
          // Capture image in a new thread.
          new Thread() {
            public void run() {
              try {
                byte[] jpgImage =
                  videoControl.getSnapshot("encoding=jpeg");
                midlet.imageCaptured(jpgImage);
                discardPlayer();
              } catch (MediaException me) {
                midlet.showError("MediaException: " + me.getMessage());
              } catch (SecurityException se) {
                midlet.showError("SecurityException: " + se.getMessage());
              }
            }
          }.start();
        }
      }
    }
    

InfoScreen class

This is a simple utility screen that displays information and error messages.

  1. Create the InfoScreen class file.

  2. Import the required classes.

    package mmsmidlet;
    import javax.microedition.lcdui.*;
    
    
  3. Set the InfoScreen class to extend Alert. Create the constructor.

    // Utility class used to show some information to the user
    class InfoScreen
      extends Alert
    {
      InfoScreen()  {
        super("InfoScreen");
      }
    
    
  4. Create methods for showing the INFO and ERROR AlertTypes.

      void showInfo(String message, Display display) {
        setTitle("Info");
        setType(AlertType.INFO);
        setTimeout(3000);
        setString(message);
        display.setCurrent(this);
      }
       
      void showError(String message, Display display) {
         setTitle("Error");
         setType(AlertType.ERROR);
         setTimeout(5000);
         setString(message);
         display.setCurrent(this);
      }
    }