Archive for the ‘Blackberry’ Category

Publish Early, Fix Later

RIM has taken a lot of flak for what some call bringing the PlayBook to the market too early. However over on Slashdot there is an article extolling the virtues of a Stanford class who have become successful doing just that. But then the IT press has never been know to be even-handed or fair.

 

Two Weeks with the BlackBerry PlayBook

I picked up a 16GB PlayBook on Tuesday April 19th when they went on sale. I was travelling on business at the time so I was eager to add the PlayBooks capability to my toolkit while on the road. The first thing I noticed was that to set the PlayBook up out of the box all you need is a power outlet (to charge the battery) and a Wi-Fi connection. During set up a large update is downloaded and installed, and you are walked through setting up a BlackBerry ID (if you don’t already have one). Your BlackBerry ID identifies you to AppWorld, and the VideoChat application (more on this later).

Personally, I don’t think there is much to be gained in comparing the PlayBook to the iPad, but since that seems to be the current fad, here are the major differences I see between the two. I only have access to a first generation Wi-Fi only iPad, so that is the basis of my comparison. You will have to decide for yourself which device wins (if any) for each item:

  • Size. The PlayBook has a 7.1 inch 16×9 touch screen, the iPad a 10 inch 9×4 touch screen.
  • Battery life. The PlayBook being smaller has less volume available for battery, and has a more powerful processor than the first generation iPad. So the iPad has a longer life, but the shorter life of the PlayBook hasn’t been an issue for me yet. Power has always been available before I needed it.
  • Software maturity. The iPad has a good head start in this department. So far I have received two major OS upgrades for the PlayBook. There are more applications in AppWorld each time I look, and I have found a number that are useful for work already.

Size

I like the smaller size of the PlayBook. It is easier to carry around than the iPad which is nearly as large as my Dell Mini 9 net-book. I rarely, though I will admit occasionally, wish for a larger screen; but for the most part I find I am much more likely to have the PlayBook with me when I need a tablet platform that I am the iPad. Feel free to disagree with me on this point, it is purely a matter of personal preference.

Software

This is where RIM has taken a real beating during the release of the PlayBook. Yes, the software is not ‘finished’ in that there are a number of core applications one would expect to find that aren’t there yet. Many reviewers have suggested that RIM should have delayed the introduction of the device until the software was ‘finished’. I am personally glad they didn’t because I can be productive with the device the way it is today. They may have gotten a better reception had they waited until the summer to put the PlayBook on sale, but then I (and others like me) would have been denied the use of the thing for that long. So, what can you do with it out of the box today? This is with OS version 1.0.3.1868 (the latest). And let’s leave the Bridge to one side for the moment.

Connectivity

The PlayBook supports modern dual band Wi-Fi, and Bluetooth. Using Wi-Fi you can, of course, connect through a hotspot to the Internet. Using Bluetooth you can tether to any phone supporting the Bluetooth Dial Up Networking (DUN) profile to provide wireless access to the Internet. Extra data charges may apply for using this, so check with your carrier.

Applications

The PlayBook comes with a Web-Kit derived web browser that provides full Flash support and multiple tabs. The browser renders very fast and has a fairly intelligent zoom feature that will zoom into one logical ‘region’ when you double tap. This is a much more usable zoom that what seems like a random zoom I’ve seen on other devices.

There is video chat, a picture viewing application, music and video players, calculator, clock, voice notes, Adobe reader, Slacker Radio, National Film Board, a Podcast aggregator and built in web short cuts to Bing, YouTube, Twitter, Gmail, Hotmail, Yahoo! Mail and AOL Mail. These all perform as one might expect. There is a music store application that is tied to Amazon, and a Kobo Book reader application that will download your Kobo library if you have one. There is also Need For Speed Undercover (a PlayBook specific version of Need For Speed), and Tetris. Oh, and at BlackBerry World, Angry Birds for PlayBook has been announced.

So far I have installed the CBC News, Globe News, TechCrunch and Netting (a network diagnostic tool) applications. For fun and relaxation I’ve also installed QickXKCD (for thrice weekly XKCD fix), Spider Solitaire, Scroodle (a blackboard app), Piano, DoodleBlast (a very intersesting game), Elemental (a periodic table of the elements), Ridgid Digital Level, Waterwheel (a waterwheel simulator based on a Lorenz attractor), Pixelated (mindless game), Air Hockey (yes that’s right), SilentNoise (a noise generator), Stars (a star catalog), Scrapbook (for playing with pictures), the native Facebook application, and PlottingGraphs (a function plotter).

