I’m sending out an SMS

My latest programming adventure was using SMS (short message service) — that little tiny packet of data that does big things!!!

Every mobile developer should be familiar with this protocol because it is so widely accepted and supported, and because it’s such an important part of the revenue stream, conveniently tied in with the operators’ billing systems. Despite the arrival of more evolved standards like MMS and EMS, plain old SMS is likely to be with us for some time.

The main challenge with SMS is that it fits so little data per message — only 140 bytes of payload!!! So it’s good for sending small things like a URL, a short message, or a signal that the user has paid to use a bonus feature of your application. It’s less useful for sending more data-intensive items (like a whole new board for a game) unless you really optimize. Of course you can send more data by concatenating multiple SMSes, but this has limited utility. Sending too many leads to a bad user experience (costly in time and money). It takes three just to send a tiny favicon, so it’s not terribly practical for sending whole images. It’s more useful for sending signals than for sending content.

The WTK’s “WMADemo” provides a really good basic example of how to write the code to send and receive an SMS. It shows how to register to listen for incoming messages on a Push-Port, how to recognize and read both text and binary messages, and how to open the connection to send them. Text messages are simpler to deal with and can be sent either to an application or to the user’s inbox, depending on the URL used when creating the connection. Binary messages are useful for packing the data in tightly 😉 .

I tried uploading the WMADemo as-is to my Sagem my700x, but got some sort of strange permission error that prevented it from installing. Rather than tracing down the exact culprit, I just stripped down the demo to a version that used SMS only, eliminating the other protocols described in the demo. (I think I may have had to change the port number as well to something within the application port number range: 16000 to 16999, under project > settings > “push registry” and “user defined”.) With that I was able to get my handset to successfully send a message to itself.

The WMADemo shows how to statically request a push-port. That means that the precise push-port number the MIDlet wants to listen on is written in the jad and manifest files. (If you’re looking at the “WMADemo” example, note that the relevant jad attribute is the “MIDlet-Push-i” attribute. The user-defined “SMS-Port” attribute is not standard — it was added by the programmer so the MIDlet could read the push-port from the jad without having to parse the more complicated “MIDlet-Push-i” attribute.)

The advantage to defining the push port in the jad file is that you know in advance what port your MIDlet will be listening on. The disadvantages is that if you have the very bad luck of choosing the same push-port that another installed MIDlet is already listening on (of the 1000 possible choices), then your MIDlet won’t install at all on the handset. The other option is to request the push-port dynamically once the MIDlet is launched (basically keep requesting push-ports in a loop until you find one that isn’t in use). As explained in the MIDP PushRegistry JavaDoc, the effect is the same as static push-port registration in that your MIDlet is permanently registered with the requested push-port (and messages will be routed to the right MIDlet even if it isn’t running). The disadvantage is that you don’t know in advance what the port number will be. On the other hand, you don’t necessarily know in advance the phone number of all of the handsets that have downloaded and installed your MIDlet, so one solution is to program your MIDlet to request to send an SMS back to your server once it’s installed to tell you the relevant phone number and push-port info so you can push messages to your application. Note that receiving a message rings the handset and requires the user to allow your MIDlet to be launched, so obviously it’s important to be careful to send your users only messages they’ve agreed to receive — you can get in trouble for irritating people with spam.

My first home SMS exercise (after making sure that SMS worked from Java on my handset) was to modify the WMADemo to request its push-port dynamically, and then code the port number into a binary SMS and have the recipient handset read the message and reply to the correct port. It wasn’ too difficult — see the MIDP PushRegistry JavaDoc for hints.

My next trick will be to modify the checkers game from my book so that two players can play each other via SMS. The version in the book has the two players playing each other by communicating with a central server on a plain socket. Plain-socket programming is a useful exercise for understanding the theory of how more complex protocols are built on simpler ones (and don’t knock this kind of exercise — protocols change quickly enought that it’s often more useful to learn to learn new protocols than it is to learn one individual protocol 😉 ). However in a real application, using a protocol that is supported by the target handset and operator network is a fundamental concern. As I discovered in my previous blog entry, the operator network is not always willing to route http to an unfamiliar server port number, so the network is will probably like sending plain socket transmissions to a strange port even less…

On the other hand, your SMS is sure to get through. 😀

Advertisements

6 comments so far

  1. Mekhi on

    Can anyone recommend me?
    I need an free sms service for my homepage.
    I am seeking one with the option to change the design(for a bit).
    Thanks a million!

  2. carolhamer on

    Hi Mekhi,

    There’s one here: Text 4 Free. That’s the only one I know of, and I don’t know if it allows you to change the design.

    Otherwise, you may find more where I found this one, namely Wikipedia: SMS gateways

  3. Thierry on

    Hi Carol,
    I would like to intercept from my Midlet all standard sms sent by other mobile phones. But of course, I don’t know the sms port to watch. Do you know who set sms port number in that case ? operators ? phone manufacturers ?
    Thank u,
    Thierry

  4. carolhamer on

    Hi Thierry,

    Are you asking how to receive the standard SMS (text) messages that are sent to the main inbox of the handset?

    Unfortunately, you can’t intercept those from Java.

    When one person sends an SMS to another handset the normal way (specifying the phone number but not a port number), the handset’s operating system won’t direct the message to a MIDlet.

    (At least not in a standard way — in theory you could have an aggreement with the handset manufacturer so that your MIDlet is acting as the user’s standard inbox, but this requires special programming on the manufacturer’s part.)

    You can only catch those messages that are sent to a specific port number.

  5. carolhamer on

    Here’s the code for the dynamic push port registration exercise. Start with the WTK’s SMS demo and add constants and change the SMSReceiver’s startApp as follows:

    /** default port number */
    public static final int DEFAULT_SMS_PORT = 16133;
    /** min possible port number */
    public static final int MIN_SMS_PORT = 16000;
    /** max possible port number */
    public static final int MAX_SMS_PORT = 16999;

    public void startApp() {
    // See whether we’re already registered.
    connections = PushRegistry.listConnections(false);
    // Create the URL string for the dynamic push port:
    String smsProtocol = “sms://:”;
    smsPortNum = DEFAULT_SMS_PORT;
    String smsPort = smsProtocol + smsPortNum;
    // As long as no connection is registered, keep
    // trying to get registered:
    while ((connections.length == 0) && (smsPortNum port: ” + smsPortNum);
    ioe.printStackTrace();
    smsPortNum++;
    smsPort = smsProtocol + smsPortNum;
    } catch (Exception e) {
    e.printStackTrace();
    content.setString(“failed to register–>port: ” + smsPortNum);
    display.setCurrent(resumeScreen);
    return;
    }
    }
    // print the URL string to the console of the connection
    // that worked:
    System.out.println(“connection: ” + connections[0]);
    try {
    smsconn = (MessageConnection) Connector.open(smsPort);
    smsconn.setMessageListener(this);
    } catch (IOException ioe) {
    ioe.printStackTrace();
    }

    // Initialize the text if we were started manually.
    connections = PushRegistry.listConnections(true);
    if (connections == null || connections.length == 0) {
    content.setString(“Waiting for SMS on port ” + smsPortNum + “…”);
    } else {
    System.out.println(“connection: ” + connections[0]);
    }
    done = false;
    thread = new Thread(this);
    thread.start();

    display.setCurrent(resumeScreen);
    }

  6. Jason on

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: