Join Now
Quality Rating:
  • Currently 5.0 / 5
(5.0 / 5 - 1 vote cast)
This page was last modified 12:50, 12 October 2008.

CS000981- Listening for incoming SMS messages: Asynchronous version

From Forum Nokia Wiki



ID CS000981 Creation date May 27, 2008
Platform S60 3rd Edition, FP1 Tested on devices Nokia N95 8GB
Category Java ME Subcategory WMA 2.0 (JSR-205)


Keywords (APIs, classes, methods, functions): javax.wireless.messaging.MessageListener, javax.wireless.messaging.MessageConnection, javax.microedition.io.Connector, javax.wireless.messaging.TextMessage, javax.microedition.io.Connector.open(), javax.wireless.messaging.MessageConnection.setMessageListener(), javax.wireless.messaging.MessageConnection.receive(), javax.wireless.messaging.MessageConnection.close()

Overview

This code snippet demonstrates how to implement a MIDlet that listens for incoming SMS messages. This is an asynchronous implementation with the flow of operations as follows:

  1. The user installs the SMSListenerMIDlet to a device and starts it. Let's call this device Device A. The MIDlet doesn't listen for incoming messages yet, so if the user now sent a message from another device – let's call this Device B – they wouldn't be intercepted by the MIDlet. Instead, they would arrive in the inbox of Device A.
  2. The user tells the MIDlet to start listening for incoming messages by selecting Options > Start listening. Inside the MIDlet, the following happens:
    1. The startListening() method is called.
    2. The method opens the connection to the specified port and registers the MIDlet as the listener for incoming messages.
  3. From Device B, the user may now send a message to the specified port in Device A, which will cause the following to happen in the MIDlet:
    1. The notifyIncomingMessage() method gets called by the WMA implementation.
    2. To minimize the time spent in the notifyIncomingMessage() method, a separate thread is created to fetch the message.
    3. Once the thread is started, it will block in the receive() method until there is a message available. This shouldn't take long, since the MIDlet has already been notified that there is a message waiting. Nevertheless, it is good practice to ensure that the notifyIncomingMessage() system method returns quickly, hence the thread creation.
    4. When a message has been received, the processMessage() method is called. It checks the type of the message (text, binary, or multipart message) and acts accordingly. In practice, it displays the payload text of the message on the screen. Only handling of text messages is implemented in this snippet.
  4. Note that messages sent to the specified port will never arrive in the inbox of Device A as long as the MIDlet is listening for them. If the user now stopped the listener (by selecting Options > Stop listening), subsequent messages to the specified port would end up in the inbox of Device A instead of the MIDlet.

Source

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.MessageListener;
import javax.wireless.messaging.MultipartMessage;
import javax.wireless.messaging.TextMessage;
public class SMSListenerMIDlet
        extends MIDlet
        implements CommandListener, MessageListener {
 
    // 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);
            
            // Register this MIDlet as the listener that should be notified
            // whenever messages arrive
            connection.setMessageListener(this);
        } catch (IOException ex) {
            return;
        }
        
        listening = true;        
        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 {
                // Deregister the message listener and close the connection
                connection.setMessageListener(null);
                connection.close();
                connection = null;
            } catch (IOException ex) {
                // TODO: Exception handling
            }
        }
        
        listening = false;
        mainForm.append("Listener stopped.\n");
    }
 
    /**
     * Asynchronous callback method for receiving incoming messages.
     * Called by the WMA implementation when a new message is ready.
     * @param connection the message connection with incoming messages
     */
    public void notifyIncomingMessage(final MessageConnection conn) {
        // Because this method is called by the platform, it is good practice to
        // minimize the processing done here, on the system thread. Therefore,
        // let's create a new thread for reading the message. 
        Thread smsThread = new Thread() {
            public void run() {
                try {
                    // Receive all incoming messages to the specified
                    // connection. The receive() method will block until there
                    // is a message available.
                    Message message = conn.receive();
                    if (message != null) {
                        mainForm.append("Message received.\n");
                        processMessage(message);
                    }
                } catch (IOException ex) {
                    // Stop listening
                    stopListening();
                }
            }
        };
        smsThread.start();
    }
 
    /**
     * 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
    }
}

Note: When you send the message, make sure the port number is the same as in the listener. Otherwise, the listener thread won't notice the message. Here's an example of preparing a text SMS for sending:

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

Postconditions

The MIDlet listens for incoming messages and displays their payload text on the screen as they arrive.

See also

Related Discussions
Thread Thread Starter Forum Replies Last Post
Not reading SMS Message muneendra78 General Messaging 0 2002-10-23 05:05
Emulator tools for MMS receiving / S60 / C++ jarkoos Symbian Networking & Messaging 4 2007-01-10 23:56
Not reading SMS Message muneendra78 PC Suite API and PC Connectivity SDK 0 2002-10-23 07:45
warning.mp3 Yurkesh Symbian Media (Graphics & Sounds) 0 2005-10-11 15:54
IMEI no and read incoming sms from inbox ?? Neelakantan Mobile Java Networking & Messaging & Security 4 2007-07-20 09:59
 
Powered by MediaWiki
RDF Facets: qfnZtypeQUqfnTypeZCommunityContentQ qfnZtypeQUqfnTypeZWebpageQ qfnZtypeQUqfnTypeZWikiContentQ qmarsZlanguageQUxhttpE3aE2fE2fswE2enokiaE2ecomE2flanguageE2d1E2fenX