All this love, along with the documents I need to have with me, fits in my coat pocket and still leaves me 10GB of storage left to fill up.

The real power and utility of the PlayBook comes from the Bridge and Documents To Go.

PlayBook Bridge

The Bridge is ingenous. What it does is allow you to use the PlayBook to access the data available to your BlackBerry handheld device on the PlayBook with a PlayBook specific user interface. It is not tethering, synchronization, or remote viewing. Non-BlackBerry Enterprise Server (BES) users get:

  • Messages: all your activated email accounts. Sadly not PIN-to-PIN messages or SMS (text) messages.
  • Contacts
  • Calendar
  • MemoPad
  • Tasks
  • BlackBerry Messenger
  • Bridge Files: access to (some) files on the BlackBerry SDCard. There are some limits based on file type.

BES Users also get the Bridge Browser which allows web browsing through the corporate servers, and corporate email in messages. For me the Bridge pays for the device. It is possable to compose and edit email on a BlackBerry handheld device, but if they get very large it can be quite difficult. The Bridge and PlayBook give a very nice intermediate size, but still portable way of composing complex email messages when a desktop or laptop machine is not available, or not an option.

Documents To Go

The PlayBook comes with three Documents To Go applications: Word To Go, Sheet To Go and Slideshow To Go. Word To Go allows you to create, edit and save MS Word format documents. Sheet To Go does the same for MS Excel spreadsheets. Slideshow To Go allows you to view and present MS Powerpoint slideshows using the microHDMI output to provide 1080P HD output. Slideshow works in one of two modes: mirrored output where the output to the projector is a copy of the PlayBook screen; and presentation mode where the slides are shown on the projector and something else (presenter notes, or even an other application) is shown on the PlayBook screen.

File Sharing

One of the neatest features of the PlayBook is the ability to share its disk storage via the network as a Windows share. This means that you can connect to the PlayBook from any computer that can act as a Windows share client, and drag-and-drop files back and forth. This works even when the PlayBook is asleep.

Final Thoughts

So, is the PlayBook as bad as the press seem to think it is? For me, definitely not! It has features that have allowed me to be productive with it right out of the box. I have a BlackBerry Torch, so not having stand alone email, contacts, calendar, etc. is not a drawback. In fact with the Bridge giving access to that data on my Torch, those applications would have been redundant. I can see that would be an issue for someone who does not have a BlackBerry. So, shoul RIM have waited until until they had stand alone versions of those applications? Should they have made all their existing customers wait? I don’t think so, and I’m very happy they didn’t.

Updates

Native Email and PIM applications demonstrated at BlackBerry World, see here or at crackberry.

Andoid player demonstrated at BlackBerry World, crackberry.

…the majority of the business market uses Microsoft PowerPoint, not Apple Keynote. There is no PowerPoint app for the iPad. Until there is, the absolute gold standard for portable PowerPoint will be the Playbook. That’s a pretty important selling factor in business.

ReelPortal application released for PlayBook.

Using the BlackBerry Notifications Manager

Creative Commons Licence

This work is licenced under a Creative Commons Licence.

Quite often we want to be able to notify the user that some event has happened. It is nice to be able to allow the user to configure what form that notification takes depending on the profile in use (Normal, Silent, Vibrate, etc.). The procedure to do this is quite simple, although when I first tackled this problem the documentation was confusing. I like to have a state class that keeps the data used to trigger the notification. This can become important if you application has a complex notification system. In this example it isn’t really necessary, but here is my storage class Notify:

/*
 * Notify.java
 *
 * © Richard Buckley www.hrbuckley.net, 2011
 *
 * This work is licenced under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
 * To view a copy of this licence, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to
 * Creative Commons, 171 Second Street, Suite 300, San Francisco, California 94105, USA.
 */

package src.notify;

import net.rim.device.api.notification.NotificationsManager;
import net.rim.device.api.notification.NotificationsEngineListener;

// The Notify class is just a helper to keep track of the data needed to invoke and
// cancel the notification. Mainly they keep track of the _eventId so the notification
// can be canceled, if you want to implement that, it is not used here and this
// could be rolled into the main program if simplification is more important.

final class Notify
{
    long _sourceId;
    long _eventId;
    int _priority;
    int _triggerIndex;
    long _timeout;

