Archive for October, 2006|Monthly archive page

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

Troubleshooting blues…

“Why won’t my MIDlet connect with my Servlet?”

It’s such a simple question, isn’t it?

Unfortunately, there are so many layers of communication and so many places to make a little (yet fatal) error, that there’s no simple answer that solves the problem every time.

In my experience, establishing the initial “hello world”-level back-and-forth communication between the client and the server is one of the most frustrating steps in client-server programming. Once you’ve established a complete and correct communication circuit, you’ve got your foundation to build on. Before that — even if you know your networking and protocols well — you’re kind of tossing your message into the black void and hoping it comes out the other side…

But troubleshooting — tracking the problem down wherever it may be — is something every good engineer should be ready and able to do. So let’s talk a little bit about strategies for narrowing down where the problem may lie in a simple case such as a MIDlet that fails to connect with a Servlet via HTTP.

1. Does it work locally, on the simulator?

Getting it running on the WTK simulator is the first step to making sure it isn’t your MIDlet or Servlet that are the problem. Unfortunately, even if it works on the simulator, it still may be that your MIDlet is wrong. Sometimes the WTK is excessively lenient about things that your handset might not like such as reading the body of the message before getting the response code.

If it’s not even working on the WTK, what can you do?

As a general rule, at this point, I would strip my example down to the simplest possible example — a servlet that returns “hello world” and a MIDlet that displays the response code and the message recieved — to reduce the number of places where things can go wrong.

Be sure you know where your server logs are, and check them for clues. Try your URL in your browser and see what the browser returns. If you’re running the client and server on the same machine, you can substitute 127.0.0.1 for the IP address to see if it’s some sort of routing issue. If none of that yields any response from the server, try your server’s “Hello World Servlet” tutorial.

On the client side, note that the WTK has a built-in profiler. You can find it under Edit > Preferences > Monitor > Enable Profiling. This will display for you the raw data exchanged between the client and the server. I’m a little wary of this profiler because it starts some processes that sometimes interfere with installing a MIDlet using Project > Run via OTA for some unexplained reason, but when you really need it, the profiler is useful.

Now, let’s suppose it’s working on the WTK simulator but not on the handset.

2. Can the handset successfully make any HTTP communications from Java?

Generally a handset has a configurable profile which gives information regarding proxy servers and whatnot that tells how to get from the operator’s network to the open Internet. Sometimes the handset has a separate profile for Java and for WAP. They’re usually careful to make sure the WAP profile is right, so if they’re separate, one thing to do is to copy the data from the WAP profile to the Java profile, if you can find the right menus to do it…

One way to check if your Java profile is correct is to try some other working MIDlet that makes a connection via HTTP. For example, I ran the MobileZoo MIDlet the other day, and it succeeded in contacting MobileZoo, so I know that my handset is correctly configured to use HTTP from Java.

3. Is the server accepting requests from the outside?

You know the old story: internal routing is different from external routing, and those lovely firewalls… Try your URL on a computer outside of your local network.

Now once you’ve done all that, it should work!!!

Unfortunately for my “Hello World” MIDlet/Servlet it doesn’t…

I think we’ve narrowed it down to the fact that I’ve set up my server to use a non-standard port for HTTP, and some step in the network chain doesn’t like it.

Hopefully it will be up and running this weekend. I’ll keep you posted!!! 😀

Mobile Zoo!!!

My planned post for today was going to be some interaction exercises (either HTTP or SMS — I hadn’t decided), but it looks like I won’t have anything post-worthy on that front before Wednesday at the earliest (I got sidetracked this weekend by some household tasks), so instead I’ll tell you about playing with the new alpha download from MobileZoo. It should be kosher to blog about this since I don’t see any way this could be a competitor to MobileScope.

I’ve chosen this topic not only because I find MobileZoo’s concept intriguing, but also on the principle that — since this is a new blog — I give preferential treatment to anyone who leaves a comment on my blog. Even if the comment is just an ad for your new start-up. 😉  (As long as the comment is relevant to my post of course.)  My goal is to get so many comments that the welcome default comment from “Mr. WordPress” drops out of the “Recent Comments” section of my sidebar. Sure I could just delete it, but that would be cheating…

The idea of MobileZoo appears to be the creation of a centralized database of all of the precise specs a Java developer might need to optimize an application for a given handset (including which JSRs are supported with version numbers if applicable, plus screen and canvas size and colors, etc.). All of this information is harvested by a MIDlet along the same lines as the MIDlet I posted the other day only more extensive, gathering up every bit of information about the handset that is accessible via Java. Then the MIDlet sends this information to MobileZoo. It looks like the revenue model is to offer a premium service and/or a stats-gathering library to registered developers. (Or maybe they’re just planning to get paid through putting ads on their site?)

So, I downloaded their jar of goodies to try it out.

The first thing I noticed was that the download is a jar file alone. I guess that’s okay since this product/service is aimed at developers, and one can reasonably expect that a Java ME developer would know how to take a jar file from his local PC and get it installed on a handset. However, personally I don’t have a cable or other simple way of connecting my handset directly to my PC, so I ended up writing my own jad (descriptor) file for it. For that I had to open the jar file and copy a bunch of lines out of the mainfest file and then add the jar size and jar url attributes by hand. Then I uploaded the files to my site so I could download them onto my handset from there. Since this project depends on persuading as many people as possible to run this program on their handsets, MobileZoo might want to make their MIDlet available on a WAP page (if it isn’t already) and post the URL on their main page. There’s no reason not to do that since it would only take a few minutes to add this feature to their site, and it might make it easier for some novice developers and other random users.

It’s pretty clear that it’s an alpha. Some of the links on the site don’t work, the “français” page is the same as the English page, there are grammatical errors, etc. (Of course I’m hardly one to taalk — I’ve noticed that my previous blog entry is riddled with typos, but I can’t go back and correct it without screwing up the formatting on the code sample because of the screwey blog editing software. But that’s an unrelated minor squabble between me and Mr. WordPress. 😉 .) Anyway, every good idea has to start somewhere.

I was almost a little hesitant to run this program on my handset, since it’s an unknown application that I just happened to download off the Internet that’s going to read information from my handset and then send that information to some unknown site on the Internet. However — given Java’s security system — I don’t think there’s really much danger that a MIDlet running with the “untrusted” security level can do any harm. (I know it’s running as “untrusted” since there’s no digital signature in the jad file I wrote for it…) I double-checked the PIM API JavaDoc to make sure that an untrusted MIDlet can’t read information from my addressbook without asking for permission, so I know they’re not even trying to harvest my contacts’ phone numbers for some nefarious marketing purposes or something. Even so, since I’m not much of a trusting soul I guess, I ran it first on the WTK to see what it was going to do. (There it had a strange Exception, but ran anyway.)

And here’s the result.

Amusingly, the program failed to identify my handset as a Sagem — it looks like this is the first Sagem they’ve captured stats for.

All in all, this looks like a fun idea. My one concern would be to wonder how they’ll persuade enough people to install and run their program. It costs the user effort and network time, and the user doesn’t get much in return except detailed developer-level information about the local handset. I guess that’s enough to make it interesting for me, but for how many others? Maybe they should reward the user by showing an animation of a dancing monkey during the upload? Hehe, just kidding, but it seems like it would be a good idea to somehow make this little procedure more cool and fun so kids will recommend it on forums or mySpace or whatever… 😉

JSRs galore!!!

One of the things I had to learn about when I switched from programming Enterprise Edition Java to Mobile Edition was Java Specification Requests. Of course I was vaguely aware of JSRs and the Java Community Process as en Enterprise Edition programmer, but I didn’t really have to deal with them much in my daily life. (This was back in the old days when it was called “J2EE” 😉 )

But when you’re programming for mobile phones, as much as you’d like it to really be as simple as “write once, run anywhere,” devices unfortunately vary in implementation (behavior) as well as in terms of which standard (optional) APIs are available. So you get to know your JSRs, and keep track of which ones your program needs in order to run.

