You may be used to thinking of mobile phones as client devices, but they may be full-fledged networked citizens, with the ability to receive incoming network connections. Although ServerSocketConnection provides the ability to listen for incoming socket connections, it can only be active while a MIDlet is actually running.
A typical server loop, listening for incoming socket connections on port 80, looks something like this:
ServerSocketConnection ssc;
ssc = (ServerSocketConnection)Connector.open("socket://:80");
boolean trucking = true;
while (trucking) {
SocketConnection sc = (SocketConnection)ssc.acceptAndOpen();
// Handle the client connection sc.
}
MIDP 2.0 goes one step further and allows MIDlets to be launched in response to incoming network connections. The name for this technique is push. You could, in theory, create a web server MIDlet, although in practice a mobile phone is probably a poor platform for a web server. A more likely example would be an SMS MIDlet, something built using JSR 120, the Wireless Messaging API. Assuming the MIDlet was configured correctly, incoming SMS messages would cause the MIDlet to be launched to handle the connection.
A MIDlet may register for push connections in two ways. It can register at runtime, using static methods in javax.microedition.io.PushRegistry, or it can register at install time using special entries in the application descriptor (JAD file). The important thing to remember is that the push registry has a lifetime beyond your MIDlet. It is part of the MIDlet management software that runs on the device. When a MIDlet registers for push notifications, the device software is obligated to listen for incoming network connections and launch your MIDlet if the appropriate connection is made.
Inside your MIDlet, you don't have to do anything different to catch the incoming connection. All you do is call Connector.open() with the appropriate network listening string.
Let's say, for example, that you had created a web server in a MIDlet and called it PatchyMIDlet. (The source code for this book, available from http://www.apress.com/, includes PatchyMIDlet; it sends a randomly selected text message in response to incoming requests.) This MIDlet responds to incoming socket connections on port 80 (the default HTTP port). If you wanted to register the MIDlet at runtime, you'd do this in the code somewhere:
PushRegistry.registerConnection("socket://:80", PatchyMIDlet, "*");
The first two parameters are pretty clear—any incoming socket connections on port 80 should launch PatchyMIDlet. The third parameter is a filter that will be applied to incoming connections. In this case, we accept all incoming connections with the "*" wildcard. Other possibilities would be to restrict incoming connections to a single IP address or a range of addresses.
Remember, the results of the call to registerConnection() persist beyond the lifetime of the MIDlet. Even after the MIDlet has been destroyed, the MIDlet management software on the device is watching out for incoming socket connections on port 80. If a connection is received, PatchyMIDlet will be launched. The push registry doesn't actually do anything with the incoming connection; it just detects it and launches a registered MIDlet to respond. It's the MIDlet's responsibility to accept the incoming connection. To find out whether it has been launched by the push registry or the user, the MIDlet can call PushRegistry's listConnections() method, passing true for the available parameter. The method will then return a list of connections that have input available. If this list is empty, then the MIDlet must have been launched by the user, not by an incoming connection.
Instead of a MIDlet registering push connections at runtime, it's much more likely that the push registrations would be contained in the application description for the MIDlet suite containing PatchyMIDlet. Thus, the push registration would be performed at installation time so that the user would never need to run the MIDlet manually. In this case, the MIDlet descriptor would contain a line like this:
MIDlet-Push-1: socket://:80, PatchyMIDlet, *
The parameters are exactly the same. The push registration is made when the MIDlet suite is installed. If the MIDlet cannot be registered (for example, some other application might already be listening for incoming socket connections on port 80), then the MIDlet suite will not be installed. Multiple push registrations are listed in the descriptor using ascending numbers: MIDlet-Push-1, MIDlet-Push-2, and so on.
The J2ME Wireless Toolkit (version 2.0) allows you to register and test push connections easily. Just click on the Settings… button, then choose the Push Registry tab. If you downloaded the source code for this book, you'll see an entry for PatchyMIDlet. Figure 9-5 shows this entry.
To test the push notification, you'll have to package the application, then deploy it on the emulator. First choose Project ?/font> Package ?/font> Create Package to package the project into a MIDlet suite JAR. Then choose the Project ?/font> Run via OTA from the KToolbar menu. You'll see the emulator pop up, showing its Application Management Software (AMS). Select Install Application, then accept the URL that is supplied. KToolbar contains a small OTA server; the URL is automatically preloaded when you select Run via OTA. You will see a series of other prompts about installing the application; just say yes to everything. Eventually the installation succeeds and you will see the MIDlet suite wj2 listed in the emulator's menu. The emulator is now running, listening for incoming connections, even though no MIDlets are running.
Now test PatchyMIDlet by pointing your browser to http://localhost/. PatchyMIDlet will be launched and will send a response to the browser. (The emulator will ask if it's okay to send data back on the network; you'll have to say yes.) Figure 9-6 shows the emulator running PatchyMIDlet and a browser showing its output.
Run via OTA is an excellent tool for testing your MIDlet's installation behavior rather than its runtime behavior. Just remember that you need to package the MIDlet first because the toolkit's small OTA distributes the MIDlet suite JAR file from the project's bin directory.
| Note?/td> |
The Run via OTA feature is not available in the J2ME Wireless Toolkit 2.0 beta 1. It was added in version 2.0 beta 2. |
PushRegistry contains several other static methods that are related to network registrations. The getMIDlet() and getFilter() methods return the MIDlet name and filter for a given network connection string. The listConnections() method returns a string array containing all the registered network connection strings. Finally, to remove a connection-to-MIDlet mapping, use unregisterConnection().