I.Giới thiệu

Wireless Messaging API 2.0 là một gói tùy chọn của J2ME. Nó được sử dụng để truy cập vào tài nguyên giao tiếp không dây như SMS(Short Message Service), CBS(Cell Broadcast Service) và MMS(Multimedia Messaging Service). Chức năng chính của nó là gửi MMS bao gồm: audio, text, image và video. Messaging API dựa trên GCF(Generic Collection Framework) được định nghĩa trong đặc tả CLDC.

Ban đầu, WMA được giới thiệu trong J2ME, đó là WMA 1.1 thuộc JSR 120. Sự khác nhau giữa bản 1.1 và 2.0 là hỗ trợ thêm Multi-part message sử dụng cho MMS.

II.Các gói hỗ trợ

javax.microedition.io: gói này bao gồm các interface network đã được sửa đổi để sử dụng platform có hỗ trợ kết nối message.

javax.wireless.messaging: gói này định nghĩa các API cho phép các ứng dụng gửi và nhận message. Gói này bao gồm các interface và class sau:

BinaryMessage: giao diện sử dụng cho message nhị phân.

Message: đây là giao diện cơ bản để các giao diện các kế thừa.

MessageConnection: giao diện sử dụng để gửi và nhận tin nhắn.

MessageListener: giao diện này sử dụng để thông báo khi có các message đến.

MultipartMessage: giao diện này sử dụng cho các message multipart.

TextMessage: giao diện sử dụng cho message text.

MessagePart: lớp này được sử dụng để thêm vào instance của MessagePart vào MultipartMessage.

1.Giao diện Message

Là kiểu cơ bản cho tất cả các message giao tiếp sử dụng WMA 2.0 – một Message chứa: địa chỉ nguồn, địa chỉ đích và payload.

Một số phương thức dùng để nhận và thiết lập địa chỉ nguồn và địa chỉ đích của message, và nhận timestamp của nó.

String getAddress();
void setAddress(String address);
Date getTimestamp();

WMA 2.0 định nghĩa 3 giao diện con của Message:

2.BinaryMessage

Giao diện con BinaryMessage đại diện cho một message với một payload binary, và có thể được gửi như là một SMS. Giao diện này khai báo các phương thức để nhận và thiết lập payload nhịn phân như là một mảng byte.

byte[] getPayloadData();
void setPayloadData(byte[] bytes);

3.TextMessage

Giao diện con TextMessage đại diện cho một với một payload text và có thể được gửi đi như là một SMS. Giao thức này cung cấp các phương thức để nhận và thiết lập chuỗi text.

String getPayloadText();
void setPayloadText(String data);

4.MultipartMessage

MultipartMessage subinterface as the name suggests represents a message that consists of multiple parts, mainly an MMS-based multimedia message. It defines a combination of one or more MessageParts, and provides methods to manage the sender and recipient addresses, message’s headers, “start message” content ID, and the message’s parts: The methods available are:

Giao diện con MultipartMessage đại diện cho một message bao gồm nhìu phần, trong đó chủ yếu là MMS. Nó tạo ra sự kết hợp giữa một hay nhiều MessagePart, và cung cấp các phương thức để quản lý người gửi và địa chỉ người nhận, header của message, contentID.

boolean addAddress(String type, String address);
void addMessagePart(MessagePart messagePart) throws sizeExceededException;
String getAddress();
String[] getAddresses(String type);
String getHeader(String headerField);
MessagePart getMessagePart(String contentID);
MessagePart[] getMessageParts();
String getStartContentId();
String getSubject();
boolean removeAddress(String type, String address);
void removeAddresses();
void removeAddresses(String type);
boolean removeMessagePart(MessagePart messagePart);
boolean removeMessagePartId(String contentID);
boolean removeMessagePartLocation(String contentLocation);
void setAddress(String address);
void setHeader(String headerField, String headerValue);
void setStartContentId(String contentID);
void setSubject(String subject);