The very first new thing I wanted to try on my new Sagem my700x was to write a simple program to tell me which JSRs are available for me to play with. This info is probably available through everyone’s best friend (Google), but you’d probably have to dig around for it. Normally the specs you find on the Internet (like here) will tell you if the handset has Java, and whether it’s MDIP 1 or MIDP 2 and not much more. That’s okay, because it sets us up for a fun little exercise!!!

Let’s make a simple MIDlet to find out what JSR APIs are implemented on this handset!!!

It’s maybe not realistic to check for all possible JSRs, but at least we can check for the ones that are implemented in the WTK. Running the ktoolbar application and selecting the “Settings” button (after opening a new project), I get a window that lists the following optional JSRs: JSR 75 (PIM), JSR 75 (File Connection), JSR 82 (Bluetooth), JSR 135 (Mobile Media), JSR 172 (Web Services RMI), JSR 172 (Web Services SAX), JSR 184 (3D Graphics), (JSR 205 Wireless Messaging).

I looked them all up here and downloaded the final draft documentation for each one.

The next step was to write a MIDlet that attempts to load a class from each optional package. I assume that if one class is there, the whole package is probably there too. For fun I decided to check for MobileScope’s EGE API as well!!! 😀

The result on the WTK was exactly as expected: all of the above APIs are supported except MobileScope’s EGE API.

Here’s the result for the Sagem m700x:

JSR 75 PIM: supported,
JSR 75 File Connection: supported,
JSR 82 Bluetooth: not supported,
JSR 135 Mobile Media: supported,
JSR 172 Web Services RMI: not supported,
JSR 172 Web Services SAX: not supported,
JSR 184 3D Graphics: supported,
JSR 205 Wireless Messaging: not supported,
EGE: supported.

If you’d like to try the MIDlet on your own handset, I’ve put it on my site here: http://www.frog-parrot.net/hello.wml

Here’s the code:


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.lcdui.List;
import javax.microedition.midlet.MIDlet;
/**
* A simple MIDlet to test which APIs are implemented.
*/
public class Test extends MIDlet implements CommandListener {
  
  private Command m_exitCommand = new Command("Done", Command.EXIT, 1);
  private List m_menu;
  private Form m_resultScreen;
  /**
   * The list of API labels.
   */
  private String[] m_jsrs = {
    "JSR 75 PIM",
    "JSR 75 File Connection",
    "JSR 82 Bluetooth",
    "JSR 135 Mobile Media",
    "JSR 172 Web Services RMI",
    "JSR 172 Web Services SAX",
    "JSR 184 3D Graphics",
    "JSR 205 Wireless Messaging",
    "EGE",
  };
  
  /**
   * The index constants for the label array.
   */
  private static final String SUPPORTED = "Supported";
  private static final String NOT_SUPPORTED = "Not Supported";
  private static final int JSR_75_PIM = 0;
  private static final int JSR_75_FC = 1;
  private static final int JSR_82_BLUETOOTH = 2;
  private static final int JSR_135_MOBILE_MEDIA = 3;
  private static final int JSR_172_WEB_SERVICES_RMI = 4;
  private static final int JSR_172_WEB_SERVICES_SAX = 5;
  private static final int JSR_184_3D_GRAPHICS = 6;
  private static final int JSR_205_WIRELESS_MESSAGING = 7;
  private static final int EGE = 8;
  
  /**
   * Empty constructor.
   */
  public Test() {
  }
  
  /**
   * Initialize the Displayables.
   */
  public void startApp() {
    m_menu = new List("Test Menu", List.IMPLICIT, m_jsrs, null);
    m_menu.addCommand(m_exitCommand);
    m_menu.setCommandListener(this);
    Display.getDisplay (this).setCurrent(m_menu);
    m_resultScreen = new Form("Results");
    m_resultScreen.addCommand(m_exitCommand);
    m_resultScreen.setCommandListener(this);
  }
  
  public void pauseApp() {
  }
  
  public void destroyApp(boolean unconditional) {
  }
  
