Search

Extend J2ME to Wireless Messaging

0 views

Understanding GSM Messaging Foundations

Before a Java application can send or receive text on a mobile network, it must understand how the underlying GSM system handles messages. The two primary services are Short Message Service (SMS) and Cell Broadcast Service (CBS). SMS is a point‑to‑point channel where one handset sends a short burst of data to another handset or device. CBS, on the other hand, delivers the same message to every device within a cell, making it ideal for alerts or public announcements.

SMS packets are limited to 160 alphanumeric characters or 140 bytes in binary form. When an application fires an SMS, it first reaches a Short Message Service Center (SMSC). The SMSC stores the packet until the network can forward it. The SMSC checks the home location register (HLR) to discover the current location and status of the subscriber. If the recipient is inactive or roaming, the SMSC holds the message until a delivery attempt succeeds. This holding mechanism explains why messages can arrive after a device has been turned off for a while.

Delivery proceeds through a paging cycle: the network broadcasts a page to the handset’s location area code. When the handset replies, the SMSC forwards the packet. The handset acknowledges receipt. The SMSC logs the success and removes the packet from its queue. This end‑to‑end sequence is why SMS is reliable, even over congested networks. The flow diagram is illustrated in many GSM specifications and can be visualised as a chain of three stages: Sender → SMSC → Recipient.

Cell Broadcast Service operates differently. CBS messages are transmitted to every device in a cell, so there is no per‑recipient addressing. The message is encoded with a channel number that identifies the topic (for example, weather or traffic). A message code marks each unique broadcast so that a handset can detect duplicates. An update number allows the system to push a newer version of the same message while keeping the previous ones in memory. The language tag tells the handset what language the payload uses. A CBS message can be as long as 15 pages of 93 characters each, but many implementations support only ASCII text.

While SMS is suited for direct communication between two parties, CBS shines in mass dissemination. In emergency alerts, for instance, a public safety agency can broadcast a single message to thousands of devices in minutes. Both services coexist on the same physical layer but are routed by the network according to their destination and payload size.

For a J2ME developer, grasping these network fundamentals is essential because the Java APIs expose the same operations in an abstracted form. The same underlying protocols - paging, routing, delivery receipts - remain, but the developer interacts through a clean object model instead of low‑level telephony commands.

In the next section we’ll dive into the Java API that mirrors these GSM mechanisms and show how the code is structured to separate concerns from the developer’s perspective.

Architecture of J2ME Wireless Messaging

J2ME’s wireless messaging capabilities are organized into a three‑tiered architecture that keeps platform specifics away from the MIDlet developer. The layers are: Interface, Implementation, and Transport. Each layer builds on the one below it, creating a clean abstraction that can be extended or swapped without touching application code.

The Interface Layer defines generic message objects and the connection interface that a MIDlet uses. At the core of this layer is the javax.wireless.messaging.Message interface. It encapsulates the address, payload, and flags common to all message types. Concrete subclasses like TextMessage and BinaryMessage provide typed accessors for text and binary payloads. The MessageConnection interface offers send and receive methods, a factory for creating new messages, and a helper that calculates the number of protocol segments required for a given payload. All of these are pure interfaces; the actual logic lives in the next tier.

Moving down, the Implementation Layer contains classes that provide the real logic for each protocol. For SMS, classes in com.sun.midp.io.j2me.sms implement the MessageConnection interface and provide text or binary message subclasses that interact with the underlying telephony stack. They also handle message segmentation and concatenation: if a payload exceeds 160 characters, the implementation will split it into multiple short messages and re‑assemble them on the receiving end. The same principle applies to CBS, where the implementation will pack the message into the appropriate channel, add the necessary headers, and send it over the cell broadcast channel.

At the base sits the Transport Layer, which interacts directly with the GSM network. In a real handset this layer talks to the radio, but for testing and development the J2ME platform offers a datagram‑emulation mode. In that mode, the SMS implementation wraps the packet in a UDP datagram that is sent to a local socket. The transport also manages the Service Center address, the port numbers, and the permissions needed for sending or receiving messages.

Because the layers are decoupled, you can switch the implementation without changing the MIDlet code. For example, a developer could test with the datagram‑emulation layer on a PC, then deploy the same MIDlet on a real phone that uses the native SMS stack. The code that calls Connector.open("sms://:5000") stays the same; only the underlying protocol changes.