    public Notify(long sourceid, long eventid, int priority, long timeout, int triggerIndex) {
        _sourceId = sourceid;
        _eventId = eventid;
        _priority = _priority;
        _triggerIndex = triggerIndex;
        _timeout = timeout;
    }

    // invoke the event
    public void fire() {
        // triggerImmediateEvent causes non-interactable events to fire, such as Tunes, Vibrations and LED flashing
        NotificationsManager.triggerImmediateEvent(_sourceId, 0, this, null);
    }

    // cancel the event
    public void cancel() {
        NotificationsManager.cancelImmediateEvent(_sourceId, 0, this, null);
    }

}

Somewhere in the initialization of your code you must register a UID, Name and level with the OS. This will cause the name you have chosen to appear in the profiles where the user can get creative. Then it is a simple matter of firing the appropriate notification at the right time.

/*
 * Notify.java
 *
 * © Richard Buckley www.hrbuckley.net, 2011
 *
 * This work is licenced under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
 * To view a copy of this licence, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to
 * Creative Commons, 171 Second Street, Suite 300, San Francisco, California 94105, USA.
 */

package src.notify;

import net.rim.device.api.notification.NotificationsConstants;
import net.rim.device.api.notification.NotificationsManager;

// A skeleton class that will fire notifications.
//
class MyNotifierClass {
    public static final long NOTIFY1 0x6deb32addca8d89aL; // src.notify.Notify1
    public static final long NOTIFY2 0xd8759a3149fe119L; // src.notify.Notify2

    private Notify        _notify1, _notify2;
    private long          _EVENT_ID;

    public MyNotifierClass() {
        _EVENT_ID = 0L;

        //New Notifications Sources - these will show up as editable configurations in the Profiles application
        NotificationsManager.registerSource( NOTIFY1, "Notify 1", NotificationsConstants.IMPORTANT );
        NotificationsManager.registerSource( NOTIFY2, "Notify 2", NotificationsConstants.IMPORTANT );
    }

    public void someMethod() {
        _notify1 = new Notify(NOTIFY1, ++_EVENT_ID, 500, -1, NotificationConstants.MANUAL_TRIGGER);
        _notify1.fire();
    }

    public void someOtherMethod() {
        _notify2 = new Notify(NOTIFY2, ++_EVENT_ID, 500, -1, NotificationConstants.MANUAL_TRIGGER);
        _notify2.fire();
    }
}

Blackberry Torch Sync Pod

I’ve picked up charging pods for the Bold 9000 and 9700 when I was carrying those models. Having a charging pod on the bedside table is very handy. Setting up the Alarm Clock application bedside mode the way you like it, and dropping the device in the charging pod is a vary nice way to make sure your BlackBerry behaves the way you want over night, and is ready to go in the morning. With the advent of faster processors and more always active applications, and living in the country is hard on a BlackBerry battery. Starting every day fully charged is an important step in getting the most out of the device.

I’ve been given a Torch 9800 to use, but the Sync (and charging) Pod has only just become available. It represents an evolutionary improvement over the pods available for previous devices. Because the Torch has accelerometers and adapts to orientation, the Pod is set to hold the device in landscape mode. This provides a much more stable base than the pods for the 9000 and 9700 did. The Pod for the 9800 also carries the full USB bus connection through to the device, so you can use the pod on your desktop to connect to a PC for synchronizing. I was concerned that this might make docking a finicky process, but the form of the cradle seems to guide the device onto the plug fairly well.

In the box you get the tiny little power to USB cube just like the one that came with your 9800, a USB cable (which I replaced with a short third party cable to keep the wire bundle under control), and the Pod.

BlackBerry Torch 9800 in Sync Pod

BlackBerry Torch 9800 in Sync Pod

Fun With Text Filters

Creative Commons Licence

This work is licenced under a Creative Commons Licence.

In the Blackberry API the TextFilter, and its subclasses (EmailAddressTextFilter, FilenameTextFilter, HexadecimalTextFilter, IPTextFilter, LowercaseTextFilter, NumericTextFilter, PhoneTextFilter, URLTextFilter, and UppercaseTextFilter) provide useful input filtering for Blackberry programmers. Sometimes we want to quickly combine the function of two existing text filters into one. I have a project where I want the user to be able to input groups of upercase letters and numbers separated by spaces. Here is the quick hack I came up with:

import net.rim.device.api.ui.text.TextFilter;
import net.rim.device.api.system.Characters;

    /**
     * A TextFilter class to filter for station identifiers
     */
    private static class StationFilter extends TextFilter {

        // Order of the supporting filters is important, NUMERIC will convert
        // letters to numbers if it gets them first.
        private static TextFilter[]      _tf = {
            TextFilter.get(TextFilter.NUMERIC),
            TextFilter.get(TextFilter.UPPERCASE)
        };

        // Convert using the first supporting filter that has a conversion
        public char convert( char character, int status) {
            char c = 0;

            for (int i = _tf.length - 1; i >= 0; i--) {
                c = _tf[i].convert(character, status);
                if (c != 0) {
                    return c;
                }
            }

            return 0;
        }

        // Validate a space for separator, then by supporting filter
        public boolean validate(char character) {
            if (character == Characters.SPACE) {
                return true;
            }

            for (int i = _tf.length - 1; i >= 0; i--) {
                boolean b = _tf[i].validate(character);
                if (b) {
                    return true;
                }
            }

            return false;
        }
    }

Getting Input from a Custom Dialog

Creative Commons Licence

This work is licenced under a Creative Commons Licence.

Quite often we want to be able to get some information from the user but don’t want to use the MainScreen interface. Instead we would rather use a Dialog. The built in Dialog API has some nice static functions that suspend the program execution until the user responds, then allows execution to continue. They handle all the tedious issues with the event thread for us. Wouldn’t it be nice to have a dialog that we could call to get some text, a phone number, or some other piece of information from the user? Well here is how you can do that:

/*
 * BasicTextDialog.java
 *
 * © Richard Buckley www.hrbuckley.net, 2010
 *
 * This work is licenced under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
 * To view a copy of this licence, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to
 * Creative Commons, 171 Second Street, Suite 300, San Francisco, California 94105, USA.
 */

package src.dialog;

import net.rim.device.api.ui.component.Dialog;
import net.rim.device.api.ui.component.DialogClosedListener;
import net.rim.device.api.ui.component.BasicEditField;
import net.rim.device.api.system.Bitmap;

//
//  Create a dialog with a BasicEditField to accept user input. This example sets the field style to
//  allow only uppercase input.
//
//
public class BasicTextDialog extends Dialog implements DialogClosedListener {
    private BasicEditField      _text;
    private int                 _choice;

    public BasicTextDialog()  {
        super(Dialog.D_OK_CANCEL, "Eenter Some Text.", Dialog.D_OK, Bitmap.getPredefinedBitmap(Bitmap.QUESTION), 0L);
        _text = new BasicEditField("Only Uppercase: ", null, BasicEditField.DEFAULT_MAXCHARS, BasicEditField.FILTER_UPPERCASE);
        add(_text);
        setDialogClosedListener(this);
    }

    //
    //   The dialogClosed listener is called when the user closes the dialog, we can get the selection made at this point.
    //
    public void dialogClosed(Dialog dialog, int choice) {
        _choice = choice;
    }

    //
    //   A static convenience function that takes care of creating the dialog, posting it as a modal window (this blocks
    //   our execution and gives the event thread back to the OS so the user can interact with our dialog).
    //
    public static String askForText() {
        BasicTextDialog nsd = new BasicTextDialog();
        nsd.doModal();

        //
        //    If the user selected OK return the content of the BasicEditField, otherwise return null
        //
        if (nsd._choice == Dialog.OK) {
            return nsd._text.getText();
        } else {
            return null;
        }
    }

    //
    //    This function move the focus to the BasicEditField when the dialog is attached to the UiEngine. If you don't
    //    do this the focus will go to the default button.
    //
    protected void onUiEngineAttached(boolean attached) {
        if (attached) {
            _text.setFocus();
        }
    }
}

Using the new dialog is very easy:

    String sometext = BasicEditDialog.askForText();

Blackberry UI, What’s on the Menu

Creative Commons Licence
This work is licenced under a Creative Commons Licence.

Often one of the first things we want to do is add a menu to our Screen. The MainScreen we learned of last time makes this quite easy but also flexible. First as always we need to import the new Classes we are going to use:

import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.MenuItem;
import net.rim.device.api.ui.ContextMenu;
import net.rim.device.api.ui.component.Menu;

To post a menu we over ride the base Class (MainScreen in this case) implementation of makeMenu(). Since, for the moment at least, we are only providing a single menu we can ignore instance.

