Thursday, May 24, 2007

Responsive UI: do the heavy lifting in backgroup thread

Slow wireless connection, less processing power, less memory, all these factors make JavaME applications tend to feel sluggish. One trick we developers can play is to use background thread to do the heavy lifting parts.

The sample code below shows how one can use a separate thread to perform the time consuming task, while the UI still interacts with user, and update the UI when the task is completed.

Please note that the Runnable object passed to UiApplication.invokeLater() should return quickly. The Runnable object is put into the event queue to be executed by the event dispatcher thread. During the time this runnable is executing, all new UI events are queued so the UI will not respond to any input.


package com.mycompany.sample;

import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.AutoTextEditField;
import net.rim.device.api.ui.component.ObjectChoiceField;
import net.rim.device.api.ui.container.MainScreen;

public final class DemoBackgroundThread extends UiApplication {
public DemoBackgroundThread(){
super();
pushScreen(new EditorScreen());
}

public static void main(String[] args) {
new DemoBackgroundThread().enterEventDispatcher();
}

private static class EditorScreen extends MainScreen {
private AutoTextEditField _firstNameField;
private AutoTextEditField _lastNameField;
private ObjectChoiceField _timezoneField;
public EditorScreen()
{
super();
_firstNameField = new AutoTextEditField("First Name: ", "");
_lastNameField = new AutoTextEditField("Last Name: ", "");
_timezoneField = new ObjectChoiceField("Timezone: ", new String[]{"Loading Timezones"});
add(_firstNameField);
add(_lastNameField);
add(_timezoneField);
new Thread(new Runnable() {
public void run() {
final String[] zones = new String[6];
zones[0] = "-Select Timezone-";
for(int i = 1; i < zones.length; i++) {
try {
//do the heavy lifting here, like fetching data from remote server or heavy calculations.
Thread.sleep(1000);
} catch (InterruptedException e) {
//who cares
}
zones[i] = "GMT-"+i;
}
UiApplication.getUiApplication().invokeLater(new Runnable(){
public void run() {
_timezoneField.setChoices(zones);
}
});
}
}).start();
}
}
}

Tuesday, May 22, 2007

Debug Blackberry app inside Eclipse

Once you get your eclipse environment setup, it is pretty straight forward to debug your app, thanks to Blackberry JDE, 4.1 and higher comes with JDWP implementation.

Let's first start JDWP, from Start --> All Programs --> Research In Motion --> Blackberry JDE 4.?.? --> JDWP. In this interface, the first main tab "Simulator" configures the simulator to lanch when debugger connects and the other behaviors. Please make sure that in the "General" tab "Launch simulator when debugger connects" is checked. In the second main tab "Communications", you can change the port JDWP listens to. This is the port we will connect to from our eclipse debugger.

With JDWP running, we can go back eclipse. Before we get started, we should increase the debugger's timeout threshold. Start elcipse, go to Window --> Preferences --> Java --> Debug, at the bottom of the dialog, increase the "Debugger timeout" and "Launch timeout" to 10 times longer. :) It is much needed unless you have a monster computer with multiple cores and multiple gigs of memory.

To config the debugger, go to Run --> Debug... In the dialog, select "Remote Java Application" from left hand list, then click on the "New" button; now at the right hand pane, give it a meaningful name, check the remote host and port matches JDWP's, then go to the third tab "Common", check "Debug" option in "Display in Favorites menu" so you don't have to open this dialog next time. Click "Debug" button if you are ready, otherwise click "Close" button to save the configuration.

Now the fun part begins. Edit code, run the ant task to deploy, set break point, click on the debug icon, and repeat this cycle.

Monday, May 21, 2007

Eclipse setup for blackberry development

These are proven-to-work steps to setup your eclipse environment for developing Blackberry applications. I hope this post will make somebody's entry into the RIM development easier.