Nhiều phần dữ liệu thông điệp theo các định dạng tiêu chuẩn email, trong đó bao gồm header dựa trên RFC822 và nhiều phần dựa trên chuẩn MIME( Internet Mail Extensions) của World Wide Web Consortium (W3C) tại RFC2045 và RFC2046, như trong hình dưới đây.

Giao diện MultipartMessage đại diện cho phần thân và header của multimedia của nó, còn lớp MessagePart đại diện cho MIME.

5.Lớp MessagePart

Lớp MessagePart đại diện cho một phần của message, cung cấp các phương thức để nhận nội dung và các thông tin liên quan đến nội dung.

MessagePart(byte[] contents, int offset, int length, String mimeType, String contentId, String contentLocation, String encoding) throws SizeExceededException;
MessagePart(byte[] contents, String mimeType, String contentId, String contentLocation, String encoding) throws SizeExceededException;
MessagePart(java.io.InputStream is, String mimeType, String contentId, String contentLocation, String encoding) throws IOException, SizeExceededException;
public byte[] getContent();
public InputStream getContentAsStream();
public String getContentID();
public String getContentLocation();
public String getEncoding();
public int getLength();
public String getMIMEType();

A message part consists of a MIME type as defined in RFC2046, a content ID, a content location, and the content itself.

MessagePart đại diện cho một kiểu MIME  được định nghĩa trong RFC2046, đó là content ID, content location và content của chính nó.

6.MessageConnection

MessageConnection defines methods for creating TextMessages, BinaryMessages, and MultipartMessages, method to calculate the number of protocol segments needed for sending the message, methods to receive and send messages, and a method to set the message listener for this connection. The application opens a MessageConnection with the Generic Connection Framework by providing a URL connection string. The methods available are:

MessageConnection định nghĩa các phương thức để tạo TextMessage, BinaryMessage và MultipartMessage, đông thời tính toán số lượng các segment giao thức cần thiết để gửi thông điệp, các phương thức để gửi và nhận thông điệp, và một phương thức thiết lập message listener cho kiểu kết nối này. Ứng dụng mở một MessageConnection với GCF(Generic Connection Framework) bằng cách cung cấp một chuỗi URL. Các phương thức đó là:

Message newMessage(String type, String address);
int numberOfSegments(Message message);
Message receive() throws IOException, InterruptedIOException;
void send(Message message) throws IOException, InterruptedIOException;
void setMessageListener(MessageListener messageListener) throws IOException;

Ngoài ra, nó còn định nghĩa các constant được sử dụng để xác định kiểu của thông điệp thông qua phương thức newMessage(…)

String TEXT_MESSAGE = “text_msg”;
String BINARY_MESSAGE = “binary_msg”;
String MULTIPART_MESSAGE = “multipart_msg”;

Khi tạo MessageConnection, phải lưu ý rằng cần phải sử dụng một trong các kiểu constant kể trên, ví dụ:

mmsconnection = (MessageConnection)Connector.open(address);

MultipartMessage mmmessage

=  (MultipartMessage)mmsconnection.newMessage(MessageConnection.MULTIPART_MESSAGE);

mmmessage.setAddress(address);

mmsconnection.send(mmmessage);


MessageConnection có thể được mở và đóng thông qua 2 phương thức sau: javax.microedition.io.Connector.open() and javax.microedition.io.Connection.close().

Sự cấp phép

WMA sử dụng cơ chế bảo mật nằm bên dưới platform như mở kết nối hay gửi và nhận thông điệp, và sự cấp phép là bắt buộc bởi ứng dụng và platform. Trong MIDP 2.0, sự cấp phép được yêu cầu trong JAD hay manifest, và được sự chấp thuận của người dùng khi thao tác này được thực hiện. Đối với các ứng dụng đã được đăng ký, sự cấp phép được định nghĩa trong manifest.

Một ngoại lệ SecurityException sẽ được ném một trong các trường hợp sau:

javax.microedition.io.Connector nếu ứng dụng chưa được cấp phép để tạo ra kết nối cho giao thức message.
MessageConnection.send(); nếu ứng dụng không được cấp phép để gửi thông điểm vào cổng định trước.
MessageConnection.receive(); nếu ứng dụng không được cấp phép nhận thông điệp trên cổng định trước.

Ví dụ dưới đây cho biết sự cấp phép WMA yêu cầu thông qua JAD hay manifest:

...
MIDlet-Permissions: javax.microedition.io.Connector.sms,
javax.wireless.messaging.sms.receive,
javax.wireless.messaging.sms.send,
javax.microedition.io.Connector.cbs,
javax.wireless.messaging.cbs.receive,
javax.microedition.io.Connector.mms,
javax.wireless.messaging.mms.receive,
javax.wireless.messaging.mms.send,
javax.microedition.io.PushRegistry
...

III.Một số ví dụ

1.Tạo và gửi text message

package example.sms;

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

public class SMSSend extends MIDlet implements CommandListener {
    Command exitCommand = new Command("Exit", Command.EXIT, 2);
    Command okCommand = new Command("OK", Command.OK, 1);
    Display display;
    String smsPort;
    TextBox destinationAddressBox;
    Alert errorMessageAlert;
    Alert sendingMessageAlert;
    SMSSender sender;
    Displayable resumeScreen = null;
    public SMSSend() {
        smsPort = getAppProperty("SMS-Port");
        display = Display.getDisplay(this);
        destinationAddressBox = new TextBox("Destination Address?", null, 256,        
        TextField.PHONENUMBER);
        destinationAddressBox.addCommand(exitCommand);
        destinationAddressBox.addCommand(okCommand);
        destinationAddressBox.setCommandListener(this);
        errorMessageAlert = new Alert("SMS", null, null, AlertType.ERROR);
        errorMessageAlert.setTimeout(5000);
        sendingMessageAlert = new Alert("SMS", null, null, AlertType.INFO);
        sendingMessageAlert.setTimeout(5000);
        sendingMessageAlert.setCommandListener(this);
        sender = new SMSSender(smsPort, display, destinationAddressBox, sendingMessageAlert);
        resumeScreen = destinationAddressBox;
        display.setCurrent(resumeScreen);
    }

    public void startApp() {

    }

    public void pauseApp() {

    }

    public void destroyApp(boolean unconditional) {
    }

    public void commandAction(Command c, Displayable s) {
        try {
         if ((c == exitCommand) /*|| (c == Alert.DISMISS_COMMAND)*/) {
               destroyApp(false);
               notifyDestroyed();
           } else if (c ==  Alert.DISMISS_COMMAND) {
               display.setCurrent(resumeScreen);
           } else if (c == okCommand) {
               promptAndSend();
           }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private void promptAndSend() {
        String address = destinationAddressBox.getString();

        if (!SMSSend.isValidPhoneNumber(address)) {
            errorMessageAlert.setString("Invalid phone number");
            display.setCurrent(errorMessageAlert, destinationAddressBox);

            return;
        }

        String statusMessage = "Sending message to " + address + "...";
        sendingMessageAlert.setString(statusMessage);
        sender.promptAndSend("sms://" + address);
    }

    private static boolean isValidPhoneNumber(String number) {
        char[] chars = number.toCharArray();

        if (chars.length == 0) {
            return false;
        }

        int startPos = 0;

        // initial '+' is OK
        if (chars[0] == '+') {
            startPos = 1;
        }

        for (int i = startPos; i < chars.length; ++i) {
            if (!Character.isDigit(chars[i])) {
                return false;
            }
        }

        return true;
    }
}

2.Nhận một text message

package example.sms;

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

public class SMSReceive extends MIDlet implements CommandListener, Runnable, MessageListener {
    Command exitCommand = new Command("Exit", Command.EXIT, 2);
    Command replyCommand = new Command("Reply", Command.OK, 1);
    Alert content;
    Display display;
    Thread thread;
    String[] connections;
    boolean done;
    String smsPort;
    MessageConnection smsconn;
    Message msg;
    String senderAddress;
    Alert sendingMessageAlert;
    SMSSender sender;
    Displayable resumeScreen;

    public SMSReceive() {
            smsPort = getAppProperty("SMS-Port");
            display = Display.getDisplay(this);
            content = new Alert("SMS Receive");
            content.setTimeout(Alert.FOREVER);
            content.addCommand(exitCommand);
            content.setCommandListener(this);
            content.setString("Receiving...");
            sendingMessageAlert = new Alert("SMS", null, null, AlertType.INFO);
            sendingMessageAlert.setTimeout(5000);
            sendingMessageAlert.setCommandListener(this);

            sender = new SMSSender(smsPort, display, content, sendingMessageAlert);

            resumeScreen = content;

            display.setCurrent(resumeScreen);
    }

    public void startApp() {
            display.setCurrent(resumeScreen);

             String smsConnection = "sms://:" + smsPort;
                if (smsconn == null) {
            try {
                smsconn = (MessageConnection)Connector.open(smsConnection);
                smsconn.setMessageListener(this);
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
        }

        connections = PushRegistry.listConnections(true);
        if ((connections == null) || (connections.length == 0)) {
            content.setString("Waiting for SMS on port " + smsPort + "...");
        }

        done = false;
        thread = new Thread(this);
        thread.start();

    }

    public void notifyIncomingMessage(MessageConnection conn) {
                        if (thread == null) {
            done = false;
            thread = new Thread(this);
            thread.start();
        }
    }

    public void run() {
             try {
            msg = smsconn.receive();

            if (msg != null) {
                senderAddress = msg.getAddress();
                content.setTitle("From: " + senderAddress);

                if (msg instanceof TextMessage) {
                    content.setString(((TextMessage)msg).getPayloadText());
                } else {
                    StringBuffer buf = new StringBuffer();
                    byte[] data = ((BinaryMessage)msg).getPayloadData();

                    for (int i = 0; i < data.length; i++) {
                        int intData = (int)data[i] & 0xFF;

                        if (intData < 0x10) {
                            buf.append("0");
                        }

                        buf.append(Integer.toHexString(intData));
                        buf.append(' ');
                    }

                    content.setString(buf.toString());
                }

                content.addCommand(replyCommand);
                display.setCurrent(content);
            }
        } catch (IOException e) {
            // e.printStackTrace();
        }
    }

    public void pauseApp() {
        done = true;
        thread = null;
        resumeScreen = display.getCurrent();
    }

    public void destroyApp(boolean unconditional) {
        done = true;
        thread = null;

        if (smsconn != null) {
            try {
                smsconn.close();
            } catch (IOException e) {
                // Ignore any errors on shutdown
            }
        }
    }

    public void commandAction(Command c, Displayable s) {
        try {
            if (c == exitCommand || s == sendingMessageAlert ) {
                                                 destroyApp(false);
                notifyDestroyed();
            } else if (c == replyCommand) {
                reply();
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private void reply() {
        // remove the leading "sms://" for displaying the destination address
        String address = senderAddress.substring(6);
        String statusMessage = "Sending message to " + address + "...";
        sendingMessageAlert.setString(statusMessage + "\n\n...'Done' to close demo");
        sender.promptAndSend(senderAddress);
    }  
}

3.Tạo MultipartMessage

Mỗi MessagePart là trung tâm của MultipartMessages, nó bao gồmkiểu MIME, content ID, và content của chính nó. Các kiểu Constructor của MessagePart:

MessagePart(byte[] contents, int offset, int length, String mimeType, String contentId, String contentLocation, String encoding) throws SizeExceededException
MessagePart(byte[] contents, String mimeType, String contentId, String contentLocation, String encoding) throws SizeExceededException
• MessagePart(java.io.InputStream contents, String mimeType, String contentId, String contentLocation, String encoding) throws IOException, SizeExceededException

Trong đó:

Contents: tham chiếu đến nội dung thực sự của thông điệp.
mime Type : kiểu MIME, được định nghĩa trong RFC2046.
ContentId : đó là một ID duy nhất để xác định một message part, được định nghĩa trong RFC2045.
ContentLocation: specifies the filename for the attached message represented by the content. A null value means that no content location value is set for this message part.
encoding: xác định encoding của nội dung. Nếu giá trị này bằng null, có nghĩa là không có encoding nào được chỉ định trong message part.

Hai Constructor đầu tiên cho phép tạo ra message part từ một mảng byte, và Constructor còn lại sử dụng để tạo message part từ một InputStream.

  • Một số API hữu ích:

addAddress(String, String): thêm một địa chỉ vào multipart message.
addMessagePart(MessagePart): đính kèm một MessagePart vào multipart message.
getAddress(): trả về một địa chỉ “from” kết hợp với message này.
getHeader(String): nhận nội dung của header cho trước của multipart message.
getMessagePart(String): trả về một MessagePart từ message mà phù hợp với tham số content-id.
getStartContentId(): trả về contentId của MessagePart .
getSubject(): nhận subject của multipart message.
removeMessagePart(MessagePart): xóa MessagePart từ multipart message.
removeMessagePartId(String): xóa MessagePart với contentID định trước từ multipart message.
removeMessagePartLocation(String): xóa MessageParts với content location định trước từ multipart message.
setAddress(String): thiết lập địa chỉ đến “to” kết hợp với thông điệp.
setHeader(String, String): thiết lập header định trước của multipart message.
setStartContentId(String): thiết lập Content-ID của MessagePart của một multipart message liên quan.
setSubject(String): thiết lập subject của multipart message.
removeAddress(String, String): xóa địa chỉ từ multipart message.

Ví dụ:

package example.mms;

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

public class PartsDialog implements CommandListener {
    private static final Command CMD_BACK = new Command("Back", Command.BACK, 1);
    private static final Command CMD_NEXT = new Command("Next", Command.OK, 1);
    private static final Command CMD_OK = new Command("OK", Command.OK, 1);
    private static final Command CMD_CANCEL = new Command("Cancel", Command.CANCEL, 1);
    private MMSSend mmsSend;
    private List typeList;
    public int counter = 0;
    public PartsDialog(MMSSend mmsSend) {
        this.mmsSend = mmsSend;

        String[] stringArray = { "Text", "Image" };

        typeList = new List("Add Part: Type", Choice.EXCLUSIVE, stringArray, null);
        typeList.addCommand(CMD_BACK);
        typeList.addCommand(CMD_NEXT);
        typeList.setCommandListener(this);
    }

    public void show() {
        mmsSend.getDisplay().setCurrent(typeList);
    }
    public void commandAction(Command c, Displayable s) {
        try {
            if (c == CMD_BACK) {
                mmsSend.show();
            } else if (c == CMD_NEXT) {
                if (typeList.getSelectedIndex() == 0) {
                    mmsSend.getDisplay().setCurrent(new TextDialog());
                } else {
                    mmsSend.getDisplay().setCurrent(new ImageDialog());
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private class TextDialog extends Form implements CommandListener {
        private Displayable mainForm;
        private TextField text;
        private String mimeType = "text/plain";

        public TextDialog() {
            super("Add Text");

            text = new TextField("Text: ", null, 256, TextField.ANY);
            append(text);
            append("MIME-Type: " + mimeType);

            addCommand(CMD_OK);
            addCommand(CMD_CANCEL);
            setCommandListener(this);
        }

        public void commandAction(Command c, Displayable s) {
            try {
                if (c == CMD_OK) {
                    String encoding = "UTF-8";
                    byte[] contents = text.getString().getBytes(encoding);
                    mmsSend.getMessage()
                           .addPart(new MessagePart(contents, 0, contents.length, mimeType,
                            "id" + counter, "contentLocation", encoding));
                    counter++;
                    mmsSend.show();
                } else if (c == CMD_CANCEL) {
                    mmsSend.show();
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }

    private class ImageDialog extends Form implements CommandListener {
        private Displayable mainForm;
        private ChoiceGroup cg;
        private String mimeType = "image/png";
        private String[] resouces = { "/Java.png", "/Duke.png" };
        private String[] imagesNames = { "Java", "Duke" };

        public ImageDialog() {
            super("Add Image");
            cg = new ChoiceGroup("Select Image", Choice.EXCLUSIVE, imagesNames, null);
            append(cg);
            append("MIME-Type: " + mimeType);
            addCommand(CMD_OK);
            addCommand(CMD_CANCEL);
            setCommandListener(this);
        }

        public void commandAction(Command c, Displayable s) {
            try {
                if (c == CMD_OK) {
                    int index = cg.getSelectedIndex();
                    String resouce = resouces[index];
                    InputStream is = getClass().getResourceAsStream(resouce);
                    byte[] contents = new byte[is.available()];
                    is.read(contents);

                    String contentLocation = imagesNames[index];
                    mmsSend.getMessage()
                           .addPart(new MessagePart(contents, 0, contents.length, mimeType,
                            "id" + counter, contentLocation, null));
                    counter++;
                    mmsSend.show();
                } else if (c == CMD_CANCEL) {
                    mmsSend.show();
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }
}

4.Gửi multipart message

package example.mms;

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

public class MMSSend extends MIDlet implements CommandListener {
    private static Command CMD_EXIT = new Command("Exit", Command.EXIT, 2);
    private static Command CMD_SEND = new Command("Send", Command.ITEM, 1);
    private static Command CMD_ADD_PART = new Command("Add Part", Command.ITEM, 1);
    private Display display;
    private String appID;
    private TextField subjectField;
    private TextField destinationField;
    private StringItem partsLabel;
    private Alert errorMessageAlert;
    private Alert sendingMessageAlert;
    private Displayable resumeScreen = null;
    private MMSMessage message;
    private PartsDialog partsDialog;
    public MMSSend() {
        appID = getAppProperty("MMS-ApplicationID");
        display = Display.getDisplay(this);
        Form mainForm = new Form("New MMS");
        subjectField = new TextField("Subject:", null, 256, TextField.ANY);
        mainForm.append(subjectField);
        destinationField = new TextField("Destination Address: ", "mms://", 256, TextField.ANY);
        mainForm.append(destinationField);
        partsLabel = new StringItem("Parts:", "0");
        mainForm.append(partsLabel);
        mainForm.addCommand(CMD_EXIT);
        mainForm.addCommand(CMD_SEND);
        mainForm.addCommand(CMD_ADD_PART);
        mainForm.setCommandListener(this);
        errorMessageAlert = new Alert("MMS", null, null, AlertType.ERROR);
        errorMessageAlert.setTimeout(5000);
        sendingMessageAlert = new Alert("MMS", null, null, AlertType.INFO);
        sendingMessageAlert.setTimeout(5000);
        sendingMessageAlert.setCommandListener(this);

        resumeScreen = mainForm;

        message = new MMSMessage();
    }
    public void startApp() {
        display.setCurrent(resumeScreen);
    }

    public void pauseApp() {
        resumeScreen = display.getCurrent();
    }

    public void destroyApp(boolean unconditional) {
    }

    public void commandAction(Command c, Displayable s) {
        try {
            if ((c == CMD_EXIT) ) {
                destroyApp(false);
                notifyDestroyed();
            } else if (c == Alert.DISMISS_COMMAND) {
                         display.setCurrent(resumeScreen);
            } else if (c == CMD_ADD_PART) {
                if (partsDialog == null) {
                    partsDialog = new PartsDialog(this);
                }
                partsDialog.show();
            } else if (c == CMD_SEND) {
                promptAndSend();
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    void show() {
        partsLabel.setText(Integer.toString(partsDialog.counter));
        display.setCurrent(resumeScreen);
    }

    Display getDisplay() {
        return display;
    }

    MMSMessage getMessage() {
        return message;
    }

    private void promptAndSend() {
        try {
            String address = destinationField.getString();
            message.setSubject(subjectField.getString());
            message.setDestination(address);

            String statusMessage = "Sending message to " + address + "...";
            sendingMessageAlert.setString(statusMessage);

            new SenderThread(message, appID).start();
        } catch (IllegalArgumentException iae) {
            errorMessageAlert.setString(iae.getMessage());
            display.setCurrent(errorMessageAlert);
        }
    }
}

5.Nhận multipart message

import java.io.IOException;

import javax.microedition.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
import javax.wireless.messaging.*;
public class MMSReceive extends MIDlet implements CommandListener, Runnable, MessageListener {
    private static final Command CMD_EXIT = new Command("Exit", Command.EXIT, 2);
    private Form content;
    private Display display;
    private Thread thread;
    private String[] connections;
    private boolean done;
    private String appID;
    private MessageConnection mmsconn;
    private Message msg;
    private String senderAddress;
    private Alert sendingMessageAlert;
    private Displayable resumeScreen;
    private String subject;
    private String contents;
    public MMSReceive() {
        appID = getAppProperty("MMS-ApplicationID");
        display = Display.getDisplay(this);
        content = new Form("MMS Receive");
        content.addCommand(CMD_EXIT);
        content.setCommandListener(this);
        content.append("Receiving...");
        sendingMessageAlert = new Alert("MMS", null, null, AlertType.INFO);
        sendingMessageAlert.setTimeout(5000);
        sendingMessageAlert.setCommandListener(this);
        resumeScreen = content;
    }
    public void startApp() {
            display.setCurrent(resumeScreen); 
        String mmsConnection = "mms://:" + appID;
        if (mmsconn == null) {
            try {
                mmsconn = (MessageConnection)Connector.open(mmsConnection);
                mmsconn.setMessageListener(this);
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
        }
        connections = PushRegistry.listConnections(true);

        if ((connections == null) || (connections.length == 0)) {
            content.deleteAll();
            content.append("Waiting for MMS on applicationID " + appID + "...");
        }
        done = false;
        thread = new Thread(this);
        thread.start();
    }

    public void notifyIncomingMessage(MessageConnection conn) {
        if ((thread == null) && !done) {
            thread = new Thread(this);
            thread.start();
        }
    }

    public void run() {
        try {
            msg = mmsconn.receive();
            if (msg != null) {
                senderAddress = msg.getAddress();
                content.deleteAll();
                String titleStr = senderAddress.substring(6);
                int colonPos = titleStr.indexOf(":");
                if (colonPos != -1) {
                    titleStr = titleStr.substring(0, colonPos);
                }
                content.setTitle("From: " + titleStr);
                if (msg instanceof MultipartMessage) {
                    MultipartMessage mpm = (MultipartMessage)msg;
                    StringBuffer buff = new StringBuffer("Subject: ");
                    buff.append((subject = mpm.getSubject()));
                    if (mpm.getTimestamp() != null) {
                        buff.append("\nDate: ");
                        buff.append(mpm.getTimestamp().toString());
                    }
                    buff.append("\nContent:");
                   StringItem messageItem = new StringItem("Message", buff.toString());
                    messageItem.setLayout(Item.LAYOUT_NEWLINE_AFTER);
                    content.append(messageItem);
                    MessagePart[] parts = mpm.getMessageParts();
                    if (parts != null) {
                        for (int i = 0; i < parts.length; i++) {
                            buff = new StringBuffer();
                            MessagePart mp = parts[i];
                            buff.append("Content-Type: ");
                            String mimeType = mp.getMIMEType();
                            buff.append(mimeType);
                            String contentLocation = mp.getContentLocation();
                            buff.append("\nContent:\n");
                            byte[] ba = mp.getContent();

                            try {
                                Image image = Image.createImage(ba, 0, ba.length);
                                content.append(buff.toString());
                                ImageItem imageItem =
                                    new ImageItem(contentLocation, image,
                                        Item.LAYOUT_NEWLINE_AFTER, contentLocation);
                                content.append(imageItem);
                            } catch (IllegalArgumentException iae) {
                                buff.append(new String(ba));

                                StringItem stringItem = new StringItem("Part", buff.toString());
                                stringItem.setLayout(Item.LAYOUT_NEWLINE_AFTER);
                                content.append(stringItem);
                            }
                        }
                    }
                }

                display.setCurrent(content);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void pauseApp() {
        done = true;
        thread = null;
        resumeScreen = display.getCurrent();
    }

    public void destroyApp(boolean unconditional) {
        done = true;
        thread = null;

        if (mmsconn != null) {
            try {
                mmsconn.close();
            } catch (IOException e) {
                // Ignore any errors on shutdown
            }
        }
    }

    public void commandAction(Command c, Displayable s) {
        try {
            if ((c == CMD_EXIT)) {
                destroyApp(false);
                notifyDestroyed();
            } else if (c == Alert.DISMISS_COMMAND) {
                startApp();
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

6.Validate số điện thoại

package example.mms;

import java.util.Vector;
import javax.wireless.messaging.*;

public class MMSMessage {
    private String destination;
    private Vector parts = new Vector();
    private String subject;
    private static boolean isValidPhoneNumber(String address) {
        String protocol = "mms://";
        if (!address.startsWith(protocol)) {
            return false;
        }
        String number = address.substring(protocol.length());
        char[] chars = number.toCharArray();
        if (chars.length == 0) {
            return false;
        }
        int startPos = 0;
        if (chars[0] == '+') {
            startPos = 1;
        }
        for (int i = startPos; i < chars.length; ++i) {
            if (!Character.isDigit(chars[i])) {
                return false;
            }
        }
        return true;
    }

    public String getSubject() {
        return subject;
    }

    public void setSubject(String subject) {
        this.subject = subject;
    }

    public String getDestination() {
        return destination;
    }

    public void setDestination(String destination) {
        if (!isValidPhoneNumber(destination)) {
            throw new IllegalArgumentException("Invalid phone number");
        }

        this.destination = destination;
    }

    public MessagePart[] getParts() {
        MessagePart[] partsArray = new MessagePart[parts.size()];
        parts.copyInto(partsArray);

        return partsArray;
    }

    public void addPart(MessagePart part) {
        parts.addElement(part);
    }
}

7.Gửi thông điệp sử dụng thread

package example.mms;
import java.io.IOException;
import javax.microedition.io.*;
import javax.wireless.messaging.*;

public class SenderThread extends Thread {
    private MMSMessage message;
    private String appID;

    public SenderThread(MMSMessage message, String appID) {
        this.message = message;
        this.appID = appID;
    }

    public void run() {
        String address = message.getDestination() + ":" + appID;
        MessageConnection mmsconn = null;

        try {
            mmsconn = (MessageConnection)Connector.open(address);

            MultipartMessage mmmessage =
                (MultipartMessage)mmsconn.newMessage(MessageConnection.MULTIPART_MESSAGE);
            mmmessage.setAddress(address);

            MessagePart[] parts = message.getParts();

            for (int i = 0; i < parts.length; i++) {
                mmmessage.addMessagePart(parts[i]);
            }

            mmmessage.setSubject(message.getSubject());
            mmsconn.send(mmmessage);
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (mmsconn != null) {
            try {
                mmsconn.close();
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
        }
    }
}

Bạn thấy bài viết này thế nào?