First we find out which Field, if any, has focus. We can then get the contextMenu for that Field, if any, and include it in our menu. The context menu contains items like Copy and Paste or other actions that make sense in the context of the Field with focus.

In many programs and tutorials you will find line 47 written using the UiApplication Class:

        Field focus = UiApplication.getUiApplication().getActiveScreen().getLeafFieldWithFocus();

This is of course perfectly good coding, arguable better than what I’ve done here. The way I’ve coded it demonstrates that our main Class BasicGUI is a sub-Class of UiApplication so we can use it anyplace we would use UiApplication. This saves us from having to import the definition of UiApplication into the BasicGUIScreen file because the definition of BasicGUI is autmatically shared with all classes in the package src.lessonOn. So why is using UiApplication better? Well, if we decide we want to use BasicGUIScreen in an application with a different main Class that isn’t named BasicGUI, we will have a problem. Something to keep in mind.

With the potential context menu taken care of we can add our own MenuItem screen2 which we will define in a moment. Finally if we want to include the default menu items, Close and Switch Application we simply call the Super Class implementation of makeMenu(). If we leave that call out, then we can eliminate those options from the menu, if we so chose.

    protected void makeMenu(Menu menu, int instance) {

        Field focus = BasicGUI.getUiApplication().getActiveScreen().getLeafFieldWithFocus();
        if (focus != null) {
            ContextMenu context = focus.getContextMenu();
            if (!context.isEmpty()) {
                menu.add(context);
                menu.addSeparator();
            }
        }

        menu.add(screen2);

        super.makeMenu(menu, instance);
    }

One way to create a MenuItem is as an instance variable. This is no different than declaring and initializing a simple type, like an int, but a bit more complex because a MenuItem is a complex type. The three arguments to the MenuItem constructor are: the text to display in the menu; the ordinal, which is used to sort the MenuItems on the menu; and the priority which is used to dynamically select the MenuItem that is selected when the menu is first posted. When the MenuItem is selected, the run() method is executed on the Event Thread. So you must remember the priviledges and restrictions that go along with running on the Event Thread: no long processing, but you may alter the UI. In this case we create an instance of MainScreen, set the title and add a LabelField, and finally push the Screen onto the screen stack.

    private MenuItem screen2 = new MenuItem("Screen 2", 200, 200) {
        public void run() {
            MainScreen s2 = new MainScreen();
            s2.setTitle("Screen 2");
            s2.add(new LabelField("This is screen number 2"));
            BasicGUI.getUiApplication().pushScreen(s2);
        }
    };

And here is the new BasicGUIScreen.java source file:

/*
 * BasicGUIScreen.java
 *
 * © Richard Buckley www.hrbuckley.net, 2010
 *
 * This work is licenced under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
 * To view a copy of this licence, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to
 * Creative Commons, 171 Second Street, Suite 300, San Francisco, California 94105, USA.
 */

package src.lessonOne;

import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.MenuItem;
import net.rim.device.api.ui.ContextMenu;
import net.rim.device.api.ui.component.Menu;

//
//
//
public class BasicGUIScreen extends MainScreen {
    BasicGUIScreen() {
        setTitle("Hello World");
        add(new LabelField("Hello World"));
    }

    private MenuItem screen2 = new MenuItem("Screen 2", 200, 200) {
        public void run() {
            MainScreen s2 = new MainScreen();
            s2.setTitle("Screen 2");
            s2.add(new LabelField("This is screen number 2"));
            BasicGUI.getUiApplication().pushScreen(s2);
        }
    };

    //
    // Populate the screen menu
    // @param menu the menu to populate
    // @param instance the instance, allows different menus to be posted depending
    // on user interaction. It will be 0 if the menu is posted by pressing the BB
    // button, non-zero if it was posted by a trackball click.
    //
    protected void makeMenu(Menu menu, int instance) {

        Field focus = BasicGUI.getUiApplication().getActiveScreen().getLeafFieldWithFocus();
        if (focus != null) {
            ContextMenu context = focus.getContextMenu();
            if (!context.isEmpty()) {
                menu.add(context);
                menu.addSeparator();
            }
        }

        menu.add(screen2);

        super.makeMenu(menu, instance);
    }
}

