Trong bài viết này, tôi xin trình bày cách để cài đặt một MIDlet lắng nghe các message SMS đang đến. Luồng hoạt động của nó được thực hiện một cách đồng bộ như sau:

  • Người dùng cài đặt ứng dụng SMSListenerMIDlet vào thiết bị và khởi động nó. Tạm gọi thiết bị này là thiết bị A. Lúc này, MIDlet vẫn chưa lắng nghe các message đang đến, do đó nếu lúc này, người dùng gửi một tin nhắn SMS từ một thiết bị khác – tạm gọi thiết bị này là thiết bị B – thì nó sẽ không bị chặn bởi MIDlet. Thay vào đó, SMS sẽ đến trong inbox của thiết bị A.
  • Người dùng sẽ để MIDlet lắng nghe các message đang đến bằng cách chọn Options -> Start listening. Bên trong MIDlet,sẽ xảy ra 2 vấn đề sau:
    • Phương thức startListening() được gọi. Nó sẽ mở một connection vào port chỉ định, tạo ra một thread mới, và kích hoạt nó chạy.
    • Trong phương thức run(), phương thức đồng bộ receive() được gọi, và nó sẽ được block cho đến khi có một tin nhắn available.
    • Từ thiết bị B, bây giờ người dùng có thể gửi SMS, và SMS này sẽ được bắt lấy bởi MIDlet trong A. Và trong MIDlet sẽ xảy ra các vấn đề sau:
      • Khi một tin nhắn đến, phương thức receive() được trả về và phương thức processMessage() được gọi.
      • Phương thức processMessage() kiểm tra kiểu SMS như (kiểu văn bản, nhị phân, hoặc tin nhắn multipart) và xử lý chúng phù hợp. Trong thực tế, nó sẽ hiển thị nội dung văn bản tải của tin nhắn lên màn hình. Trong ví dụ này, chỉ xử lý tin nhắn văn bản.
      • Lưu ý rằng các SMS được gửi với port chỉ định sẽ không bao giờ đến inbox của thiết bị A một khi MIDlet đang lắng nghe chúng. Và bây giờ, nếu người dùng ngừng việc lắng nghe (bằng cách chọn Options> Stop listening), các SMS tiếp theo với cổng được chỉ định sẽ rơi vào inbox của thiết bị A, thay vì MIDlet.

Code của nó như sau:

import java.io.IOException;
import javax.microedition.io.Connector;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.StringItem;
import javax.microedition.midlet.MIDlet;
import javax.wireless.messaging.BinaryMessage;
import javax.wireless.messaging.Message;
import javax.wireless.messaging.MessageConnection;
import javax.wireless.messaging.MultipartMessage;
import javax.wireless.messaging.TextMessage;

public class SMSListenerMIDlet
        extends MIDlet
        implements CommandListener, Runnable {

    // The port which is listened for incoming messages
    private final String PORT = "5000";

    private Form mainForm;
    private Command startCommand;
    private Command stopCommand;
    private Command exitCommand;
    private MessageConnection connection;
    private boolean listening;

    /**
     * Constructor. Constructs the object and initializes displayables.
     */
    public SMSListenerMIDlet() {
        mainForm = new Form("SMS Listener");

        startCommand = new Command("Start listening", Command.ITEM, 0);
        mainForm.addCommand(startCommand);

        stopCommand = new Command("Stop listening", Command.ITEM, 1);
        mainForm.addCommand(stopCommand);

        exitCommand = new Command("Exit", Command.EXIT, 1);
        mainForm.addCommand(exitCommand);

        mainForm.setCommandListener(this);
    }

    /**
     * From MIDlet.
     * Called when the MIDlet is started.
     */
    public void startApp() {
        // The initial display is the main form
        Display.getDisplay(this).setCurrent(mainForm);
    }

    /**
     * From MIDlet.
     * Called to signal the MIDlet to enter the Paused state.
     */
    public void pauseApp() {
        // No implementation required
    }

    /**
     * From MIDlet.
     * Called to signal the MIDlet to terminate.
     * @param unconditional whether the MIDlet has to be unconditionally
     * terminated
     */
    public void destroyApp(boolean unconditional) {
        // Stop listening
        stopListening();
    }

    /**
     * From CommandListener.
     * Called by the system to indicate that a command has been invoked on a
     * particular displayable.
     * @param command the command that was invoked
     * @param displayable the displayable where the command was invoked
     */
    public void commandAction(Command command, Displayable displayable) {
        if (command == exitCommand) {
            // Exit the MIDlet
            destroyApp(true);
            notifyDestroyed();
        } else if (command == startCommand) {
            startListening();
        } else if (command == stopCommand) {
            stopListening();
        }
    }

    /**
     * Starts listening for incoming messages.
     */
    private void startListening() {
        // If we are already listening, no need to start again
        if (listening) {
            return;
        }

        try {
            // Open the connection to the specified port
            connection = (MessageConnection)Connector.open("sms://:" + PORT);
        } catch (IOException ex) {
            return;
        }

        // Create a listener thread and start listening
        Thread listenerThread = new Thread(this);
        listening = true;
        listenerThread.start();

        mainForm.append("Listener started.\n");
    }

    /**
     * Stops listening for incoming messages.
     */
    private void stopListening() {
        // If we are not listening, no need to do anything
        if (!listening) {
            return;
        }

        if (connection != null) {
            try {
                // Close the message connection
                connection.close();
                connection = null;
            } catch (IOException ex) {
                // TODO: Exception handling
            }
        }

        listening = false;

        mainForm.append("Listener stopped.\n");
    }

    /**
     * The main listening loop.
     */
    public void run() {
        while (listening) {
            try {
                // Receive all incoming messages to the specified port. The
                // receive() method will block until there is a message
                // available.
                Message message = connection.receive();
                if (message != null) {
                    mainForm.append("Message received.\n");
                    processMessage(message);
                }
            } catch (IOException ex) {
                // Stop listening
                stopListening();
            }
        }
    }

    /**
     * Processes the received message according to its type.
     * @param message the received message
     */
    private void processMessage(Message message) {
        if (message instanceof TextMessage) {
            processTextMessage((TextMessage)message);
        } else if (message instanceof BinaryMessage) {
            processBinaryMessage((BinaryMessage)message);
        } else if (message instanceof MultipartMessage) {
            processMultipartMessage((MultipartMessage)message);
        }
    }

    /**
     * Processes a text message.
     */
    private void processTextMessage(TextMessage message) {
        String text = message.getPayloadText();
        StringItem textItem = new StringItem("Text", text);
        mainForm.append(textItem);
    }

    /**
     * Processes a binary message.
     */
    private void processBinaryMessage(BinaryMessage binaryMessage) {
        // Not implemented
    }

    /**
     * Processes a multipart message.
     */
    private void processMultipartMessage(MultipartMessage multipartMessage) {
        // Not implemented
    }
}

Lưu ý: Khi bạn gửi SMS, bạn phải đảm bảo rằng port giống như listener. Nếu không, thread listener sẽ không thông báo SMS. Đoạn code dưới đây mô tả gửi tin nhắn SMS có chỉ định port:

// Prepare the text message
TextMessage message = (TextMessage)connection.newMessage(
MessageConnection.TEXT_MESSAGE);

// Obtain the address from a text field, append a port number to it, and set the
// whole thing as the destination address for the message. The port number is
// the same as above.
String address = “sms://” + smsAddress.getString() + “:” + PORT;
message.setAddress(address);

// Obtain the specified text and set it as the payload
String text = smsText.getString();
message.setPayloadText(text);

Code tham khảo từ Forum Nokia