Archive for the ‘SMS’ Category

BlackBerry PushRegistry How-To

Suppose you’d like to create a BlackBerry application that will launch when you send an SMS message to the appropriate port.  It’s possible, but there are a number of non-obvious (and not-necessarily-documented) tricks.  I spent a few too many hours on experimenting to figure out precisely what works, and I’m posting my notes here to save you some time:

  1. Apparently your application has to be a MIDlet, not a “CLDC application” (RIMlet).  I was a little surprised when I read this in the BlackBerry Java Dev forum, since it would undoubtedly be trivial for RIM to allow either type of application to register with the PushRegistry and get launched.  So I did a few tests (with a “MIDlet-Push-1” Jad property analogous to the way the RIMlet uses the “MIDlet-1” property), and, indeed, the PushRegistry doesn’t seem to work for RIMlets, but it works fine for MIDlets. (Note: it’s still theoretically possible that there’s a way to make it work for RIMlets, but I couldn’t find the trick.)
  2. Adding a custom property to your Jad file is really easy if you know the trick. 😉 The trick is that (in the BlackBerry JDE) you can add the Jad file to the project (in the same way you add source files and images).  Once you’ve added the Jad file to the project, you can add properties and then they won’t get overwritten when you rebuild.  But before you add it, you should modify the project properties (setting the application type to MIDlet) and then build the project once, so that it will create for you a correct initial Jad file to use.
  3. Before your application closes, you should dynamically re-register with the PushRegistry.  This was the trickiest one to guess!  If your MIDlet is launched by the PushRegistry — and you open the corresponding connection to read the SMS message that launched your MIDlet — this automatically unregisters your MIDlet from the PushRegistry.  With other handsets, once you’re registered with the PushRegistry (either statically in the Jad or dynamically from within the application), you stay that way until you actively unregister it.  But not BlackBerry.  Or at least not with the BlackBerry simulator that comes with the BlackBerry JDE 4.2.0.  I assume the behavior is the same in other versions and on the device, but I’m not certain…
  4. How do you simulate the SMS to test the application launch with the PushRegistry?  I explained that here.

SMS message exchange between BlackBerry simulator instances: a very simple demo

If you’re writing a BlackBerry Java application that sends and/or receives SMS text messages, naturally you need to be able to test the application on the simulator.  And naturally the simulator doesn’t really send SMS messages, so you need to know how to get the simulator to exchange simulated SMS messages with another instance of the simulator.

This is very easy to do.  You can do it with the SmsDemo that comes in the BlackBerry JDE’s sample applications bundle — even though the SmsDemo’s JavaDoc seems to imply that you can’t.  If you look in the code of SmsDemo.java (usually found at C:\Program Files\Research In Motion\BlackBerry JDE <version>\samples\com\rim\samples\device\smsdemo), the JavaDoc says the following:

This program requires the associated server component found in the com.rim.samples.server.smsdemo package under the samples directory in your JDE installation.

That’s not precisely true.  It doesn’t require the server component — it can actually send demo messages from one instance of the simulator to another, as long as you set the sms-source-port of the one to be the sms-destination-port of the other, and vice-versa.  There are just a few quick steps and notes for launching the two instances: Continue reading

More about JSR 75

For today’s JSR adventure, I improved my SMS checkers game — as promised — by adding a feature to read contacts from the handset address book to choose opponents. The new version is available as CheckersPlus. Then I figured that since I’m playing with JSR 75, I should write a sample program to test the other half of JSR 75: the FileConnection API.