To get started, do the following if you haven't done so:

  1. Download and install Eclipse
  2. Download and install BlackBerry JDE
  3. Download and install Apache ant
  4. Download RAPC ant task jar file
Now let's setup our eclipse environment.
  1. Start your eclipse, switch to a brand-new workspace, for example: c:\RIM\workspace
  2. go to Window --> Preferences --> Java --> Installed JREs, click on "Add" button.
  3. In the dialog, leave the default "Standard VM" option for JRE type;
  4. Type in a "JRE name" as you like, such as 'RIM JRE';
  5. In "JRE Home Directory", navigate to your installed JDK home, such as 'C:\Program Files\Java\jdk1.6.0';
  6. Leave "Default VM Arguments" blank;
  7. Now select all the jar files in "JRE System Libraries", then click "Remove" button to remove all of them; Click "Add External JARs", navigate to you Blackberry JDE installation folder, select lib/net_rim_api.jar, such as 'C:\Program Files\Research In Motion\BlackBerry JDE 4.2.1\lib\net_rim_api.jar'.
  8. Click "OK" button to add the new JRE.
  9. Check the checkbox of your newly added JRE to make it the default (Optional: select this JRE, click on "Edit" button to see if the system libraries are still like you set. It happened to me a couple times that eclipse added the jars in JRE home back into the list.)
With the eclipse setup, we are ready to create our first project:
  1. Goto File --> New --> Project, select "Java Project", enter Project Name "HelloWorld", Make sure in the JRE group the "RIM JRE" is selected. In the "Project Layout" group, I prefer to have src and class output into separate folders. Click "Finish" button.
  2. Right click the project, select New --> Folder, create a folder named "lib"
  3. Right click the project, select New --> Folder, create a folder named "resources"
  4. Right click "lib" folder, select "import"; in the dialog, select "general" --> "file system", import the anttask-rapc-1.?.jar you downloaded. Right click the jar file and select "Build Path" --> "Add to Build Path".
  5. Follow the same step to import an icon file in GIF format into "resources" folder. (other image formats work too, we use GIF for demo).
  6. Create a package named "com.mycompany.sample"
  7. Create a class named "HelloWorld.java" in this package and paste these code:
    package com.mycompany.sample;

    import net.rim.device.api.ui.UiApplication;
    import net.rim.device.api.ui.component.LabelField;
    import net.rim.device.api.ui.container.MainScreen;

    public final class HelloWorld extends UiApplication {

    public HelloWorld(){
    super();
    MainScreen screen = new MainScreen();
    screen.add(new LabelField("Hello world!"));
    pushScreen(screen);
    }
    public static void main(String[] args) {
    new HelloWorld().enterEventDispatcher();
    }
    }
  8. Now right click on the project name and create a new file named "build.xml", copy and paste the following code and edit the JRE and RIM JDK pathes accordingly, also search and replace the simulator batch file "8800.bat" to one that exists in your JDE (this ant build script is modified based on a post in Blackberry Java Forum.)

    <?xml version="1.0" encoding="UTF-8"?>

    <project name="HelloWorld" default="buildRIM" basedir=".">

    <taskdef name="rim" classname="com.etaras.anttask.rapc.RAPC" classpath="lib/anttask-rapc-1.8.jar" />

    <property name="jdehome" value="C:\Program Files\Research In Motion\BlackBerry JDE 4.2.1" />
    <property name="javahome" value="C:\Program Files\Java\jdk1.5.0_11"></property>
    <property name="simulator" value="${jdehome}\simulator" />
    <property name="bin" value="${jdehome}\bin" />

    <target name="debug" depends="buildRIM">
    <copy todir="${simulator}" overwrite="true">
    <fileset dir=".">
    <include name="*.cod" />
    <include name="*.debug" />
    <include name="*.csl" />
    <include name="*.cso" />
    </fileset>
    </copy>
    <exec executable="cmd.exe" dir="${bin}" spawn="true">
    <arg value="/c" />
    <arg value="jdwp.bat" />
    </exec>
    </target>

    <target name="simulate" depends="deploy">
    <exec executable="cmd.exe" dir="${simulator}" spawn="true">
    <arg value="/c" />
    <arg value="8800.bat" />
    </exec>
    </target>

    <target name="deploy" depends="buildRIM">
    <copy todir="${simulator}" overwrite="true">
    <fileset dir=".">
    <include name="*.cod" />
    <include name="*.debug" />
    <include name="*.csl" />
    <include name="*.cso" />
    </fileset>
    </copy>
    </target>

    <target name="buildRIM" description="Composes RIM">
    <rim jdehome="${jdehome}" javahome="${javahome}">
    <workspace src="helloworld.jdw" build="true" update="true">
    <cldc src="helloworld.jdp"
    title="HelloWorld"
    vendor="my company"
    version="0.1"
    description="HelloWorld"
    arguments=""
    systemmodule="false"
    runonstartup="false"
    startuptier="7"
    ribbonposition="0"
    output="helloworld"
    options="-quiet"
    update="true">
    <files dir=".">
    <include name="**/*.java" />
    <include name="resources/**/*.*" />
    </files>
    <icons dir=".">
    <include name="resources/**/*.png" />
    <include name="resources/**/*.gif" />
    </icons>
    </cldc>
    </workspace>
    </rim>
    </target>

    </project>

  9. Open a DOS window, change to the directory where you have your build.xml file, type "ant simulate", this task will build the project, deploy it and start the simulator.
  10. Look for the logo you picked for your HelloWorld app and open it, you should see a blank screen displaying "Hello World!". How exciting!