  /**
   * Change the display in response to a command action.
   */
  public void commandAction(Command command, Displayable screen) {
    if(screen == m_menu) {
      if(command == m_exitCommand) {
        destroyApp(false);
        notifyDestroyed();
      } else {
        m_resultScreen.deleteAll();
        int index = m_menu.getSelectedIndex();
        switch(index) {
        case JSR_75_PIM:
          m_resultScreen.append(m_jsrs[JSR_75_PIM] + ": ");
          try {
            Class.forName("javax.microedition.pim.PIMException");
            m_resultScreen.append(SUPPORTED);
          } catch(ClassNotFoundException e) {
            m_resultScreen.append(NOT_SUPPORTED);
          }
          Display.getDisplay(this).setCurrent(m_resultScreen);
          break;
        case JSR_75_FC:
          m_resultScreen.append(m_jsrs[JSR_75_FC] + ": ");
          try {
            Class.forName("javax.microedition.io.file.ConnectionClosedException");
            m_resultScreen.append(SUPPORTED);
          } catch(ClassNotFoundException e) {
            m_resultScreen.append(NOT_SUPPORTED);
          }
          Display.getDisplay(this).setCurrent(m_resultScreen);
          break;
        case JSR_82_BLUETOOTH:
          m_resultScreen.append(m_jsrs[JSR_82_BLUETOOTH] + ": ");
          try {
            Class.forName("javax.bluetooth.BluetoothConnectionException");
            m_resultScreen.append(SUPPORTED);
          } catch(ClassNotFoundException e) {
            m_resultScreen.append(NOT_SUPPORTED);
          }
          Display.getDisplay(this).setCurrent(m_resultScreen);
          break;
        case JSR_135_MOBILE_MEDIA:
          m_resultScreen.append(m_jsrs[JSR_135_MOBILE_MEDIA] + ": ");
          try {
            Class.forName("javax.microedition.media.MediaException");
            m_resultScreen.append(SUPPORTED);
          } catch(ClassNotFoundException e) {
            m_resultScreen.append(NOT_SUPPORTED);
          }
          Display.getDisplay(this).setCurrent(m_resultScreen);
          break;
        case JSR_172_WEB_SERVICES_RMI:
          m_resultScreen.append(m_jsrs[JSR_172_WEB_SERVICES_RMI] + ": ");
          try {
            Class.forName("java.rmi.RemoteException");
            m_resultScreen.append(SUPPORTED);
          } catch(ClassNotFoundException e) {
            m_resultScreen.append(NOT_SUPPORTED);
          }
          Display.getDisplay(this).setCurrent(m_resultScreen);
          break;
        case JSR_172_WEB_SERVICES_SAX:
          m_resultScreen.append(m_jsrs[JSR_172_WEB_SERVICES_SAX] + ": ");
          try {
            Class.forName("org.xml.sax.SAXParseException");
            m_resultScreen.append(SUPPORTED);
          } catch(ClassNotFoundException e) {
            m_resultScreen.append(NOT_SUPPORTED);
          }
          Display.getDisplay(this).setCurrent(m_resultScreen);
          break;
        case JSR_184_3D_GRAPHICS:
          m_resultScreen.append(m_jsrs[JSR_184_3D_GRAPHICS] + ": ");
          try {
            Class.forName("javax.microedition.m3g.CompositingMode");
            m_resultScreen.append(SUPPORTED);
          } catch(ClassNotFoundException e) {
            m_resultScreen.append(NOT_SUPPORTED);
          }
          Display.getDisplay(this).setCurrent(m_resultScreen);
          break;
        case JSR_205_WIRELESS_MESSAGING:
          m_resultScreen.append(m_jsrs[JSR_205_WIRELESS_MESSAGING] + ": ");
          try {
            Class.forName("javax.wireless.messaging.SizeExceededException");
            m_resultScreen.append(SUPPORTED);
          } catch(ClassNotFoundException e) {
            m_resultScreen.append(NOT_SUPPORTED);
          }
          Display.getDisplay(this).setCurrent(m_resultScreen);
          break;
        case EGE:
          m_resultScreen.append(m_jsrs[EGE] + ": ");
          try {
            Class.forName("com.infusio.ege.toolkit.TLV");
            m_resultScreen.append(SUPPORTED);
          } catch(ClassNotFoundException e) {
            m_resultScreen.append(NOT_SUPPORTED);
          } catch(Exception e) {
            m_resultScreen.append(e.getClass()
                                  + ": " + e.getMessage());
          }
          Display.getDisplay(this).setCurrent(m_resultScreen);
          break;
        default:
          break;
        }
      }
    } else {
      Display.getDisplay (this).setCurrent(m_menu);
    }
  }
}