We could have created this screen in a number of ways. The most flexible would have been to create a new sub-Class of MainScreen. We could also reuse BasicGUIScreen. Similarly the MenuItem could be created when makeMenu is run if and when it is needed rather that when BasicGUIScreen is instantiated as screen2 is:

        menu.add(new MenuItem("Screen 3", 200, 300) {
            public void run() {
                BasicGUIScreen bgs = new BasicGUIScreen();
                bgs.setTitle("Screen 3");
                BasicGUI.getUiApplication().pushScreen(bgs);
            }
        });

Java allows all kinds of shortcuts like this. Sometimes they are very handy and improve readability, sometimes not.

As always, the Blackberry JDE project files are available from the Lesson1 Git repository. Enjoy.

Blackberry UI: Events, Screens and Threads

Creative Commons Licence
This work is licenced under a Creative Commons Licence.

There are several things that you must always bear in mind when writting BlackBerry applications: the device is event driven on a single Java Virtual Machine (JVM); the user interface is implemented using screens which are held on a screen stack; and the OS is multi-threaded, some threads have special requirements and capabilities which must be respected.

Driven by Events

Event driven software is not a new concept, especially where graphical user interfaces (GUIs) are concerned. When the user interacts with part of the interface, that interaction is presented to the appropriate software as an event. As programmers our job becomes writing little code fragments that are all related but each one takes care of some element of the user interface. This is a very powerful concept and has allowed much of what we take for granted on our digital devices to be developed. It does mean that we are no longer able to say ahead of time which order our bits of code will be executed in. That power is given over to the user.

On the BlackBerry platform, events are delivered to Listeners. A Listener is simply an object that implements a particular interface, a method or group of methods that provide the object with a specified behaviour. We don’t need to concern ourselves too much with the details of how the event delivery mechanism works, but we do need to keep certain things in mind. The operating system collects the very low level events: key presses and releases, track ball movement, data input/output etc. and delivers them to applications by placing the events in an event queue. When an application gets a turn to execute, a waiting event is taken off the queue and delivered to any listeners registered for that event. The listener may be provided by the OS or the API and it may combine many low level events into one or more higher level events. For example track ball movement and clicks may be combined into a drop down list item selection. These higher level events are then dilivered to their listeners in turn. All this event delivery is done by the Event Thread, and there is only one Event Thread. So if your program receives an event and starts a process that will take a long time (like computing Pi to thousands of decimal places) or that may block waiting for something external to the device (like downloading a web page) no other applications will receive events while your greedy program hogs the Event Thread. This will cause the device to appear to freeze. If this goes on too long, the event queue will fill up and the OS will terminate your program. So, keep your listeners short and quick. If you need to do long computation or IO start a new thread to handle those tasks.

The Event Thread, or more precicely the thread that is holding the user interface event lock is the only thread that can manipulate user interface elements. There are ways of arranging for your code to be executed on the Event Thread, or to grab the event lock, so that non-Event Threads can still have their results displayed to the user. We will look at those a little later.

Stack those Screens

Within a UiApplication Screens are held on a stack. The topmost screen is displayed to the user and receives events directed to the application. To display a Screen an Object that is a sub-class of net.rim.device.api.ui.Screen is created and pushed onto the Screen stack with pushScreen() (or one of its variants). To un-display a Screen, it can be popped off the stack manually with popScreen(), or it can be closed by calling the Screen’s close() method. This is what happens to some Screen implementations (like the MainScreen) when the user presses the escape key. When the last Screen is popped off the Screen stack, the application will exit, though it is possable to change this behaviour to put the application in the background.

Unraveling Threads

We have alread discussed threads in enough detail for the moment when we discussed Events. So lets get on with programming.

Adding a MainScreen

There are many ways to add a new Class or Object to an existing project. We will be talking about each when we need to use it, for now let’s use the traditional way of putting each Class in its own file so we create a BasicGUIScreen.java file and start typing. We will put it in the same package as our main object:

package src.lessonOne;

We also need to import the classes we will be using:

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

And we can provide the universal program greeting:

public class BasicGUIScreen extends MainScreen {
    BasicGUIScreen() {
        setTitle("Hello World");
        add(new LabelField("Hello World"));
    }
}

To have our Screen displayed we simply modify the constructor of our main Class to create an instance of our Screen and push it onto the stack. We now have a program that does something we can see. Sitll not particularly useful, but it is a begining we can build on.

    BasicGUI() {
        pushScreen(new BasicGUIScreen());
    }

Here are the complete files, first BasicGUI.java:

/*
 * BasicGUI.java
 *
 * © Richard Buckley www.hrbuckley.net, 2010
 *
 * This work is licenced under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
 * To view a copy of this licence, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to
 * Creative Commons, 171 Second Street, Suite 300, San Francisco, California 94105, USA.
 */

package src.lessonOne;

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

/**
 *
 */
public class BasicGUI extends UiApplication {
    public static void main(String[] args) {
        BasicGUI basicGUI = new BasicGUI();
        basicGUI.enterEventDispatcher();
    }

    BasicGUI() {
        pushScreen(new BasicGUIScreen());
    }
}

And BasicGUIScreen.java:

/*
 * BasicGUIScreen.java
 *
 * © Richard Buckley www.hrbuckley.net, 2010
 *
 * This work is licenced under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
 * To view a copy of this licence, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to
 * Creative Commons, 171 Second Street, Suite 300, San Francisco, California 94105, USA.
 */

package src.lessonOne;

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

/**
 *
 */
public class BasicGUIScreen extends MainScreen {
    BasicGUIScreen() {
        setTitle("Hello World");
        add(new LabelField("Hello World"));
    }
}
BasicGUI running on the simulator

BasicGUI running on the simulator

Basic Blackberry UI Program

Creative Commons Licence
This work is licenced under a Creative Commons Licence.

The Blackberry JDE workspace for this program can be obtained using Git: git clone git://git.hrbuckley.net/BB/Lesson1/

Every Java source must be part of a package. Membership in a package has an impact on class scoping rules and permissions. Objects belonging to the same package will have different access rules applied with respect to each other than objects belonging to different packages. For this reason, a standard Blackberry device will not load modules with Classes declared in restricted packages. This prevents a malicious programmer from using the scoping and access rules of package membership to bypass Blackberry security. It is traditional that the file structure of a Java project reflect the package structure, but this is not enforced by RIM’s Java Development Environment (JDE). So the first decison we need to make is what Package we want out Class to belong to, and declare it in the source code:

package src.lessonOne;

Next we must import the declarations of all the classes we are going to use. Some classes seem to be automatically imported by the JDE, String for example, and need not be explicitly imported. It is probably a bad habit not to import these, but perhaps not my worst bad habit. A Blackberry program implementing a user interface must have at least one object that extends net.rim.device.api.ui.UiApplication so:

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

We can now declare our Class:

public class BasicGUI extends UiApplication {
}

Next we must tell the compiler how to start our program. The RIM compiler/linker will look for an object with a method called main declared public static void and taking a single String array as an argument. It will arrange for this method to be called when our program is launched. A minimal main method will instantiate our sub-class of UiApplication and call the inherited method enterEventDispatcher which will not normally return:

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

Add a simple constructor (which we will embelish later) and we have a complete, if not very useful Blackberry program:

/*
 * BasicGUI.java
 *
 * © Richard Buckley www.hrbuckley.net, 2010
 *
 * This work is licenced under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
 * To view a copy of this licence, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to
 * Creative Commons, 171 Second Street, Suite 300, San Francisco, California 94105, USA.
 */

package src.lessonOne;

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

/**
 *
 */
public class BasicGUI extends UiApplication {
    public static void main(String[] args) {
        BasicGUI basicGUI = new BasicGUI();
        basicGUI.enterEventDispatcher();
    }

    BasicGUI() {    }
}

The reason this program is not very useful is that, one of the things that enterEventDispatcher does, is monitor the number of Screens a UiApplication has pushed to the screen stack. We haven’t create any screens at all, so the program will exit directly. In my next post we will add a simple screen to our program.

Scripts for Building BlackBerry Programs Automatically

Creative Commons Licence
This work is licenced under a Creative Commons Licence.

These scripts are a work in progress. I’m still working on them so check back periodically and be aware that there may be bugs. Download the Git repository with git clone git://git.hrbuckley.net/BB/bin/. Or if you have already cloned the repositiory merge in any updates with git pull git://git.hrbuckley.net/BB/bin/

I have been using Git as my version control system of choice for nearly a year now. One of the benefits of using Git on Windows is that you get a Unix like environment for free. This gives rise to the ability to write Bash scripts to compile JDE projects automatically. We need to add some files and set up the environment. I’m using Windows 7 so in %USERPROFILE% I have created a bin directory and a .bashrc file:

# %USERPROFILE%\.bashrc
ifsave=$IFS
IFS=$(echo -en "\n\b")
export MYPROGRAMFILES_X86="/g/Program Files (x86)"
IFS=$ifsave

if [ -d ~/bin ]
then
  if [ -e ~/bin/jderc ]
  then
    . ~/bin/jderc
  else
    echo "No jderc"
  fi
  if [ -e ~/bin/javarc ]
  then
    . ~/bin/javarc
  else
    echo "No javarc"
  fi
fi

The jderc file:

#
# Iterate through all installed RIM JDEs adding a JDExxx and JDELIBxxx environtment variables with the
# path to the bin and lib directories for that JDE, and add the OS version to the JDEVERSIONS
# environment variable. Set the last (highest OS version) to JDEMAIN and JDELIBMAIN.
#
export RIMPROGFILES="${MYPROGRAMFILES_X86}/Research In Motion"

IFSAVE=$IFS
IFS=$(echo -en "\n\b")

JDEVERSIONS=""
for rim in ${RIMPROGFILES}/*
do
  b=$(basename $rim);
  case $b in
    BlackBerry*)
      v=$(echo $b | sed -e "s/BlackBerry JDE //i" | sed -e "s/\.//g")
      JDEVERSIONS="${JDEVERSIONS} ${v}"
      eval "export JDE${v}=\"${rim}/bin\""
      eval "export JDELIB${v}=\"${rim}/lib\""
      export JDEMAIN="${rim}/bin"
      export JDELIBMAIN="${rim}/lib"
      ;;
  esac
done
export JDEVERSIONS

IFS=$IFSAVE

The javarc file:

#
# Set up path variables for the JDK and JRE
#
export JAVAPROGFILES="${MYPROGRAMFILES_X86}/Java"

IFSAVE=$IFS
IFS=$(echo -en "\n\b")

JDKPATH=""
for jdk in ${JAVAPROGFILES}/jdk*
do
  if [ -d ${jdk}/bin ]
  then
    JDKPATH="${jdk}/bin"
  fi
done

for jre in ${JAVAPROGFILES}/jre*
do
  if [ -d ${jre}/bin ]
  then
    JREPATH="${jre}/bin"
  fi
done

export PATH="${JDKPATH}":"${JREPATH}":"${PATH}"

IFS=$IFSAVE

Now we can build a JDE project with the build script:

#!/bin/sh
#
# Build the specified JDE project using the latest JDE instaled, or as optionally specified.
#
if [ $# -lt 1 ]
then
  echo "Usage: build <project> [ $JDEVERSIONS ]"
  exit 1
fi

DOSPWD=$(pwd | tr / \\\\ | sed -e "s/^.\(.\)/\1:/")

#
# Get the files and libraries from the project file
#
MOD=$1
if [ -e ${MOD}.jdp ]
then
   JDP="${MOD}.jdp"
   files=$(awk 'BEGIN { copy = 0 } /^\[Files/ { copy = 1; next } /^]/ { copy = 0; } copy { print }' $JDP)
   libs=$(awk 'BEGIN { copy = 0 } /^\[DependsOn/ { copy = 1; next } /^]/ { copy = 0; } copy { print }' $JDP)
fi

FILES=""
LIBS=""
jde="JDEMAIN"
lib="JDELIBMAIN"
if [ "${files}EMPTY" != "EMPTY" ]
then
  for f in $files
  do
    FILES="${FILES}\"$f\" "
  done

  for l in $libs
  do
    LIBS="${LIBS}\"${l}.jar\" "
  done

  shift

  if [ $# -ge 1 ]
  then
    jde="JDE${1}"
    lib="JDELIB${1}"
    if [ ! -d "${!jde}" ]
    then
      jde="JDEMAIN"
      lib="JDELIBMAIN"
    fi
  fi

  #
  # If we can find the appropriate rapc compiler, build the program
  #
  if [ -e "${!jde}/rapc.exe" ]
  then
    "${!jde}/rapc.exe" -quiet -define=PREPROCESSOR "import=${LIBS}${!lib}/net_rim_api.jar" "codename=${MOD}" ${MOD}.rapc $FILES
  else
    echo "Could not locate JDE compiler"
    exit 2
  fi
fi

Visitors

Site Links

  • Blackberry Forums
  • Blackberry Support Forums
  • FreshMeat
  • Radio Electronics
  • SlashDot
  • Smiths Falls Weather
  • Stack Overflow
  • XKCD
  • Yahoo Groups

Blogroll

Meta