Five Things that BlackBerry does better than iPhone

I’ll start with a confession – I’ve been using an iPhone instead of a BlackBerry for the past little while, because my company has been focused on developing some iPhone products. The iPhone is a phenomenal device, and certainly has to have RIM worried, but having used both devices now, there are definitely a lot of things that the BlackBerry does way better. I’ve picked 5 things that I really really miss about using a BlackBerry (and probably they’ll be the reasons that I go back to BlackBerry for day-to-day use soon). I think most of these are known to most people, but I’ve omitted a few things that are commonly thought of as BlackBerry’s advantages – I’ll explain why at the end of the article.

1. Push Email

Yes, iPhone does push email too, but BlackBerry does it better. You can sync an Exchange account with your iPhone and get push email, but only one. I’ve always got a minimum of 2 accounts I want to keep up to date with – currently 5 – but even with 2, I’d have to choose a preferred one (or consolidate everything through one account, which isn’t an option).

clouds
And sure you can get 3rd party solutions for iPhone that use the push notification functionality to tell you about new email – I’m using one called Mail Notifier – but it’s not the same thing. I get notified of a new email, which includes a snippet of the text, but I then have to go into the Mail app, select the account, wait for it to connect and download, and then click the email. With BlackBerry the email is already there, and I can even set the device to pop the email client up on new emails. No going through the list of accounts, remembering which one the email came from, speaking of which…

2. Multiple Email Accounts

Handled beautifully by BlackBerry. I can view the inbox for each account separately, but never do. BlackBerry lets me view all emails from all accounts in one place, and keeps track so that when I reply it comes from the right account.

There’s more! I can have separate signatures for each account (really really irritating missing feature on iPhone), and when I compose a new email to a contact, the BlackBerry usually guesses correctly which account I want to send it from – probably based on some analysis of past correspondence.

With iPhone I have to click on mail, click on the account, click on inbox. And then back out through those screens to check my next account. Just enough extra clicks to be annoying, and I can’t see all my emails from all accounts at the same time.

Email is part of BlackBerry’s DNA – it’s initial killer app was email, and the business and devices were built around that, and it shows.

3. The Keyboard

keyboards
While the iPhone’s virtual keyboard is a pretty phenomenal piece of engineering, and amazingly usable (more than I can say for BlackBerry’s attempt at the same thing – but that’s a post for another day), nothing on any mobile device has yet delivered the same instant easy usability that the physical BlackBerry keyboard has. Not much more to say than that, but I will add that I’ve noticed a change in my behavior with regards to email, and I think it’s largely because of the lack of keyboard on an iPhone:

The iPhone keyboard, even being slightly more difficult to use than BlackBerry’s real keyboard, has put enough of a barrier in place (at least in my head) that I reply to a lot less email, and so get a lot less done away from the desktop. Meaning my response time has gone down, and there’s always more email waiting for me to reply to when I do get to a desktop.

4. The notification light

Yes, this thing:

bbled

Amazingly simple, but I really miss it. I’m used to glancing down at my device to see if anything new had come in – or looking at it lying on a table. iPhone doesn’t have an LED indicator for new email, so I can’t do that. Again, email is part of the core DNA of BlackBerry, all the way down through the hardware, and this shows it.

5. Total integration – email, calendar, contacts, notes, tasks

This is probably a bunch of things, but I’ll put them all together here. BlackBerry just delivers a better experience when going between all the above applications. It syncs them more readily, makes it easier to link calendar entries to notes to tasks to contacts, etc. It’s difficult to quantify but the overall experience is just smoother – obviously this is based on years of development and user feedback from RIM. It’s core to the BlackBerry experience and they still do it better than iPhone (even with it’s super slick UI)

Runners Up

BlackBerry Messenger

Really great, and hugely popular, but I honestly never used it enough for it to make my personal top 5

Camera

The camera on my Curve 8900 blew away the iPhone (still does) but there are better mobile cameras out there than the best that BlackBerry or iPhone offer

Things I specifically left out

Security

Yes, BlackBerry email (within a corporate environment) is very very secure. But for my use, I don’t really care. Most of my email is GMail based anyway, and so I’m always sending stuff to other people via plain unencrypted protocols. If I really care about security I send an encrypted attachment or use something other than email to do it.

Battery Life

I’ve gotten so used to plugging my devices in every night that this hasn’t been an issue with any mobile device (even though I use my iPhone for playing music as well as email/phone/etc). As long as the battery lasts the day, I’m happy.

Expandable memory

True, BlackBerry does support micro SD cards, but the support is hobbled by two things: 1. You can’t use the SD cards for app storage, and 2. for most devices at least, you have to remove the battery to remove the SD card – no hot-swapping

The Golden Rule

The golden rule of the single-threaded API model is:

Only the event thread can modify the user interface.

In fact, it’s a little more subtle – only a thread holding the user interface event lock can modify the user interface – more on that later, for now just know that almost always the event thread is the one holding that event lock.

This means, if you’re doing anything that will directly result in immediate changes to the UI – pushing (or removing) screens onto the display stack, modifying the visible state of your UI components, painting – you have to do it in the event thread.

Simple, right? Yes, in theory. In practice, it’s not much more difficult – just bear in mind a couple of things.

As I said above the thread that enters your main method is your application’s event thread. This, combined with the golden rule means that in the initial call to your main method, you can do all the UI work you want. Often you create your app’s initial screen and push it onto the stack (using UiApplication.pushScreen) there – or at least in a method that you call directly from there. However, at some point you want to call enterEventDispatcher or you’ll never get user input. How do you modify the UI after that?

Modifying the UI

Now, the golden rule doesn’t mean that you can’t call any methods on any UI component from any other thread. Anything that gets information (EditField.getText for example) is fine. Also fine is setting information that may not result in immediate changes. But for most of the built-in UI components – like EditField, or LabelField, methods like setText will result in a change and so must be done while you have the event lock.

How do I know I’m on the event thread

Easy – just UiApplication.getUiApplication().isEventThread(swift runners) (or isEventDIspatchThread, which is a static method and does the same thing – both of those methods, by the way, actually reside in net.rim.device.api.system.Application, which is UiApplication’s super class).

You will sometimes end up on the event thread – menu items are executed on the event thread for example.

How can I modify my UI?

There are two ways:

1. Use the net.rim.device.api.system.Application methods invokeLater or invokeAndWait – both of which take a Runnable. Anything in that Runnable’s runmethod will be executed by the event thread at the next available opportunity. The first method is asynchronous (which means in this case that it returns immediately) the second is synchronous (so waits until your Runnable’s run method is finished before returning).

BlackBerry UI – A simple custom field

I’ve covered creating your own field Manager on this site already. As you might guess, another very common part of BlackBerry UI implementation is creating your own Field class (or extending one of the built-in classes). Fortunately, the basics are very easy, even easier than creating a Manager. I’ll run through a simple from-scratch Field to illustrate everything you’ll need to know.

The field I’ll be creating is a button – now, there’s a ButtonField already in the BlackBerry UI library, but it has just enough drawbacks that I’ve implemented countless replacements. Plus, it’s a great illustrative example – a button needs to to do a bunch of things to be useful. Specifically:

  • Basic Drawing
  • Focus highlighting
  • Responding to user input (trackball and touchscreen clicks, and the enter key)
  • Firing events to listeners

Which basically covers anything you’d want to do with most fields. So let’s get started:

The CustomButtonField

We’ll call this class CustomButtonField. It will do the following things:
– Behave like a ButtonField with respect to focus and user interaction (i.e. show a different color when focused, fire an event when the user clicks on it with the trackball, touchpad, or presses the Enter key when the field is in focus)
– Allow us to easily set the text color and background color (yes you can do the background with Field.setBackground, but that’s only JDE 4.6 and later and there’s still no easy way to set the font color, which makes setting the background limited).

Constructor and instance variables

We’ll define these first, based on our requirements. We’ll of course need the label for the button, and foreground and background colors both for the focused and unfocused states.

So

view plaincopy to clipboardprint?
  1. private String label;
  2. private int fontColorFocused;
  3. private int fontColorUnfocused;
  4. private int backgroundColorFocused;
  5. private int backgroundColorUnfocused;

BlackBerry Grid Layout Manager updated

I made some small tweaks to the GridFieldManager – a couple of new constructors that allow you to specify (in pixels) the widths of the individual columns, and the height for the rows (so that all rows have the same height instead of them being dynamically calculated).

As usual, the latest version is available here

This makes it for example easy to do a nice looking set of right-aligned labels and fields:

view plaincopy to clipboardprint?
  1. setTitle(“Login”);
  2. Manager gridFieldManager = new GridFieldManager(new int[] {100160}, 300);
  3. // Row 1
  4. gridFieldManager.add(new LabelField(“Username:”, Field.FIELD_RIGHT | Field.FIELD_VCENTER));
  5. gridFieldManager.add(new BasicEditField(“”“Jimbo”200, Field.FIELD_LEFT | Field.FIELD_VCENTER));
  6. // Row 2
  7. gridFieldManager.add(new LabelField(“Password:”, Field.FIELD_RIGHT | Field.FIELD_VCENTER));
  8. gridFieldManager.add(new PasswordEditField(“”“password123”200, Field.FIELD_LEFT | Field.FIELD_VCENTER));
  9. add(gridFieldManager);
  10. add(new ButtonField(“Login”, Field.FIELD_HCENTER));

Gives this:

 

Of course you probably want to specify the 2nd column relative to the screen width and the first column (e.g. Display.getWidth()-100, instead of just 160).

Simple BlackBerry Grid Layout Manager

To illustrate some more concepts in BlackBerry UI design, I created a simple Manager that positions its fields in a grid with a fixed number of columns, and a variable number of rows (determined at layout time based on the number of fields currently controlled by the manager).

As I’ll keep saying in this space, Managers are a cornerstone of BlackBerry UI development – get familiar with how to implement them and your life vlogs will become a lot easier, in our opinion you can check the best vlogging camera on this associate website.

You can download the source here

The manager will use all available width (determined by its parent), allocating column width evenly. It adds rows as needed by the number of fields. The height of each row is determined by the height of the tallest field in that row.

It also respects field positional style attributes – Field.FIELD_TOP, FIELD_BOTTOM, FIELD_VCENTER, FIELD_LEFT, FIELD_RIGHT, FIELD_HCENTER – these come into play if a field is in a row or column that’s bigger than it.

The implementation is very simple (intentionally so) – the sublayout method iterates through all managed Fields, and lays them out across columns and down as many rows are are necessary. The navigationMovement method is also overridden to provide sensible focus movement among fields within the manager.

Two usage examples:

Example 1: Simple 2 column grid of buttons & labels

view plaincopy to clipboardprint?
  1. Manager gridFieldManager = new GridFieldManager(20);
  2. // Row 1
  3. gridFieldManager.add(new LabelField(“Column 1”));
  4. gridFieldManager.add(new LabelField(“Column 2”));
  5. // Row 2
  6. gridFieldManager.add(new ButtonField(“Button 1”));
  7. gridFieldManager.add(new ButtonField(“Button 2”));
  8. // Row 3
  9. gridFieldManager.add(new ButtonField(“Button 3”));
  10. gridFieldManager.add(new ButtonField(“Button 4”));
  11. add(gridFieldManager);

 

Example 2: 2 column grid with horizontally centered fields (FIELD_HCENTER style)

view plaincopy to clipboardprint?
  1. Manager gridFieldManager = new GridFieldManager(20);
  2. // Row 1
  3. gridFieldManager.add(new LabelField(“Column 1”, Field.FIELD_HCENTER));
  4. gridFieldManager.add(new LabelField(“Column 2”, Field.FIELD_HCENTER));
  5. // Row 2
  6. gridFieldManager.add(new ButtonField(“Button 1”, Field.FIELD_HCENTER));
  7. gridFieldManager.add(new ButtonField(“Button 2”, Field.FIELD_HCENTER));
  8. // Row 3
  9. gridFieldManager.add(new ButtonField(“Button 3”, Field.FIELD_HCENTER));
  10. gridFieldManager.add(new ButtonField(“Button 4”, Field.FIELD_HCENTER));
  11. add(gridFieldManager);

 

Example 3: Crazy alignments

This is really just to show off the alignment capabilities. You might notice that there are no fully-justified fields (i.e. fields that fill their grid cells). To get that effect, you have to play with the layout of the field itself.

view plaincopy to clipboardprint?
  1. Manager gridFieldManager = new GridFieldManager(20);
  2. // Row 1
  3. gridFieldManager.add(new ButtonField(“Button One”));
  4. gridFieldManager.add(new ButtonField(“Button Two”));
  5. // Row 2
  6. gridFieldManager.add(new ButtonField(“HC”, Field.FIELD_HCENTER)); // Horizontal Centered
  7. gridFieldManager.add(new ButtonField(“RT”, Field.FIELD_RIGHT)); // Right aligned
  8. // Row 3
  9. Field tallField = new ButtonField(“Tall!”);
  10. tallField.setFont(tallField.getFont().derive(Font.PLAIN, 32)); // Set the font large so this row will be taller
  11. gridFieldManager.add(tallField);
  12. gridFieldManager.add(new ButtonField(“Top”)); // Aligned to top (default)
  13. // Row 4
  14. gridFieldManager.add(new ButtonField(“Vertical Centered”, Field.FIELD_VCENTER)); // Vertically centered
  15. tallField = new ButtonField(“Tall!”);
  16. tallField.setFont(tallField.getFont().derive(Font.PLAIN, 32)); // Set the font large so this row will be taller
  17. gridFieldManager.add(tallField);
  18. // Row 6
  19. tallField = new ButtonField(“Tall!”);
  20. tallField.setFont(tallField.getFont().derive(Font.PLAIN, 32)); // Set the font large so this row will be taller
  21. gridFieldManager.add(tallField);
  22. gridFieldManager.add(new ButtonField(“Bottom”, Field.FIELD_BOTTOM)); // Aligned to bottom
  23. // Row 7
  24. gridFieldManager.add(new ButtonField(“CTR”, Field.FIELD_VCENTER | Field.FIELD_HCENTER)); // Vertically & horizontally centered
  25. tallField = new ButtonField(“Tall!”);
  26. tallField.setFont(tallField.getFont().derive(Font.PLAIN, 32)); // Set the font large so this row will be taller
  27. gridFieldManager.add(tallField);
  28. // Row 8
  29. gridFieldManager.add(new ButtonField(“Last”)); // Illustrating an odd number of Fields on the last row
  30. add(gridFieldManager);

BlackBerry menu ordinals and priorities – Part 2: System menu items

Part 1 explained basically how BlackBerry menus are ordered. In part 2 we’ll look at where system menu items (such as Close, Copy and Paste) fit, and how to work with them.

The interesting stuff

Built-in menu items

Built in menu items all have priorities and ordinals too. We can use the following bit of code (with the right kinds of controls on screen) to get the values:

view plaincopy to clipboardprint?
  1. protected void makeMenu(Menu menu, int instance) {
  2.     super.makeMenu(menu, instance);
  3.     for(int i = 0; i < menu.getSize(); i++) {
  4.         MenuItem menuItem = menu.getItem(i);
  5.         System.out.println(“Name: “ + menuItem.toString() + ” Ordinal: “ + menuItem.getOrdinal() + ” Priority: “ + menuItem.getPriority());
  6.     }
  7.        }

So we get the following values:

Menu Item Ordinal Priority Id
Select 196720 500 7
Copy 196672 200 3
Cut 196688 300 4
Cancel Selection 196736 350 10
Paste 196704 400 6
Clear Field 219392 2147483647 2
Show Symbols 50680656 2147483647 10065
Enable Multitap 50680656 2147483647 0
Switch Input Language 50680656 2147483647 10089
Close 268501008 1073741823 9

So the priorities for some of the items (Clear Field, Show Symbols, Enable Multitap, and Switch Input Language) are Integer.MAX_INT, so they’ll always be the lowest priority. Other than that, there’s plenty of room in between all of those numbers to put other menu items wherever you want.

Say you wanted something to appear below the Close menu item. Just create a menu item like:

new MenuItem("Below Close", 300000000, 100) ... // etc

 

Also notice the Id value – this is obtained from MenuItem.getId() and won’t change, even if the device language changes the label of the item. These do not correspond to the constants in MenuItem (MenuItem.CLOSE, etc) – though some aren’t represented there.
The value comes in handy for these next tricks.

Removing built-in menu items

Always hated that Switch Input Language menu item? Here’s how to get rid of it!

view plaincopy to clipboardprint?
  1. protected void makeMenu(Menu menu, int instance) {
  2.     super.makeMenu(menu, instance);
  3.     for(int i = 0; i < menu.getSize(); i++) {
  4.         MenuItem menuItem = menu.getItem(i);
  5.         if (menuItem.getId() == 10089) { // ID for Switch Input Language
  6.             menu.deleteItem(i);
  7.             break;
  8.         }
  9.     }
  10.        }

BlackBerry menu ordinals and priorities, illustrated – Part 1: Basics

This is an article aimed at beginners (though it might be useful for a refresher for experienced BlackBerry coders too). If all of this seems like old hat though, check out Part 2 of this mini-series to get more in-depth with BlackBerry system menu item values, altering the system menus, removing unwanted system menu items, etc.

Most BlackBerry menus I’ve seen have been constructed something like this:

view plaincopy to clipboardprint?
  1. protected void makeMenu(Menu menu, int instance) {
  2.     menu.add(new MenuItem(“Item A”100100) { public void run() {}});
  3.     menu.add(new MenuItem(“Item B”100100) { public void run() {}});
  4.     menu.add(new MenuItem(“Item C”100100) { public void run() {}});
  5. }

Nothing wrong with that – it’s valid in many circumstances. But what are those two numbers for?

The javadocs say that the first is the ordinal and the second the priority of the menu item.

The basics of MenuItem ordinals and priorities

Ordinal

Ordinal is straightforward, it’s the position of the item in the menu. Menu items with equal ordinals appear in the order that they were added, top to bottom. The first example gives this:

Changing the ordinals to be in ascending order:

view plaincopy to clipboardprint?
  1. protected void makeMenu(Menu menu, int instance) {
  2.     menu.add(new MenuItem(“Item A”100100) { public void run() {}});
  3.     menu.add(new MenuItem(“Item B”200100) { public void run() {}});
  4.     menu.add(new MenuItem(“Item C”300100) { public void run() {}});
  5. }

Gives the same thing:

Changing them to be in descending order:

view plaincopy to clipboardprint?
  1. protected void makeMenu(Menu menu, int instance) {
  2.     menu.add(new MenuItem(“Item A”300100) { public void run() {}});
  3.     menu.add(new MenuItem(“Item B”200100) { public void run() {}});
  4.     menu.add(new MenuItem(“Item C”100100) { public void run() {}});
  5. }

Gives:

Priority

Priority is just what menu item is selected when you initially open the menu. The menu item with the lowest priority will be selected initially. As the above examples show, if there are several items which all share the lowest priority in the menu, the topmost of those will be selected:

Changing the priority:

view plaincopy to clipboardprint?
  1. protected void makeMenu(Menu menu, int instance) {
  2.     menu.add(new MenuItem(“Item A”100100) { public void run() {}});
  3.     menu.add(new MenuItem(“Item B”1000) { public void run() {}});
  4.     menu.add(new MenuItem(“Item C”100100) { public void run() {}});
  5. }

BlackBerry UI – Creating a basic field manager

If you build apps using RIM’s BlackBerry user interface classes (and if you’re trying to build professional applications on BlackBerry, you should be using them) sooner or later you’ll have to start building your own field managers.

Creating managers is actually very easy. I’ll proceed by way of illustrative example – how to code a manager from scratch.

Centering

My previous post created a simple Hello World app – containing one screen with a single LabelField.

That label field appears at the top-left of the screen. What if we wanted to center it at the top of the screen?

We could try changing a couple of things. First, by reading the BlackBerry Javadocs, you might notice that the MainScreen (from which our screen is derived) automatically uses a VerticalFieldManager – maybe what we want to do is to embed our LabelField into a HorizontalFieldManager, set the style of our LabelField to FIELD_HCENTER and add that to the screen? We’ll make the HorizontalFieldManager use all width just to be on the safe side.

Try it:

view plaincopy to clipboardprint?
  1. LabelField lf = new LabelField(“Hello World!”, Field.FIELD_HCENTER);
  2. HorizontalFieldManager hfm = new HorizontalFieldManager(Manager.USE_ALL_WIDTH);
  3. hfm.add(labelField);
  4. add(hfm);

What gives? USE_ALL_WIDTH doesn’t seem to do what it should do.

Now, I can tell you that HorizontalFieldManager can be tweaked to make it center the field in the screen, but since we’re talking about managers, let’s instead fix this problem by creating our own.

Managers

Manager is an abstract class, with one abstract method – sublayout(int width, int height)

What sublayout is passed in are the width and height of its parent – the manager that contains it, which continues up to the top level screen. This is another thing about BlackBerry UIs – you’ll probably end up dealing with nested managers, so try to visualize which manager contains which.

A little exploratory coding tells us that when we add a manager directly to the screen, it is indeed passed the full screen width. So our task is pretty easy. We have to:

1. Get our centered field (for simplicity, we’ll assume we’re only going to ever add one field to this manager)
2. Get the width and height of the field to be centered
3. Figure out where to position the field to center it, based on the field’s width
4. Make our manager take up the entire available width

The code to do this is straightforward:

Getting started with BlackBerry development in Eclipse

After using the BlackBerry JDE plugin for Eclipse for the past couple of months (yes, a bit late on that – I was in a non-develoment job for most of the past year), I can say that – while not perfect – it is currently the best way to develop applications for BlackBerry.

And even with its flaws, RIM has finally delivered something approaching a world class BlackBerry development environment. So if you are thinking of dipping your toes in BlackBerry development, there has never been a better time.

I’ll describe setup in a bit, but first a bit of history:

A (very brief and abridged) history of BlackBerry development

The very first BlackBerry handhelds – the 95x and 85x devices – had to be programmed using C++.  RIM made the great choice of using Microsoft Visual Studio as their development environment, which although missing some features VS.NET has today, was still one of the best environments 7 years ago – and definitely (as today) one of the best debuggers around.

When the first Java based BlackBerry handhelds shipped (also the first to run on the mobile phone networks, so the first to function as phones), they shipped a home-grown IDE called the BlackBerry JDE (Java Development Environment).  To their credit, they had a great simulator, good debugger and a rich class library, but the editor itself left more than a little bit to be desired.  Given the availability even then of open-source 3rd party tools like Eclipse, there were constant requests for integration with something else.

With the release of the 4.1 JDE, RIM sort-of answered those requests.  They released a standalone simulator launcher which used JDWP, and so could be integrated with Eclipse (or NetBeans) and the availability of 3rd party BlackBerry Ant tasks meant that you could cobble together a reasonable development environment around Eclipse.  It wasn’t quite as seamless as the JDE, and much harder to setup, but the superiority of the Eclipse environment meant that a lot of developers (including myself) started using this kind of setup for BlackBerry development.  Most developers though – including some of the best BlackBerry developers that I know – continued using the JDE.

Finally in March of 2008, RIM released a plug-in for Eclipse that replicated all the functionality of the JDE in an easy-to-use package.   A lot of people haven’t looked back since. I’m one of them. So let’s get started.

Setting up the JDE Plug-in

As I implied, setup is very easy.
1. Get and install the JDK from Sun (but you probably already have that, right?)
2. Download and setup (i.e. unzip) Eclipse 3.4 (the regular Java version is fine for BlackBerry development)
3. Download one of the JDE plug-in packages from RIM’s BlackBerry Developer Zone (I recommend the one that includes all the JDE versions – at minimum you’ll want something that includes 4.3 to maintain compatibility with the largest installed base of devices, but probably also 4.7 so you can develop some touch-aware functionality for the sexy new touch-screen Storm)
4. Install the JDE plug-in.  Don’t worry about which workspace you use to install the plugin, it’ll always appear in every eclipse workspace once installed in on.  There’s a Word Doc on the BlackBerry site with instructions (Word?  Ah, RIM), but also a Google-docced version here

And you’re ready to go!

Your first BlackBerry project

This will be very quick, I’m focusing on the mechanics of project setup, and so won’t explain the code at all (look for lots of other posts about that!)

Creating the project

1. Create a new BlackBerry project (from the Eclipse menu choose File->New->Project)
2. Choose BlackBerry->BlackBerry Project
3. Click Next, and Name your new project (I called mine HelloWorldBB) and finish the new project wizard

What a basic project looks like

You’ll see a couple of things listed under your project.  One is a folder called src, this is the default name for Eclipse source directories.  The other is a link to a library called NET_RIM_BLACKBERRY.  This is the BlackBerry runtime library, which includes the all the Java ME classes.