MMS messages - MMS MIDlet

This section provides the source code for the SATSA MIDlet. For the complete Eclipse project ZIP file, see Forum Nokia.

The example includes the following classes:

MMSMIDlet

package mmsmidlet;

import java.io.*;
import javax.microedition.io.*;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.wireless.messaging.*;

// Main MIDlet class. It controls the user interface and the
// MMS connection
public class MMSMIDlet
  extends MIDlet
  implements MessageListener
{
  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 boolean closing;
  private Message nextMessage = null;
  
  
  public MMSMIDlet() {}
  
  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();
  }
  
  private synchronized void receive(Message incomingMessage) {
    if (receiveScreen==null) {
      receiveScreen = new ReceiveScreen(this);
    }
    receiveScreen.setMessage(incomingMessage);
    Display.getDisplay(this).setCurrent(receiveScreen);
  }
  
  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();		
  }
  
  void sendMessage(String recipientAddress,
      MessagePart imagePart, MessagePart textPart) {
    try {
      // 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());
          }
        }				
      }.start();
    } catch (SizeExceededException see) {
      showError("Message size is too big.");
    } catch (IllegalArgumentException iae) {
      showError("Phone number is missing.");
    }		
  }
  
  // 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) );
  }
  
  // Closes the message connection when the applications 
  // is stopped
  private void closeConnection() {
    closing = true;
  
    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();
    }
  }

}

CameraScreen

package mmsmidlet;

import javax.microedition.lcdui.*;
import javax.microedition.media.*;
import javax.microedition.media.control.*;
import java.io.IOException;

// 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);		
  }
  
  // Paint the canvas' background in black
  public void paint(Graphics g) {
  	// black background
  	g.setColor(0x00000000); 
  	g.fillRect(0, 0, getWidth(), getHeight());
  }
  
  public void commandAction(Command c, Displayable d) {
    if (c == exitCommand) {
      midlet.exitApplication();
    } else if (c == captureCommand) {
      captureImage();
    }
  }
  
  public void keyPressed(int keyCode) {
    if (getGameAction(keyCode) == FIRE) {
      captureImage();
    }
  }
  
  // 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

package mmsmidlet;

import javax.microedition.lcdui.*;

// Utility class used to show some information to the user
class InfoScreen
  extends Alert
{
  InfoScreen()  {
    super("InfoScreen");
  }

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

ReceiveScreen

package mmsmidlet;

import javax.microedition.lcdui.*;
import javax.wireless.messaging.*;

// 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;
  } 
  
  public void setMessage(Message mmsMessage)  {
    if (mmsMessage != null) {
      createForm(mmsMessage);
    }
  }  
   
  public void commandAction(Command c, Displayable d) {
    if (c==commandClose) {
      midlet.resumeDisplay();
    }
  }
  
  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);
  
      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);
  }
}

SendScreen

package mmsmidlet;

import java.io.*;
import javax.microedition.lcdui.*;
import javax.wireless.messaging.*;

// 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);
  }  
  
  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();
  }  
  
  public void commandAction(Command c, Displayable d) {
    if (c==commandBack) {
      midlet.showCameraScreen();
    }
  
    if (c==commandSend) {
      sendMMS();
    }
  }  
  
  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 containting 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 containting 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());
  	}
  }
}