I like the elegance of the FileConnection API, and in particular the way it’s designed to function just like the various network connection APIs (using Connector.open with a URL, returning a Connection with an InputStream and and OutputStream just as any a network connection). It’s a very natural way of accessing files both from the Java perspective (where files have traditionally been accessed through the same streams as sockets, etc.) and in the general networking universe (where users are already accustomed to reading local files in an Internet browser using a file://-type url).

Another cool advantage to FileConnection is that you can access parts of the handset’s memory that you can’t touch from MIDP’s standard little RMS memory sandbox. I found by listing the available file roots on my Sagem my700x that I can access the images folder. So for some handsets it may be possible to have a Java MIDlet store a wallpaper or a ringtone as a wallpaper or a ringtone by storing it in the right place where the handset can use it.

But that brings us to the usual disadvantage: you have to know the particular handset very well to know which folders you have access to and how to access them. So it’s great if your project has a small set of target handsets, and not so great if you want your application to be useful on all MIDP handsets across the board. The RMS (Record Management System) has the advantage of always being supported, so it’s probably better to use the RMS if all you want is to set some simple data aside and find it again later.

Of course, even the RMS isn’t as predictible as one might like. There are handsets where RMS access is slower than FileConnection access (and some where it’s not), some that handle individual records in unexpected ways (setting aside a big space for each record even if it’s not used, or failing to free up the memory of a deleted record). Then there’s the fact that the RMS is not convenient for pooling data among multiple MIDlet suites: To share a record store between suites, you need to leave the access door open to every MIDlet on the device, plus the record store is deleted when the associated MIDlet suite is deleted even if other MIDlet suites still wanted to access the data.

So, there’s a bit of a trade-off, meaning it’s better to know both the FileConnection API as well as the RMS, and choose which one to use depending on your application.

For today’s fun, here’s a sample class to illustrate the FileConnection API, doing a few very basic, standard things like listing the available roots and files; reading, writing, creating a test file, etc. As with PIM, FileConnection access is done in its own thread:

package net.frog_parrot.test;

import java.util.Enumeration;
import java.io.*;

import javax.microedition.io.*;
import javax.microedition.io.file.*;

/**
* A simple file Connection testing utility.
*/
public class FCRunner extends Thread {

FCTest myMidlet;

FCRunner(FCTest test) {
myMidlet = test;
}

public void run() {
FileConnection rootdir = null;
try {
Enumeration items = FileSystemRegistry.listRoots();

// Now print the available roots:
while(items.hasMoreElements()) {
String rootname = (String)(items.nextElement());
myMidlet.display(“\n *** new root: ” + rootname);

// open the root directory:
// note there are three slashes before the root name
// because there is no “host” for this connection:
rootdir = (FileConnection)Connector.open(
“file:///” + rootname);
// List the current files:
Enumeration ls = rootdir.list();
while(ls.hasMoreElements()) {
String filename = (String)(ls.nextElement());
myMidlet.display(” file: ” + filename);

// print the contents of the file:
FileConnection file = null;
try {
file = (FileConnection)Connector.open(
“file:///” + rootname + “/” + filename);
if(file.canRead()) {
InputStream is = file.openInputStream();
byte[] contents = new byte[25];
int len = is.read(contents);
is.close();
myMidlet.display(” contents: ”
+ new String(contents, 0, len));
} else {
myMidlet.display(” * not readable”);
}
} catch(Exception e) {
e.printStackTrace();
} finally {
try {
file.close();
} catch(Exception e) {}
}
}

// now try to create a file:
FileConnection newfile = null;
try {
newfile = (FileConnection)Connector.open(
“file:///” + rootname + “myNewFile”);
if(newfile.exists()) {
OutputStream os = newfile.openOutputStream();
os.write((new String(“overwriting old contents”)).getBytes());
os.close();
} else {
newfile.create();
OutputStream os = newfile.openOutputStream();
os.write((new String(“creating new contents”)).getBytes());
os.close();
}
} catch(Exception e) {
e.printStackTrace();
} finally {
try {
newfile.close();
} catch(Exception e) {}
}
}
} catch(Exception e) {
e.printStackTrace();
} finally {
try {
rootdir.close();
} catch(Exception e) {}
}
}

}

For completeness, here’s the MIDlet class to use to run the above FileConnection-testing class.  These two classes together make a complete MIDlet that can be easily built by creating a new project for it in the WTK:

package net.frog_parrot.test;

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.midlet.MIDlet;

/**
* A simple MIDlet to test which APIs are implemented.
*/
public class FCTest extends MIDlet implements CommandListener {

private Command myExitCommand = new Command(“Exit”, Command.EXIT, 1);
private Command myOkCommand = new Command(“OK”, Command.OK, 1);
private Form myResultScreen;

/**
* Empty constructor.
*/
public FCTest() {
}

/**
* Initialize the Displayables.
*/
public void startApp() {
myResultScreen = new Form(“Results”);
myResultScreen.addCommand(myExitCommand);
myResultScreen.addCommand(myOkCommand);
myResultScreen.setCommandListener(this);
Display.getDisplay(this).setCurrent(myResultScreen);
}

/**
* Implementation of MIDlet.
*/
public void pauseApp() {
}

/**
* Implementation of MIDlet.
*/
public void destroyApp(boolean unconditional) {
}

/**
* Respond to a button push.
*/
public void commandAction(Command command, Displayable screen) {
if(command == myExitCommand) {
destroyApp(true);
notifyDestroyed();
} else {
FCRunner runner = new FCRunner(this);
runner.start();
}
}

/**
* Append a string to the current display.
*/
public void display(String str) {
myResultScreen.append(str);
myResultScreen.append(“\n”);
}

}

SMS Checkers!!!

My SMS checkers game is done and now available!!! Try it out!!!

Just go here to download it free onto any MIDP 2 phone:

http://www.frog-parrot.net/checkers.wml

This version is a big improvement on the original. First of all, it’s a peer-to-peer game — relying entirely on exchanging SMS messages from one handset to the other — so any two people who both have the game installed can play it without worrying about whether a central server is up and running and accessible. The server wasn’t doing much more than routing the game moves from one handset to the other, so it was fairly easy to write it out of the picture.

Each move requires sending a whole SMS, yet the move data typically takes no more than five bytes. It seemed like such a shame to waste the rest of the SMS payload, so I added a “taunt” feature so that you can send your opponent a message along with your move if you like!!!

Another new feature is that the game can now recover from a pause — so you can receive a call and then return to the checkers game in progress.

Additionally I did a bunch of refactoring. The original game logic was great, but the meta-logic — the game state, whose turn it is, etc. — was too intimately tied to the communications/networking code. That makes for smaller code, but the game is already pretty small (16K). So I modularized it a bit, making separate classes for the game state logic and the communications code. Ah, with a personal project you get the luxury of taking the time to refactor the code when there’s a change in requirements! 😉

If you try this game, please feel free to post any comments about it, suggested improvements, etc. Thanks.

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. 😀