I will write down my experience of debugging applications inside eclipse in the next couple of days.

Thursday, May 03, 2007

Downgrade default JRE on windows XP

When installing Blackberry signature keys yesterday, I need to downgrade my default JRE on windows XP from 1.6 to 1.5. (Java is so good at maintaining backward compatibility, I seriously want to figure out what made the installation process not working in Java1.6. If you have a clue, please comment. Thanks.)

The complexity of this process caught me off guard. As a linux user, I instinctively went to My Computer --> Properties --> Advanced --> Environment Variables, and set the pathes. It doesn't work this way though. (Gentoo users, enjoy your java-config util and laught at me)

After some digging, here are the steps worked for me.

  1. Copy java.exe, java2.exe, javaws.exe from C:\Program Files\Java\jdk1.5.0_??\bin to C:\WINDOWS\system32\ to overwrite existing 1.6 version files.
  2. Open registry editor, goto Start --> Run, type in "regedit" and enter.
  3. Do a search for "JavaSoft", you should find something under HKEY_LOCAL_MACHINE -->SOFTWARE --> JavaSoft --> Java Runtime Environment, modify "CurrentVersion" key to "1.5" or the version you want.
  4. Update the correspondent environment variables.

Install RIM Blackberry signature keys and sign .cod file

Waited one week after placing the signature key order with RIM, we finally lost our patience and contacted them. And shortly after that, we received our keys. :)

Three ".csi" files were emailed to us. Installation is straight forward unless you have incompatible Java version. Downloading files onto hard drive, double click on one, you should see a dialog popping up saying "cannot find private key pair file, blah blah" and a "Yes" button at the end to create one. Click on the "Yes" button, if nothing happens you probably have JDK1.6 running and need to downgrade to JDK1.5. Otherwise another dialog will pop up and ask for the registration pin (the 10 digit number you entered when ordering the key) and select a password. Follow the steps to get your first key registered with RIM. Then do the same for the other two. You are done.

Signing your .cod file is straight. Double click on the .cod file, the Signature Tool window with a table listing all the signatures that you need and need not to request for your cod file will pop up. The signatures you need to request depends on the APIs you used in your cod file. Select the rows with category "required" and status "not signed", click the "Request" button, the Signature Tool will talk to RIM server to get the signature needed. Voila, you just got your application signed.