Did I say Sagem myX700?

It’s written right on the handset my700x!!!

Dyslexics of the world, untie!!! 😉

Strategies and Mobilists

I’ve just added the “Carnival of Mobilists” to my little reading list over on the side there. It’s interesting stuff — a lot of discussions on the different mobile technologies out there and where the industry is going.

The funny thing is that for me, reading about where the industry is going and what various companies are up to has always been kind of like eating broccoli (or whatever your least-favorite-yet-good-for-you vegetable is…). Yet I’ve discovered that for some reason it’s more interesting on blogs. It seems kind of counterintuitive that reading things that random people have posted for free would be more interesting than serious news outlets, but it makes sense: A lot of news in the standard press consists of (maybe slightly modified) press releases, and it’s hard tell anything from a press release except that the P.R. departments of the companies involved want you to think that this new product or merger or whatever is the greatest thing since sliced bread. Whereas the bloggers tell what they think of the prospects of various technologies and why. Plus a lot of them are writers promoting themselves, so they’re skilled and motivated to write something interesting.

I’m not sure I really fit in with that particular blogging carnival since my interest here is more to get down in the guts of new technologies to see on how to apply them in practice, and only occasionally come up for air to tell you what I think of them and how they compare to related technologies. Off the top of my head yesterday I came up with a list of eleven little projects I’d like to try and write about here. So I should probably go find myself a carnival of mobile software engineering blogs. 😉 But it’s good to get some added perspective by reading the higher-level tech business blogs.

I have one little thing to say about macro business strategy though, and that’s that I think it’s cool that mobiles are starting to follow the rest of the Internet in the direction of having a big draw be socializing through content uploading and interacting with other users. It makes sense that a lot of this online interaction would be entirely mobile-based (i.e. there are people you play a game with on your mobile, but you don’t necessarily play a P.C. game at home against the same people). However, I’m more excited about the prospect of mobile applications having a tie-in with existing communities on the Internet.

For one thing, it’s difficult to build a community from scratch through mobile interaction, except for cases like games where the application provides a natural framework/activity. I can’t really see getting hooked on, say, a forum through my handset just because I can’t see that many posts at once, and what’s more it’s a pain to type a post on that tiny keyboard. But people who are already hooked on Internet communities are a great potential market for mobile services.

It’s almost kind of funny that the classic example program for an online service was originally the “real-time stock quotes” program. Probably many engineers (like me!) have a difficult time relating to people wanting such a thing (see above about how fascinated I am by business news). At least since the year 2000 anyway. Whenever I read tutorials implementing that service, I mostly just relate to the exercise on the “sell software to people who have money” principle.

On the other hand, I can easily see wanting to have a mobile client to stay up-to-the-minute on the latest posts on favorite blogs, forums, and wikis. My classic example program for an online service would be one that gives real-time blog stats for those neurotic bloggers who compulsively check their stats every twenty minutes. Not that I know anybody like that. Anyway, I’m totally exaggerating. I mean every five minutes.

It’s not clear how one could make money off such a thing, but identifying the market is an important step. Then comes a fun little engineering exercise known as designing the billing model… 😉

One more time, from the top!!!

My task for today was to set up my home development environment from scratch.