The javax.wireless.messaging API was designed for portability. It mirrors the standard J2ME Messaging API (JSR 120) and is part of the Java ME Platform Services. The API’s documentation is extensive, but the core concepts are simple: create a MessageConnection, set a MessageListener if you need callbacks, build a Message object (TextMessage or BinaryMessage), and then send or receive. Understanding the architecture helps you debug problems when messages don’t arrive or when segmentation behaves unexpectedly.

In the following section we’ll translate this architecture into a concrete example: a server MIDlet that listens for incoming SMS messages and a client MIDlet that sends them. The code demonstrates the use of MessageConnection, MessageListener, and the text and binary message types.

Practical Example: Server and Client MIDlets

Below is a concise yet complete implementation of two MIDlets that illustrate how to receive and send SMS messages using the J2ME Wireless Messaging API. The server listens for inbound messages on port 5000 and displays them on the device screen. The client simply pushes a single text message to the same port. Both MIDlets share a common design pattern: open a MessageConnection, register a MessageListener for the server, and use Connector.open for the client.

First, let’s examine the server code. The MIDlet implements CommandListener and MessageListener so it can respond to UI commands and incoming messages. In startApp() the Form is set up with Exit and Get commands. The server then calls Connector.open("sms://:5000") to open a server‑mode connection. Because this is a server, it can send and receive. The call returns a MessageConnection instance which the MIDlet keeps as a field.

Registering a MessageListener is a one‑liner: serverConn.setMessageListener(this). When a new SMS arrives, the runtime calls notifyIncomingMessage(). Inside this method, we call conn.receive() to fetch the Message object. A type check determines whether the payload is text or binary. For TextMessage we call getPayloadText(); for BinaryMessage we pull getPayloadData() and convert the bytes to a string for display. The payload is stored in the msgReceived field so that the Get command can show it to the user.

Here is the key fragment that receives a message and extracts its content:

Prompt
public void notifyIncomingMessage(MessageConnection conn) {</p> <p> Message msg = null;</p> <p> try {</p> <p> msg = conn.receive();</p> <p> } catch (Exception e) {</p> <p> System.out.println("processMessage.receive " + e);</p> <p> }</p> <p> if (msg instanceof TextMessage) {</p> <p> TextMessage tmsg = (TextMessage)msg;</p> <p> msgReceived = tmsg.getPayloadText();</p> <p> } else if (msg instanceof BinaryMessage) {</p> <p> BinaryMessage bmsg = (BinaryMessage)msg;</p> <p> byte[] data = bmsg.getPayloadData();</p> <p> msgReceived = new String(data);</p> <p> }</p> <p>}</p>

Destroying the MIDlet cleans up the connection and removes the listener to avoid memory leaks. The client MIDlet follows a very similar pattern but with a few differences. In startApp() it calls Connector.open("sms://+18643630999:5000") to open a client‑mode connection to the phone number +18643630999 on port 5000. The client never receives messages, so it doesn’t register a MessageListener. When the Send command is activated, the MIDlet builds a new TextMessage using conn.newMessage(MessageConnection.TEXT_MESSAGE), sets the address and payload, and then sends it with conn.send(tmsg).

Here’s the snippet that constructs and sends a text message:

Prompt
TextMessage tmsg = (TextMessage)clientConn.newMessage(MessageConnection.TEXT_MESSAGE);</p> <p>tmsg.setAddress("sms://18643630999:5000");</p> <p>tmsg.setPayloadText(msgToSend);</p> <p>clientConn.send(tmsg);</p>

Both MIDlets compile into a JAR and JAD file that can be deployed on a J2ME platform. The server demonstrates inbound processing, while the client shows outbound capabilities. Together they form a minimal but complete demonstration of the Wireless Messaging API.

Deploying and Running Your J2ME Messaging MIDlets

To test the MIDlets on a simulator or a real device, you need the J2ME Wireless Messaging Reference Implementation (WMA RI). The WMA 1.0 RI is a drop‑in library that emulates the SMS and CBS protocols over a local datagram socket. This is particularly useful for developers who lack a handset but want to validate message flows on a desktop.

First, download the RI from Oracle’s J2ME product page: https://www.oracle.com/java/technologies/java-midp-technology.html. After unpacking, copy wma.jar from the wma1_0/lib folder to your J2ME SDK’s lib directory. Then open the internal.config file in the SDK’s lib folder and add entries that enable SMS and CBS permissions and configure the datagram hosts and ports. The snippet below shows typical values:

Prompt
# Default values for SMS internal implementation</p> <p>com.sun.midp.io.j2me.sms.Impl=com.sun.midp.io.j2me.sms.DatagramImpl</p> <p>com.sun.midp.io.j2me.sms.DatagramHost=localhost</p> <p>com.sun.midp.io.j2me.sms.DatagramPortIn=56789</p> <p>com.sun.midp.io.j2me.sms.DatagramPortOut=34567</p><h1>Permissions</h1> com.sun.midp.io.j2me.sms.permission.receive=true</p> <p>com.sun.midp.io.j2me.sms.permission.send=true</p> <p>com.sun.midp.io.j2me.cbs.permission.receive=true</p><h1>Connector entries</h1> javax.microedition.io.Connector.sms=true</p> <p>javax.microedition.io.Connector.cbs=true</p><h1>SMS Service Center</h1> wireless.messaging.sms.smsc=+18643299089</p>

With the configuration in place, you can compile the MIDlets. The J2ME SDK ships a pre‑verify tool and a JAR utility. A typical build script looks like this (adjust paths as needed):

Prompt
@echo off</p> <p>echo <strong><em> Compiling source files </strong></em> javac -bootclasspath <SDK>/libmidpapi.zip -d <build>/tmpclasses -classpath <build>/tmpclasses;wma.jar <srcpath>/*.java</p> <p>echo <strong><em> Pre‑verifying class files </strong></em> binpreverify -classpath <SDK>/libmidpapi.zip;<build>/tmpclasses;wma.jar -d <build>/classes <build>/tmpclasses</p> <p>echo <strong><em> Jaring pre‑verified classes </strong></em> jar cmf MANIFEST.MF <build>/WMAClient.jar -C <build>/classes .</p> <p>echo <strong><em> Adding resource files </strong></em> jar umf MANIFEST.MF <build>/WMAClient.jar -C <build>/res .</p>

After packaging, the resulting JAD file points to the JAR and describes the MIDlet’s properties. To launch the MIDlet in the emulator, a second script can start the simulator with the appropriate classpath:

Prompt
@echo off</p> <p>cd <SDK>/bin</p> <p>emulator -classpath <build>/WMAClient.jar;wma.jar -Xdescriptor <build>/WMAClient.jad</p>

When running on a real device, simply side‑load the JAD and JAR via OTA or direct installation. The device will prompt for permissions for SMS sending and receiving. Once granted, the server MIDlet will listen on port 5000 and the client MIDlet will send messages to the specified number. If you’re using the datagram emulation, the messages travel over UDP to localhost, mimicking the network flow without needing a physical handset.

Testing tips: use the emulator’s console to inspect outgoing datagrams. Enable debug logging in the MIDlet by printing to System.out; the simulator captures these prints. Check the internal.config for correct port numbers - if they clash with other services, the connection will fail. Finally, remember that real devices enforce strict size limits; SMS payloads larger than 160 characters are automatically segmented by the implementation, but your MIDlet may need to handle re‑assembly if you process the message further.

Resources and Next Steps

For developers who want to deepen their knowledge of J2ME and wireless messaging, a number of official resources are available. The J2ME Platform Services page on Oracle’s website provides the latest specifications, API documentation, and reference implementations: https://www.oracle.com/java/technologies/java-midp-technology.html. The JSR‑120 specification is the formal contract for messaging in Java ME, and it is worth reading to understand the guarantees the API offers.

IBM DeveloperWorks hosts a dedicated wireless zone where articles cover topics from MIDlet architecture to performance tuning: https://developer.ibm.com/technologies/wireless/. The Java Technology zone (https://developer.ibm.com/java/) offers deeper dives into the core Java SE APIs that underlie J2ME, which can be useful when you need to bridge between device code and desktop services.

For practical hands‑on experience, the J2ME Wireless Toolkit (WTK) remains the most straightforward way to experiment. It bundles the SDK, a built‑in simulator, and a set of sample MIDlets. After installing the toolkit, you can use the Eclipse plug‑in to manage projects, or stick with the command line if you prefer.

Finally, consider extending the sample server and client MIDlets. Add a user interface that allows the server to display a list of all received messages, or enable the client to send binary payloads such as images or GPS coordinates. The Wireless Messaging API is intentionally lightweight, so you can experiment without adding heavy dependencies.

By following the steps above - understanding GSM messaging, mastering the J2ME messaging layers, building concrete MIDlets, and deploying with the reference implementation - you’ll be well equipped to develop robust, portable messaging applications for Java‑powered mobile devices.

Suggest a Correction

Found an error or have a suggestion? Let us know and we'll review it.

Share this article

Comments (0)

Please sign in to leave a comment.

No comments yet. Be the first to comment!

Related Articles