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:
- 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.
- The user tells the MIDlet to start listening for incoming messages by selecting Options > Start listening. Inside the MIDlet, the following happens:
- The startListening() method is called.
- The method opens the connection to the specified port and registers the MIDlet as the listener for incoming messages.
- 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:
- The notifyIncomingMessage() method gets called by the WMA implementation.
- To minimize the time spent in the notifyIncomingMessage() method, a separate thread is created to fetch the message.
- 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.
- 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.
- 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 |