Obviously this should be nothing for a serious programmer, but the problem is that my Sys Admin is just too nice!!! So I’ve been spoiled — for many tasks I could do for myself, I had a bad habit of saying “Oh, I’ll just ask my Sys Admin to do it.” This includes browsing around the http://java.sun.com/ site to find the right Java SE and Java ME versions to download and install. This is weirdly more confusing than it should be, made worse by the fact that I left my java developer account username and password on my computer at work only, and when I hit “send” on the “forgot your password” page, of course it sent the password to my work email address, which I can’t access here. D’oh! So I had to make another account…

I had to get Java SE installed in order to install the wireless toolkit to develop for Java ME, and annoyingly since our last Linux upgrade, the version of Java SE I’d been using seems to have disappeared — I could only find pre-1.4 versions of the JDK, which aren’t recent enough. But with a little navigation effort, I managed to find myself a JDK 1.5.0-09 and a WTK 2.2 download for my system. The installation was simple enough that I won’t bore you with the details. Just read the “read me” — if you can find it on their site!!! Mwa-ha-ha!!!

Once everything was installed, I launched KToolbar. Writing my book, I’d gotten into the habit of running from the command line, keeping in mind that the documentation will tell me all of the possible environment and preferences options. But there’s also something to be said for having a nice GUI where all of the possibilities are right there in the menus. I would recommend being familiar with both the “for simplicity” (GUI) method and the place to go to look deeper. As I’ve said, the WTK documentation is pretty good, and you can find most of the things you’d like to do there.

So from KToolbar, I selected “create a project” for my “Jump” (Tumbleweed) game, and — as expected — the program created everything I needed exept the source code. 😉

Then I copied all of the source files from my Jump game into the directory that the “create a project” option created. I’ve zipped it into a nice file, so if you have your WTK installed, just unzip this under the WTK’s apps directory, and the Jump project will be there when you choose “open a project.” Then build (under the “project” menu) and run.

Now, exactly as Seapegasus discovered here, you’ll find that the screen is too big, so — since I’ve carefully optimized this game for a particular screen size 😉 — you get an exception.

I could go to the source code of JumpCanvas.java and change the screen size requirements, but it looks like Seapegasus has proposed an interesting exercise where that would be cheating. 😉

How do we change the screen size to emulate (and write a program for) the screen of a smaller device? It’s really not obvious… Wandering through KToolbar’s menus, there are a lot of items you can tweak, but screen size isn’t one of them.

Since I wrote this program, I feel responsible for making the effort to figure out how to get it to run. And it’s a fun opening exercise to get to know the entrails of the WTK’s file-structure. 😉

My first instinct was to go after some familiar configuration files that I have to modify all the time in my daily life: WTK/lib/internal.config, WTK/lib/system.config, and WTK/wtklib/emulator.properties. Just look at them — you’ll see that you can modify a lot of system parameters directly right there, especially dealing with networking and communications. But none of them said anything about screen size…

So digging around some more, I noticed the WTK/wtklib/devices directory had subdirectories for all of the various devices…

So, I made a copy of the whole directory “DefaultColorPhone” naming it “CarolColorPhone” ;-), and renamed the DefaultColorPhone.properties under it to CarolColorPhone.properties. In that file I found “screenPaintableRegion.width” and “screenPaintableRegion.height” and thought “Aha, jackpot!” Looking at the values in JumpCanvas.java, I saw that all I needed to do was change the value of “screenPaintableRegion.height” to 250.

Then I ran KToolbar, and “CarolColofPhone” appeared in the little “Device” drop-down menu, and had the desired screen size. This was a particularly fun exercise, because I did the first thing I guessed to do and it worked!!!  (Well, almost the first thing…)  That usually doesn’t happen — it always seems like in an unfamiliar system it’s a little tweak here and a little tweak there for hours until you zero in on what you need to do.

Of course as always, eliminating one bug makes it run just up to the next bug…

The next thing I got was a java.io.IOException…

This is a familiar enough exception with a new set-up that I should have guessed off the top of my head what the problem was, but I didn’t. So I added an “e.printStackTrace()” in a strategic location and built and ran again. Can you guess what it was? If not, the stack trace should make it pretty obvious!!!

