The BlackBerry Developer

Thursday, September 28, 2006

Why must the device be restarted after an application update? Does this indicate problems in the future?

After experimenting quite a bit, and posting a few questions, Mark Sohm from RIM (BlackBerry Developer Journal) has filled us in on the conditions that an application update forces a restart:


1. The application is running or the library is in use.
2. The application has any open resources (ie: a library could be holding onto something).
3. The application has an active listener registered with the system.
4. The application has added menu items to any BlackBerry applications.
5. It is an auto start application.
6. The application is listening for incoming IO connections (this would also fall under the "application is running" reason).
7. The application makes use of persistent storage and/or backup/restore features.


This can be a huge productivity issue, as some more loaded down devices require as much as 15 minutes (no kidding) to restart.

But a larger issue is looming.

This must mean that there is only one classloader in the RIM JVM. I can understand why the design decision was made (device capacity), specifically at the time it was first rolled out, but is this the way it will continue? Are there plans to revisit the classloader issue?

It indicates problems ahead if they aren't addressed.

As the devices become more powerful, applications will become more complex. This is happening today. With that natural progression, developers will move away from monolithic single codebases for applications towards composite applications, with commonly reused libraries. If any of you have attempted this, you will recall the class 'multiply defined' issue. Since there is no classloader isolation (such as in J2EE web applications), this causes a slew of issues.

For example, it is not far fetched to assume that developers will want to use a BlackBerry version of log4j. We certainly have ported it for use in our core libraries. In hopes that it will someday be well supported on the platform, we have left it in the org.apache.log4j packaging so we can essentially move to a community supported library when one is available (and we can contribute to). That is another discussion.

What if *any* other developer in the world has the same idea, or the community library is readily available and reusable? *Any* user in the world that happens to install applications from different developers will render one application unusable.

RIM's current answer to this would be to deploy the log4j as a 'library' on the device. Good idea, but what if Vendor A uses log4j 1.0 and Vendor B uses an incompatible version 1.2? The application installed last will win. Regardless, it means one application will NOT function.

Our company (Metova) has a lineage in J2EE, so entering mobile development, we naturally began developing reusable libraries for applications. We had no issues on the Windows Mobile environment (eRCP using the J9 JVM). In shifting our focus to BlackBerry, we were stunned that we can't reuse our core library on the same device unless we go through great pains to keep *every* application we have *ever* developed compatible with a readily available update for *every* user, *ever*.

I hope I have stressed *every*, *ever*, *world* enough in that last paragraph. This is NOT reasonable.

Developers know, cutting a release is more than just 'getting it to compile'. Testing is necessary for all releases. If you make a change to one of your core classes, are you prepared to put every application you have *ever* built into a testing/release process?

It is clear that this is a huge issue in the BlackBerry platform, as innocuous as it seems on the surface. The question is what will RIM do about it? Maybe they are already working on it?

As much as I hate to say it, until such time RIM addresses the issue, you will not be able to reliably, confidently reuse *any* community project with confidence that it will work reliably.

If someone from RIM could fill us in with a roadmap, it would make us much more comfortable. We would also be glad to meet with RIM to discuss how the problems are impacting us today and give our input on potential solutions.

- Kevin Ross

Kevin Ross is president of Metova LLC. If you have projects needing Blackberry Application Development, you may contact the author at Kevin.Ross@Metova.com, or make a general inquiry at info@Metova.com

Tuesday, August 22, 2006

BlackBerry Device Debugging with a new simulator bundle and the JDWP

This entire effort has been an exercise in patience, but there is hope!

Let me start off by saying that we don't use RIM's canned environment, so it isn't necessarily RIM's fault. Tools such as eclipse and comprehensive build tools such as maven 2.x integrated into our continuous integration process are far more helpful than the JDE to ignore. That's a whole other post to come, so let's get back on track.

I finally found a solution to integrating a new simulator bundle into the environment while utilizing the JDWP. None of RIM's instructions or tech notes worked. After some experimentation, I found a way that makes this whole thing much easier if you are just using the JDWP. This deviates entirely from RIM's instructions, which are cumbersome, and ineffective at best.

