dcsimg

EventLogger: printf for BlackBerry

Using the EventLogger feature of the BlackBerry to record important events

Everyone’s first debugger

Do you remember your first program?

For many of us it was was a simple Basic language program that looked something like this:

10 print "your name"
20 goto 10

From that humble beginning, our programs became more sophisticated, thankfully.

While the novelty of printing your name to the screen quickly wore off, the need to “see” what your program is doing never goes away.

Today we have sophisticated tools for performing line by line debugging and we have the ability to peer into running virtual machines to evaluate expressions and even conditionally break when a particular situation occurs.

However, there is still something magical about a string painted to the screen, or written to a log file which says, “I am here.”

That simple line conveys much to a programmer — it says that our program has survived to this point and whatever error we are looking for is likely ahead, not before, this line of logging code.

Another important technique is to print out a run-time value, such as a sensor reading or a user-entered value.

This practice of writing out a log line is helpful, however not every platform has a simple means of gathering this kind of data from users in the field.

A desktop application can simply append lines to a text file and a help desk technician can request and review this file to sort out an application problem.

Mobile applications are not always so easy to trouble-shoot. This article introduces the EventLogger class for BlackBerry applications, a true life-saver for those hard-to-find problems that seem to creep into applications, particularly ones running on newer devices that may behave a bit differently from the device used during initial application testing.

The EventLogger

BlackBerry is one of those platforms where gathering run-time data from users can be a bit challenging.

BlackBerry applications are coded in the Java language. Depending on the version of the BlackBerry Operating System (and device) you are working with, your choices vary a bit in terms of how readily you can stream data to a “file”.

Luckily there is a mechanism in the core BlackBerry software development kit (SDK) which permits us to record data to a log and readily gain access to it from devices in the field. To accomplish this we employ the EventLogger class.

The EventLogger permits our application to write “events” to a persistent log which is kept on each BlackBerry device.

This log is viewable by the user right on their device. They can even filter and copy events to the clipboard for easy conveyance to the application vendor by simply “Pasting” the copied log entries into the body of an email.

Accessing the Event Log

The Event Log is made visible through one of two techniques.

The first technique can be done by the user at anytime. From the home screen of the device, simply “type” the following key sequence:

alt-l alt-g alt-l alt-g

Note that if you are testing this with the BlackBerry simulator and you use the keyboard on your PC, you will want the “control” key instead of the “alt” key on your keyboard.

This will pop-up the EventLog viewer as shown in the image below.

EventViewer
EventViewer

As you can see from the screenshot, the Event Log viewer application menu permits a few options including:

  • Copying the day’s events
  • Refreshing the log
  • Clearing the log
  • Options — filtering by application or by severity

The other way to launch the EventLog viewer is to call a particular api method, namely:

EventLogger.startEventLogViewer();

Let’s go ahead and add logging to a simple application.

Demo application code

The demo application has four user interface elements:

  • An EditField — to allow the user to type in a name.
  • A LabelField — to display output to the user. In this case, the application simply converts the entered string to upper-case.
  • A ButtonField — to initiate the text conversion.
  • A ButtonField — to programmatically launch the EventLog viewer application.

Demo Application in Action
Demo Application in Action

The application contains three source files:

  • logger.java — this is the main application file including the entry point function, main.
  • loggerscreen.java — this class implements the MainScreen interface and provides all of the application’s user interace code.
  • guid.java — this class simply defines a globally accessible constant value which is used in the logging methods. This was broken out to a distinct class to demonstrate how you might incorporate this code into a larger, more complex application.

In logger.java, we setup our logging capabilities by first registering our application with the EventLogger. We then make our first entry with a call to logEvent.

/*
 * logger.java
 */

package com.msi.lm;

import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.system.EventLogger;

class logger extends UiApplication
{
    // one and only instance of our application
    static logger theApp = null;
    loggerscreen ls;

    // constructor
    public logger()
    {
        EventLogger.logEvent(Guid.eventLogId,"in constructor".getBytes());
        ls = new loggerscreen();
        EventLogger.logEvent(Guid.eventLogId,"after screen constructor".getBytes());
        pushScreen(ls);
        EventLogger.logEvent(Guid.eventLogId,"after push screen".getBytes());
        requestForeground();
    }
    public static void main(String[] args) {

        // very first thing -- register the event log!!!
        EventLogger.register(Guid.eventLogId,"LMLogger",EventLogger.VIEWER_STRING);
        EventLogger.logEvent(Guid.eventLogId,"App Launch".getBytes());

        theApp = new logger();
        EventLogger.logEvent(Guid.eventLogId,"After Constructor".getBytes());
        if (theApp != null)
        {
            EventLogger.logEvent(Guid.eventLogId,"Class Created, enterDispatcher".getBytes());
            theApp.enterEventDispatcher();
        }
  }
}