java.io.IOException
    at javax.microedition.lcdui.ImmutableImage.getImageFromStream(+15)
    at javax.microedition.lcdui.ImmutableImage.<init>(+20)
    at javax.microedition.lcdui.Image.createImage(+8)
    at net.frog_parrot.jump.Cowboy.<init>(+6)
    at net.frog_parrot.jump.JumpManager.<init>(+72)
    at net.frog_parrot.jump.JumpCanvas.<init>(+249)
    at net.frog_parrot.jump.Jump.<init>(+75)
    at java.lang.Class.runCustomCode(+0)
    at com.sun.midp.midlet.MIDletState.createMIDlet(+19)
    at com.sun.midp.midlet.Selector.run(+22)

Oops, forgot to copy the image files into the right place where they’ll be included in the game’s jar file!!! D’oh!!

But easy to fix. And now it runs, yay!!!! 😀

My games on my phone!!!

The first step was to install the games from my book on my new handset.

This was a pretty simple exercise — the only glitch was that some of the built jar files I had lying around on my machine were earlier versions (with a bug, unfortunately), so it took me a couple of tries to get the correct version built, uploaded to my website, and from there downloaded onto the phone.

I had of course already played my MIDP 1 games (Maze and Car-Voiture) on my old Nokia 6100. Here’s what they look like on my new Sagem:

Now I hate to admit this, but I didn’t get a chance to test my MIDP 2 games on an actual handset before the book went to press. This is because at the time MIDP 2 handsets weren’t available on the market. There was one Nokia that almost came out in time for me to buy it as my game-prototype handset (but didn’t quite make it). And though I was working for a mobile gaming development firm during the corrections phase, I was working with the simulator myself, not actual handsets. Of course I’ve had my hands on tons of MIDP 2 handsets since then, so I suppose the fact that I never bothered to upload these games on any of them shows a deplorable lack of curiosity. But I’m here to make up for it now!!!

I feared the worst, especially since another blogger who said some nice things about my book here noted that the screen-size restrictions I’d placed on my game prevented it from running in his environment. I assumed I’d run into the same problem and have nothing to see. So I was pleasantly surprised when my Dungeon game ran great on my Sagem, and was more fun than I’d remembered it (if I do say so myself 😉 ).

I ended up just sitting around playing this one for a bit. I’d forgotten how much care I’d put into designing these boards to be built of simple building blocks and described by a very small amount of data, yet tricky enough that you always need to use at least two keys to solve each board and not always obvious which key will be useful when. That’s my excuse for why I limited the screen size by the way — if you see the whole dungeon at once the solution is obvious. (That’s my excuse for this game anyway — I don’t remember what my excuse was for doing that on Tumbleweed.)

Here’s Tumbleweed:

This one really is kind of an absurd game, but the animated jumping cowboy and waving grasses are entertaining. The music track I invented for it is a bit less amusing. My husband stopped by the computer room to tell me how annoying the music is, but it was hardly necessary to point it out. So we learn that while it’s possible to write music for a game using a tone sequence, it is a pretty rudimentary tool — it’s difficult to get something that sounds professional from it. I’m pretty sure all of the games produced by the company I work for use real sound files.

I’ll test the Checkers game later because of the networking involved…

You can download these games onto your handset at the following address: http://www.frog-parrot.net/hello.wml

I normally think of myself as a person with very little graphic design ability, and I’d set these games aside on the shelf for the past few years while working exclusively with games produced by studios that have at least a few graphic and game designers in addition to just programmers, so I kind of expected to find these absurdly clunky — just prototypes to illustrate programming techniques. I was pleasantly surprised to see they’re actually not too bad as games. The thing is that even as these devices increase in computing power and memory, you’re still fundamentally limited by screen size an ergonomics, which means that often a simple game ends up being more fun and popular than something more complex.

That said, there are some fairly simple things you can do to take your game up a notch from the design level illustrated by these examples and turn it into something that looks polished and professional (in addition to the obvious “be a good artist or hire one” 😉 ). That’s one of the topics I hope to discuss in this blog.

First things first, though. My next installment will be setting up the latest wireless toolkit and maybe some other emulators as well.