Here are new instructions (as complete as I am aware). The advantages of this approach are that you can have many versions of the simulators and switch usage with ease, without modifying the JDE installation at all (suggested by RIM's technote).


  1. Install the new simulators in their own directory structure (not under the existing JDE). i.e. C:\tools\rim\simulators\4.1.0.194\
  2. Open the JDWP, and create a new profile name. i.e. 8700 194 Where the model is the 8700 and the build is 194.
  3. Goto the advanced tab, then search and replace the copied profile model #, replacing with the target model for the 'Command Line'. i.e. 7100g with 8700c
  4. In the 'Command Line' box, replace the current location of the fledge.exe with your new location. Here is an example of my total command line:
    C:\tools\rim\simulators\4.1.0.194\fledge.exe /app-param=JvmAlxConfigFile:8700c.xml /app=Jvm.dll /pin=0x2100000A /data-port=0x4d44 /data-port=0x4d4e /app-param=DisableRegistration /session=8700c_194 /handheld=8700c
  5. Change the 'Working Directory' to point to your new simulator bundle dir. i.e. C:\tools\rim\simulators\4.1.0.194\
  6. Move all the files from C:\tools\rim\simulators\4.1.0.194\Debug to C:\tools\rim\simulators\4.1.0.194\
  7. Restart the JDWP.

You can now debug an 8700 for build 194 without altering your original installation at all.

- Kevin Ross

Kevin Ross is president of Metova LLC. If you have projects needing Blackberry Application Development, you may contact the author at Kevin.Ross@Metova.com, or make a general inquiry at info@Metova.com

Friday, July 14, 2006

Launch an external application

I'll start off by saying this is not intuitive. It is especially difficult if the external application cannot be installed on the simulator (Thank you Yahoo Instant Messenger for Blackberry). I used the logic: 1.) show the app if it is already running, 2.) launch the app if it is not running, and 3.) show the download page if it isn't installed. You will need 4 things:

1. The app name.
The text it shows on the bottom of the ribbon when you select the icon.

2. The module name.
Go to Options -> Advanced -> Applications, select the app and select view properties. There may be more than one module in which case you'll have to figure out which one is the main app.

3. The application arguments.
I found this by debugging and examining the currently running Application Descriptors
4. The download URL.

Once you have these I used this code to check if the application is running and bring it to the front if it is:

ApplicationManager manager = ApplicationManager.getApplicationManager();

//Check to see if application is running.
ApplicationDescriptor descriptors[] = manager.getVisibleApplications();
//Retrieve the name of a running application.
for (int i = 0; i <>ApplicationDescriptor descriptor = descriptors[i];
if (descriptor.getName().equals( applicationName )) {
manager.requestForeground( manager.getProcessId( descriptor ) );

}
}

If it is not already running and you want to start it you need to get a handle on the module using this code:

int modHandle = CodeModuleManager.getModuleHandle( moduleName );

If that returns a number greater than 0 than you have a module handle id. That can be used to get an application descriptor which can be used to launch the application.
ApplicationDescriptor[] apDes = CodeModuleManager.getApplicationDescriptors( modHandle ); ApplicationDescriptor descriptor = apDes[0]; ApplicationManager.getApplicationManager().runApplication( descriptor );

If you want to add custom arguments, you will need to make your own descriptor. Since an ApplicationDescriptor object can only be created from an already existing descriptor, this code will do the trick:

ApplicationDescriptor newDescriptor = new ApplicationDescriptor(descriptor, descriptor.getName(), args);

If that doesn't work then you can launch the browser and direct them to the download page.

Tuesday, June 27, 2006

Multiple Applications in one JAD

I was trying to deploy multiple applications or multiple COD files OTA with one JAD so that a user doesn't have to download each dependent project or application independently. I finally found the answer buried in a PDF that was linked to from the BlackBerry forum. You have to manually edit the jad file using the generated jad files from the jde and change your RIM-COD-URL and RIM-COD-Size properties to look like this:

RIM-COD-URL-1: mySystemProject.cod
RIM-COD-Size-1: 9972
RIM-COD-URL-2: myApplicationProject.cod
RIM-COD-Size-2: 8108

Saturday, June 17, 2006

Reset and clean the blackberry simulator

Are you sick of having a million icons on your BlackBerry simulator for every HelloWorld and demo project you have every tested? Try this to remove old programs from the simulator and start with a clean ribbon. From the command line browser to your rim jde directory, switch to the simulator sub directory and run clean.bat. This program takes longer than you would expect (about 30 seconds or so on my 3 ghz machine).

Thursday, June 15, 2006

Just the numbers


In my latest app I needed to add something to a menu that allowed a contact's phone numbers to be selected. It sounds easy enough but the whole PIM concept is foreign to me. Here is some of my code so that you can easily do this without wasting time. First create your menu item extending the net.rim.blackberry.api.menuitem.ApplicationMenuItem. Then implement your run method:


public Object run(Object context) {

...Code Here...
}

Next determine what the context is:


if (context == null) {

//Handle Null Context. This occurs in the
//Phone Menu if a call log is not selected.


}
else if (context instanceof BlackBerryContact) {

//Handle BlackBerryContect. This context is from the
//address book menu


..Code Here..
}
else if (context instanceof PhoneCallLog) {

//Handle PhoneCallLog. This context is
//from the Phone menu if a previous call is selected.


PhoneCallLog callLog = (PhoneCallLog) context;

String dialedPhoneNumber = callLog.getParticipant().getNumber();

..Do something with number..
}


The mildly confusing part is iterating over the phone numbers in a BlackBerry Contact. I did not find the APIs to be much help. The PIM class I am using is net.rim.blackberry.api.pdap.BlackBerryContact. I only mention this because there is also a class in the net.rim.blackberry.api.pim package with the same name. Here is the code:


BlackBerryContact blackBerryContact = (BlackBerryContact) context;

//Get the PIMList. It is useful for getting the labels for
//Each phone field

PIMList pimList = blackBerryContact.getPIMList();

if (blackBerryContact != null) {
//How many phone numbers does this contact have?
int phoneCount = blackBerryContact.countValues(Contact.TEL);

//Setup variables to hold the numbers and their labels.
String[] phoneNumbers = new String[phoneCount];
String[] labels = new String[phoneCount];

for (int i = 0; i > phoneCount; i++) {
//Fetch the phone number

String phoneNumber = blackBerryContact.getString(Contact.TEL, i);

//Determine the label for that number.
String label = pimList.getAttributeLabel(blackBerryContact.getAttributes(Contact.TEL, i));

//Add the number and label to the array.
phoneNumbers[i] = phoneNumber;
labels[i] = label + ":" + phoneNumber;
}

if (phoneCount == 0) {
..Handle the case when there is no number..
}
else if (phoneCount == 1) {
..Handle the number for
phoneNumbers[0]..
}
else {
//Create a dialog to ask the user which number they
//would like to use
int choice = Dialog.ask("Which Number?", labels, 0);

if (choice > -1 && choice < style="font-style: italic;">.. Handle the number for phoneNumbers[choice]..

}
else {
..Handle the case when the user doesn't pick a number..

}

}


So that is how you get the phone numbers from a blackBerry contact using J2ME. The other thing I had to look into was getting the actual name from the record. A getName() method would have been great but instead I had to use:


String firstName = c.getStringArray(Contact.NAME, 0)[Contact.NAME_GIVEN];
String lasttName = c.getStringArray(Contact.NAME, 0)[Contact.NAME_FAMILY];

Monday, June 12, 2006

OTA Deployment

This weekend I had to learn how to deploy a BlackBerry J2ME application OTA without using a BES server. It sounded easy enough. I had a COD file with my compiled code and a JAD file with the description of my application. I copied the two files out to my Apache web server. I then sent myself an email from Gmail with the link to my BlackBerry (why type when you don't have to?).

When I tried to follow the hyperlink, I received a 502 error. I could hit it fine from my machine but the BlackBerry device could not hit it. I then tried typing the URL into the BlackBerry browser. It connected and displayed the text contents of the JAD file on the screen. This was not the behavior I wanted or expected. I was hoping that the BlackBerry would just install the Java application just as it would Google Maps or any other application I had downloaded from the Web. Time to try a new approach.

I then started to research the BlackBerry Application Web Loader. I downloaded the app and read the BlackBerry Application Web Loader Developer Guide. My executive summary: this is an ActiveX control used with JavaScript for downloading BlackBerry applications and installing them from your desktop using USB synchronization. This application is not helpful for installing applications directly to your BlackBerry.

Now frustrated I decided to compare something I knew worked to my setup. When I used ieHTTPHeaders I found that the MIME Type of the JAD file should be text/vnd.sun.j2me.app-descriptor. Once I changed that and restarted my Apache service, the app downloaded and installed just fine!

The e-mail link problem:
The link I sent myself via email still wasn’t working. I realized that I started taking Gmail for granted. When I sent the URL in the email, it auto-magically created a hyperlink. When I created the link manually by creating an HTML email with an anchor tag and an href attribute, the link worked just fine.

How do I install an instant messenger?

I have recently started developing BlackBerry applications in J2ME and found that all of the BlackBerry development forums are full of people asking how to install an instant messenger on their BlackBerry. This Blog is not for people who want to install an instant messenger on their BlackBerry. This Blog is for all the problems I run into. When I find a solution, I will post it here so check back often.