Note that this code has a somewhat paranoid number of event logging statements. While it is not typically necessary to put these in during application start-up, there may be instances where an application requires tracking down every line of code in a critical method in order to find the source of a Null Pointer exception for example.

The process of editing, compiling, signing, distributing, uninstalling and re-installing an application can take a bit of time and project management — particularly if your client is distributing an application via a BlackBerry Enterprise Server (BES), where you may have to get a number of different people involved to simply perform one test.

A “best practice” is to load your code up with a number of logging statements in an effort to track down the problem with as few iterations of this process as possible. You may need to perform this cycle a number of times — each time narrowing down the problem as you go.

The code for implementing the application functionality is below. In addition to the relatively boring application code, note the call to invoke the Event Log viewer. In a real application, this feature would likely live in an “Options” interface, accessible outside of the main application interface.

/*
 * loggerscreen.java
 *
 */

package com.msi.lm;

import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.component.ButtonField;
import net.rim.device.api.ui.component.EditField;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.component.SeparatorField;
import net.rim.device.api.ui.FieldChangeListener;
import net.rim.device.api.system.EventLogger;

class loggerscreen extends MainScreen
{
    LabelField lblOutput;
    EditField txtInputBox;
    ButtonField btnGo;
    ButtonField btnShowLog;

    loggerscreen()
    {
        EventLogger.logEvent(Guid.eventLogId,"Setting up screen".getBytes());
        setTitle("Linux Mag:: EventLogger");

        txtInputBox = new EditField("Enter your name: ","",50,EditField.EDITABLE | EditField.NO_NEWLINE);
        btnGo = new ButtonField("Go!",ButtonField.CONSUME_CLICK);
        btnGo.setChangeListener ( new FieldChangeListener() {
            public void fieldChanged(Field f, int context)
            {
                EventLogger.logEvent(Guid.eventLogId,"Go Selected".getBytes());
                String value = txtInputBox.getText();
                if (value != null)
                {
                    lblOutput.setText(value.toUpperCase());
                }
                btnGo.setDirty(false);
            }
        });

        btnShowLog = new ButtonField("Show Log",ButtonField.CONSUME_CLICK);
        btnShowLog.setChangeListener ( new FieldChangeListener() {
            public void fieldChanged(Field f, int context)
            {
                EventLogger.startEventLogViewer();
                btnShowLog.setDirty(false);
            }
        });

        lblOutput = new LabelField("");

	// add elements to user interface screen
        add(txtInputBox);
        add(btnGo);
        add(lblOutput);
        add(new SeparatorField());
        add(btnShowLog);
        EventLogger.logEvent(Guid.eventLogId,"UI is now setup!".getBytes());
    }
}

And here is guid.java.

/*
 * guid.java
 */

package com.msi.lm;

class Guid {

    // eventLogId is the long generated with string "LMLogger"
    public static final long eventLogId = 0xd80d08d0154d42d5L;
}

Viewing the log

With the event log now populated with events from our application, let’s drill down through the noise and find what is useful to us.

We start by filtering the events down to just our events — remember, other applications are writing to this log also. And not just applications, but the BlackBerry system itself is logging data to the event log.

Filter out all other data
Filter out all other data

Once the list is filtered, we can see just our own events.

Just our events
Just our events

We can even drill down to see the details on a particular event.

Event details
Event details

Now that we have the list, we can extract those by copying them to the clipboard. We have the option of copying all events, or just the filtered events. We’ll pick the “filtered” events.

Copy our events
Copy our events

Now that we have the events, let’s email them to support.

Paste into an email
Paste into an email

That should do it for our basic EventLogger functionality. I hope this helps you improve your ability to support your BlackBerry applications — it has certainly helped me a time or two. Please don’t email me your logs, but if you do have questions, please post them to the comments section.

Fatal error: Call to undefined function aa_author_bios() in /opt/apache/dms/b2b/linux-mag.com/site/www/htdocs/wp-content/themes/linuxmag/single.php on line 62