Author Archive

Add Setting to the BlackBerry Options

The Options application – or Settings on some BlackBerry themes – provides a unified location to set BlackBerry options and configure applications. A BlackBerry application can also add its own options to this listing, allowing a user to configure an application from outside of the application. This can be very useful for background applications that do not use a graphical user interface (GUI). The sample application below shows how to add custom options to the BlackBerry Options application by using the OptionsManager class and the OptionsProvider interface.

Note: This sample application uses an alternate entry point that specifies “auto-start” as its parameter. For more information on alternate entry points, see this article .

package com.rim.samples.options;

import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
import net.rim.device.api.system.*;
import net.rim.blackberry.api.options.*;

public class OptionsSample extends UiApplication
    public static void main(String[] args)
        //This sample makes use of alternate entry points.
        //An alternate entry point will need to be configured
        //in your workspace to use this sample.

        if (args.length > 0 && args[0].equals("auto-start"))
            //Enter the auto start portion of the application.
            //Register an options provider and exit.
            OptionsSampleOptionsProvider provider =
              new OptionsSampleOptionsProvider();
            //Enter the GUI portion of the applicaiton.
            //Create a new instance of the application
            //and start the application on the event thread
            OptionsSample theApp = new OptionsSample();

    public OptionsSample()
        MainScreen theScreen = new MainScreen();
        theScreen.setTitle(new LabelField("Options Sample"));
        OptionsSampleProperties props = OptionsSampleProperties.fetch();
        RichTextField greeting = new RichTextField();

        if (props.isGreetingEmphasized())
            // An emphatic greeting is in all capitals and followed by
            // exclamation marks and is displayed in bold.
            String greetingText = props.getGreeting().toUpperCase()
              + "!!!!";
            Font emphatic = Font.getDefault().derive(Font.BOLD);
            int[] offsets = {0, greetingText.length()};
            byte[] attributes = {0};
            Font[] fonts = {emphatic};
            greeting.setText(greetingText, offsets, attributes, fonts);


package com.rim.samples.options;

import net.rim.blackberry.api.options.*;
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.container.*;
import net.rim.device.api.ui.component.*;

class OptionsSampleOptionsProvider implements OptionsProvider
    private EditField greetingEdit;
    private ObjectChoiceField styleChoice;
    private OptionsSampleProperties optionProperties;

    public OptionsSampleOptionsProvider()

    public String getTitle()
        return "Options Sample";

    public void populateMainScreen(MainScreen mainScreen)
        //Read in the properties from the persistent store.
        optionProperties = OptionsSampleProperties.fetch();

        //Get the current values from optionProperties and create
        //the controls to represent them.
        greetingEdit = new EditField
          ("Greeting: ", optionProperties.getGreeting(),
            BasicEditField.DEFAULT_MAXCHARS, BasicEditField.NO_NEWLINE);

        Object[] choices = {"Normal", "Emphatic!!"};
        int selection = optionProperties.isGreetingEmphasized() ? 1 : 0;
        styleChoice = new ObjectChoiceField("Style: ", choices, selection);

    public void save()
        //Get the new values from the UI controls
        //and set them in optionProperties.
          (styleChoice.getSelectedIndex() != 0);

        //Write our changes back to the persistent store.;

        //Null out our member variables so that their objects can be garbage
        //collected. Note that this instance continues to be held by the
        //options manager even after the user exits the options app,
        //and will be re-used next time.

        greetingEdit = null;
        styleChoice = null;
        optionProperties = null;

package com.rim.samples.options;

import net.rim.device.api.system.*;
import net.rim.device.api.util.*;

//The configuration properties of the OptionsSample application. One instance holding
//the effective values resides in the persistent store.
class OptionsSampleProperties implements Persistable
    private String greeting;
    private boolean greetingEmphasized;

    //Hash of
    private static final long PERSISTENCE_ID = 0x7eeffcc691f4418dL;

    //Persistent object wrapping the effective properties instance
    private static PersistentObject store;

    //Ensure that an effective properties set exists on startup.
    static {
        store = PersistentStore.getPersistentObject(PERSISTENCE_ID);
        synchronized (store) {
            if (store.getContents() == null) {
                store.setContents(new OptionsSampleProperties());

    // Constructs a properties set with default values.
    private OptionsSampleProperties()
        greeting = "Hello there";
        greetingEmphasized = false;

    //Retrieves a copy of the effective properties set from storage.
    public static OptionsSampleProperties fetch()
        synchronized (store)
            OptionsSampleProperties savedProps =
              (OptionsSampleProperties) store.getContents();
            return new OptionsSampleProperties(savedProps);

    //Causes the values within this instance to become the effective
    //properties for the application by saving this instance to the store.
    public void save()
        synchronized (store)

    //The greeting is the text that is displayed within the
    //OptionsSample application.
    public String getGreeting()
        return greeting;

    public void setGreeting(String greetingLocal)
        greeting = greetingLocal;

    //If emphasized, the greeting is displayed in more resouding manner.
    public boolean isGreetingEmphasized()
        return greetingEmphasized;

    public void setGreetingEmphasized(boolean greetingEmphasizedLocal)
        greetingEmphasized = greetingEmphasizedLocal;

    //Cannonical copy constructor.
    private OptionsSampleProperties(OptionsSampleProperties other)
        greeting = other.greeting;
        greetingEmphasized = other.greetingEmphasized;


SVG for BlackBerry Theme Builder

What is SVG?

SVG stands for scalable vector graphics. In layman’s terms, SVG a type of graphic that will look smooth, crisp, and clean no matter how big or small it is. It is also a graphic type that can be scripted with XML-like coding, so it can be animated and/or interactive.

Even if you’ve never heard of SVGs, you’ve probably seen some of its cousins in the vector graphics field, specifically EPSs (Encapsulated PostScript), PDFs (Portable Document Format), WMFs (Windows Metafile), and SWFs (Shockwave Flash).

SVG is different from most of its cousins in that, because it is XML-based in its coding, it is possible to create and edit an SVG file with just a simple text editing program. There are plenty of graphics programs out there, though, that can be used to generate SVG files, including one provided specifically for use with BlackBerry devices.


If you’ve created themes for BlackBerry® devices for any reasonable length of time, you’ve probably noticed that there are specific areas in the BlackBerry Theme Builder where you can input SVG files. Everyone says you can make a theme do all sorts of wild and wonderful things with SVG. However, if you’ve never worked with or even seen them before, the first question you have is “What is SVG?”.

What SVG can do for themes

When working in the BlackBerry Theme Builder 5.0, there are two sections where SVGs can be used. These are the Home screen and the Lock screen. Using SVG can make your themes more dynamic in a few ways:

  • Animation: Only with SVGs can you add any sort of animation to your Home and Lock screens.
  • More customized Home screen buttons: In BlackBerry Theme Builder, you are restricted by various image sizes regarding buttons and icons. Using SVG to create buttons removes those limitations. With SVG, icons can be resized, and buttons can be given custom animations when highlighted and/or selected.
  • Make screens more interactive: With SVG files, it’s possible to make the screens more dynamic. Drawers can be created to hide Home screen buttons. Animations can be made to start or stop on unique triggers, such as the arrival of a new text message, or the rotation of a BlackBerry® Storm™ smartphone from portrait view to landscape view.

How to make SVG files

There are two main ways to go about making an SVG file for BlackBerry device themes. The first way is to use a program called the BlackBerry Composer. This free program is provided by RIM, and it’s usually installed on your machine when you install the BlackBerry Theme Builder. The second way is by writing the SVG code yourself with the use of a text editor program. There are pros and cons to each of these techniques, and different resources available for each:

BlackBerry Composer


  • WYSIWYG program geared towards those already comfortable with various graphic design programs
  • No need to learn SVG code beforehand
  • Free to download
  • Works relatively well for simple, straightforward animation and interactivity


  • May export bloated code for SVG files with complex animations and/or interactivity
  • SVG components often renamed to random, irregular number strings that make it difficult for those with coding experience to decipher




  • Artist has greater control over organization of SVG code, including the naming of elements
  • No need for any special program to write code. Just a text editor, such as Notepad, is fine.
  • Can create special effects that cannot be re-created with the BlackBerry Composer
  • Hand-coded SVG files can have a smaller file size than BlackBerry Composer exported SVG files that do the same animation/special effects


  • Has a steep learning curve for those with no coding experience
  • Testing for appearance and fuctionality involves repeatedly importing and updating the SVG file in the appropriate BlackBerry Smartphone Simulator or on a BlackBerry device
  • Not easy to find specific tutorials for hand-coding BlackBerry device SVG files



Youtube Viewer using BlackBerry 6 Communication API

The Communication and Parsing API introduced in the BlackBerry® 6 OS probably doesn’t get as much attention as it really deserves. It has one of those names that could mean just about anything, but when I created a sample with it, I found it made many tasks simple – and I barely scratched the surface of what was possible.

You’ll find the API specification in the package, where you will see the significant set of interfaces and classes that provide all this functionality. The API breaks up communication into a few parts: The Destination is the target for a connection, usually a URL, and you can send and receive Message objects through it. Destinations can block the execution thread, or not, and you can send messages without handling the response with aFireAndForgetDestination. A Destination can also be connected with a MessageProcessor, which will parse the messages for you. Several processors are included in the API for common message formats like XML, JSON, RSS, and so on. Processors can be chained to support even more functionality. Finally, Messages can be retrieved as MessageFutures, and Destinations can be used to receive pushes and other incoming connections.

Behind the scenes is even more great stuff, like message queuing, prioritization, and even support for inter-process communication. Before we get too buried in the details, I should point out that the BlackBerry 6 SDK includes a full sample application that shows how to do all of this. The sample I want to share with you today is an example using this new API to streamline development of a YouTube® client. With the proliferation of APIs like YouTube’s Data API, which offer ATOM and JSON-C (for more bandwidth saving) interfaces, many opportunities become quite accessible.

Full sample code is included so you can check it out, but let’s look at some of the Communication API in action. The destination is the YouTube Data server with several basic query parameters:

BlockingSenderDestination destination = DestinationFactory.createBlockingSenderDestination(_context,
URI.create(buildQueryURL(query, index, max)), _processor);

Where my URL is built from a base, and I’m just appending the search query string and variables to return a particular section of the feed, I end up with a URL like so:


The query I’ve used restricts the response somewhat to a mobile-friendly version, including filtering out any videos that don’t have a mobile video link – a useful feature for mobile clients that could be expanded on in this sample. I’ve also included a MessageProcessor to handle the output; in this case, it’s anXMLHashtableMessageProcessor, which nicely converts the ATOM response into a simple Hashtable, so I can do things like pulling all the titles out into a String array:

String[] titles = contents.getStringArray("/feed/entry/title");

Once I’ve grabbed all the details I care about, I can send the results back to the screen for displaying. However, the feed response contains a URL for the thumbnails, so I need to download that as well. This is a neat opportunity to use non-blocking destinations and update the display when the thumbnails arrive:

NonBlockingSenderDestination destination = DestinationFactory.createNonBlockingSenderDestination(_context,
					URI.create(url), this);

Those requests are fired off through the API and I’ve got a MessageListener waiting for them, which will take the data and inform the screen it can update the image from the placeholder:

public void onMessage(Destination destination, Message message) {
if (message instanceof ByteMessage) {
		byte[] results = ((ByteMessage) message).getBytePayload();
		EncodedImage image = EncodedImage.createEncodedImage(results, 0, -1);
		... //send the image to the Screen

Give the sample a look and check out the API in more depth to see how you can put it to work for you. We’ll follow this up later with a more detailed sample showcasing the advanced features of both YouTube’s Data API and the BlackBerry® Communication API.



BlackBerry AMMS (Advanced Multimedia Supplement) API Support

The Advanced Multimedia Supplement (AMMS) API, also known as JSR-234, is used to access advanced camera features on the BlackBerry® platform.  As of BlackBerry® 6.0 none of the audio capabilities of AMMS has been implemented, with the exception of AudioFormatControl and VideoFormatControl which have been implemented only so far as to support their stated features for video and still image capture.  Conversely many of the camera capabilities have been implemented.

AMMS by definition allows implementers to implement only some of the API.  Specifically, only the relevant ‘parts’ to the destination platform need to be implemented, with each ‘part’ consisting of a set of classes to implement.  The guarantee AMMS makes however is that any part that is implemented must be fully implemented to the extent that the platform can support it.  This means that each class that must be implemented as a part will itself be only partially implemented enough to fulfill that part with what the device is capable of.  Still following?

To put it another way, within each class the level of implementation depends on what the device can actually do. When an AMMS class is implemented the BlackBerry platform will guarantee to support the invocation (meaning an application that attempts to call an unsupported feature will compile and, if properly written, will fail gracefully and not crash) but not necessarily the implementation.

This is why developers who have used the AMMS API classes have found that not every portion of a class is fully implemented.  For example, the CameraControl class is an implemented AMMS class on the BlackBerry platform.  If an application were to call its isShutterFeedbackEnabled() method, it would always return true since that feature is supported on all platforms (a ‘click’ sound is heard when a picture is taken).  However, if that same application called its enableShutterFeedback(boolean) method, a MediaException would be thrown with the message “Setting shutter feedback is not possible”. This is because although the feature is supported, the ability to toggle it is not – it is always on.

For most classes in the AMMS API there are built-in methods to query the level of support of that class, but this was not done consistently.  In some cases the AMMS JavaDoc™ will state the behaviour of the platform if the particular feature or method is not supported on the implementing platform.  For example, in the case of the MediaException mentioned in the example above, there is no method to query if toggling shutter feedback is supported but the documentation states that the method “throws – if setting of the shutter feedback is not possible”.[1]

What’s Supported?

Once your application has created a player for still image capture or for video capture, the controls available depend largely on the context of the player.  For example a player for still image capture will not have an AudioFormatControl available, however a player for video capture will.  The following is a list of controls that are implemented for at least one player context:




Similarly, the following controls are not implemented at all on the BlackBerry platform:





None of the controls in javax.microedition.amms.control.audio3d

None of the controls in javax.microedition.amms.control.audioeffect

None of the controls in javax.microedition.amms.control.tuner

None of the controls in javax.microedition.amms.control.imageeffect

Within each implemented class, there are varying levels of implemented methods, as previously explained.  The table below shows a list of which methods are implemented for each supported AMMS Control.

Class Method Implemented?
CameraControl enableShutterFeedback(boolean) NO
getCameraRotation() YES
getExposureMode() YES
getStillResolution() YES
getSupportedExposureModes() YES
getSupportedStillResolutions() YES
getSupportedVideoResolutions() NO
getVideoResolution() NO
isShutterFeedbackEnabled() YES
setExposureMode(String) YES
setStillResolution(int) YES
setVideoResolution(int) NO
FocusControl getFocus() YES
getFocusSteps() NO
getMacro() YES
getMinFocus() NO
isAutoFocusSupported() YES
isMacroSupported() YES
isManualFocusSupported() YES
setFocus(int) YES
setMacro(boolean) YES
EnhancedFocusControl getCurrentFocusMode() YES
isAutoFocusLocked() YES
isFocusModeSupported() YES
setFocusMode() YES
startAutoFocus() YES
stopAutoFocus() YES
FlashControl getMode() YES
getSupportedModes() YES
isFlashReady() YES
setMode(int) YES
ZoomControl getDigitalZoom() YES
getDigitalZoomLevels() YES
getMaxDigitalZoom() YES
getMaxOpticalZoom() NO
getMinFocalLength() NO
getOpticalZoom() NO
getOpticalZoomLevels() YES
setDigitalZoom(int) YES
setOpticalZoom(int) YES
SnapshotControl getDirectory() YES
getFilePrefix() YES
getFileSuffix() YES
setDirectory(String) YES
setFilePrefix(String) YES
setFileSuffix(String) YES
start(int) YES
stop() YES
unfreeze(boolean) YES
AudioFormatControl getEstimatedBitRate() NO
getFormat() YES
getIntParameterValue(String) NO
getMetadataOverride() YES
getMetadataSupportMode() YES
getStrParameterValue(String) YES
getSupportedFormats() YES
getSupportedIntParameterRange(String) NO
getSupportedIntParameters() YES
getSupportedMetadataKeys() YES
getSupportedStrParameters() YES
getSupportedStrParameterValues(String) YES
setFormat(String) YES
setMetadata(String, String) NO
setMetadataOverride(boolean) NO
setParameter(String, int) NO
setParameter(String, String) YES
VideoFormatControl getEstimatedBitRate() NO
getFormat() YES
getIntParameterValue(String) YES
getMetadataOverride() YES
getMetadataSupportMode() YES
getStrParameterValue(String) YES
getSupportedFormats() YES
getSupportedIntParameterRange(String) YES
getSupportedIntParameters() YES
getSupportedMetadataKeys() YES
getSupportedStrParameters() YES
getSupportedStrParameterValues(String) YES
setFormat(String) YES
setMetadata(String, String) NO
setMetadataOverride(boolean) NO
setParameter(String, int) YES
setParameter(String, String) YES
ContainerFormatControl getEstimatedBitRate() NO
getFormat() YES
getIntParameterValue(String) NO
getMetadataOverride() YES
getMetadataSupportMode() YES
getStrParameterValue(String) YES
getSupportedFormats() YES
getSupportedIntParameterRange(String) NO
getSupportedIntParameters() NO
getSupportedMetadataKeys() NO
getSupportedStrParameters() YES
getSupportedStrParameterValues(String) YES
setFormat(String) NO
setMetadata(String, String) NO
setMetadataOverride(boolean) NO
setParameter(String, int) YES
setParameter(String, String) NO


Programmatically Reboot a BlackBerry Device

if you curious about how to programmatically reboot a BlackBerry Device,
there’s no specific API to do it.
but, you should start your curiosity from how you reinstall an application,
sometime you need to reboot your device.

here’s how to programmatically reinstall a module, so the BlackBerry will ask to reboot..

  1. Create a dummy.cod module
  2. public class Dummy extends Application{
    	public static void main( String[] args )
    	    new Dummy().enterEventDispatcher();
  3. Create new BlackBerry project (reboot project) and include the dummy.cod in the project
  4. In the reboot project, install the dummy.cod
  5. Run the dummy application in the background
  6. Uninstall the dummy application, after removing dummy.cod the BlackBerry will ask to reboot
  7. 	public  void reset() throws IOException, ApplicationManagerException {
    		// load the dummy cod file
    		byte[] cod = IOUtilities.streamToBytes(getClass().getResourceAsStream("/dummy.cod"));
    		//create new module
    		int	newHandle = CodeModuleManager.createNewModule(cod.length,
    				cod, cod.length);
    		//install the module
    		if (newHandle != 0) {
    			int savecode = CodeModuleManager.saveNewModule(newHandle, true);
    			if (savecode == CodeModuleManager.CMM_OK_MODULE_OVERWRITTEN)
    				.println("The operation completed successfully; a module was overwritten and marked for deletion in the process.");
    		//now run the dummy application in background
    		ApplicationDescriptor appDesc = CodeModuleManager.getApplicationDescriptors(newHandle)[0];
    		ApplicationManager.getApplicationManager().runApplication(appDesc, false);
    		CodeModuleManager.deleteModuleEx(newHandle, true);
    		//restart the blackberry if reuired
    		if (CodeModuleManager.isResetRequired())
    		//if you want to automate the reboot.
    		EventInjector.TrackwheelEvent moveEvent =  new EventInjector.TrackwheelEvent( EventInjector.TrackwheelEvent.THUMB_ROLL_UP, 1, 1 );
    		EventInjector.KeyCodeEvent pressEndKey = new EventInjector.KeyCodeEvent(
    				KeyCodeEvent.KEY_DOWN, (char) Keypad.KEY_ENTER , 0, 100);
    		EventInjector.KeyCodeEvent releaseEndKey = new EventInjector.KeyCodeEvent(
    				KeyCodeEvent.KEY_UP, (char) Keypad.KEY_ENTER, 0, 100);
    		try {
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    		EventInjector.invokeEvent(releaseEndKey);"device is restarting");


"multiply defined" error


When an application is loaded onto a device or simulator an error is thrown that is similar to the following:

Error Starting module_name: Class ‘class_name’ multiply defined


This error is thrown when more than one module on the device defines a class with the same name and package structure as another module on the device.

For example application A and application B both have a class defined as


Note: All classes must be uniquely identifiable to prevent this error from occurring.


If the instances of multiple classes are used by different applications you are developing

Use a library in which all common classes are defined and include this library with each application that requires access to the shared classes. This way, only one instance of the classes will ever be installed at one time, preventing this error from being thrown.

If the multiple class instances occur between your application and another third-party application

Ensure that all package names are unique by using identifiers that would not be used by other companies. One recommendation is to use your company’s web site in reverse for the package structure.For example if the company web site is, then start all packages with com.mycompany.

Because the web site URL is unique to your company, it makes sure that the package structure of your application is unique as well.


Configure The BlackBerry MDS Simulator Connection via Proxy

sometime you need to redirect the MDS simulator access not directly to the Internet,

the redirection is via HTTP Proxy (for example Squid).

here’s how to configure..

  • Open the file. The file can be found in the following locations:For BlackBerry MDS-CS Simulators installed with BlackBerry Java Plug-in for Eclipse


    For BlackBerry MDS-CS Simulators installed with BlackBerry JDE

    \Program Files\Research In Motion\BlackBerry JDE #.#.#\MDS\config

    For standalone BlackBerry MDS-CS Simulators

    \Program Files\Research In Motion\BlackBerry Email and MDS Services Simulators #.#.#\MDS\config

  • Under the [HTTP HANDLER] section, update the following:application.handler.http.proxyEnabled = true



  • To include proxy authentication, update the following under the [HTTP HANDLER] section:application.handler.http.proxyUser=username


  • To include proxy auto configuration parameters, update the following values:application.handler.http.proxyAutoConfig = true



    For the last listed parameter, change 0 to the amount of time you want the BlacKBerry MDS-CS Simulator to cache your config file.

  • [1]

    Choosing a Target BlackBerry OS

    Target the BlackBerry® smartphones that suit your application.

    As per November 2010, More than 93% of BlackBerry smartphones can be reached with BlackBerry® Device Software v4.5.

    Target BlackBerry OS


    Tooltips class for BlackBerry

    here is the copy of tooltips class for BlackBerry,
    with 2 different approach.

    first: [1]
    Easy solution to create popup style tooltips on BlackBerry.
    Extend TooltipScreen instead of the usual MainScreen, usage:

    add(new ButtonField(“myButton”), “My Tooltip text”);
    and the source:

    import java.util.Timer;
    import java.util.TimerTask;
    import java.util.Vector;
    import net.rim.device.api.ui.Field;
    import net.rim.device.api.ui.Graphics;
    import net.rim.device.api.ui.XYRect;
    import net.rim.device.api.ui.container.MainScreen;
    public class TooltipScreen extends MainScreen {
        TooltipScreen screen = this;
        boolean doRedraw = false;//prevent infinte redrawing
        Vector tooltips = new Vector();//vector to hold tooltip strings
        private Timer tooltipTimer = new Timer();
        private TimerTask tooltipTask;
        boolean alive = false;//is the tooltip alive? used to pop it after our timeout
        int count = 0;//used to calculate time tooltip is displayed
        //tooltip popup colours:
        int backgroundColour = 0xeeeeee;
        int borderColour = 0xaaaaaa;
        int fontColour = 0x666666;
        //the tooltip:
        String tooltip;
        int tooltipWidth;
        int yCoord;
        int xCoord;
        //region parameters:
        XYRect contentArea;
        int contentBottom;
        int contentRight;
        public TooltipScreen() {
            //when timeout reaches 100ms*20 ie. 2seconds set alive to false and redraw screen:
            tooltipTask = new TimerTask() {
                public void run() {
                    if (alive) {
                        if (count == 20) {
                            alive = false;
            tooltipTimer.scheduleAtFixedRate(tooltipTask, 100, 100);
        //override add method adds an empty string to tooltip vector:
        public void add(Field field) {
        //custom add method for fields with tooltip: add(myField, "myTooltip");
        public void add(Field field, String tooltip) {
        public void setColours(int backgroundColour, int borderColour, int fontColour) {
            this.backgroundColour = backgroundColour;
            this.borderColour = borderColour;
            this.fontColour = fontColour;
        //reset everything when user changes focus,
        //possibly needs logic to check field has actually changed (for listfields, objectchoicefields etc etc)
        protected boolean navigationMovement(int dx, int dy, int status, int time) {
            count = 0;
            alive = true;
            doRedraw = true;
            return super.navigationMovement(dx, dy, status, time);
        protected void paint(Graphics graphics) {
            if (alive) {
                Field focusField = getFieldWithFocus();
                tooltip = (String) tooltips.elementAt(screen.getFieldWithFocusIndex());
                //don't do anything outside the norm unless this field has a tooltip:
                if (!tooltip.equals("")) {
                    //get the field content region, this may fall inside the field actual region/coordinates:
                    contentArea = focusField.getContentRect();
                    contentBottom = contentArea.y + contentArea.height;
                    contentRight = contentArea.x + contentArea.width;
                    //+4 to accomodate 2 pixel padding on either side:
                    tooltipWidth = graphics.getFont().getAdvance(tooltip) + 4;
                    yCoord = contentBottom - focusField.getManager().getVerticalScroll();
                    //check the tooltip is being drawn fully inside the screen height:
                    if (yCoord > (getHeight() - 30)) {
                        yCoord = getHeight() - 30;
                    //check the tooltip doesn't get drawn off the right side of the screen:
                    if (contentRight + tooltipWidth < getWidth()) {
                        xCoord = contentRight;
                    } else {
                        xCoord = getWidth() - tooltipWidth;
                    //draw the tooltip
                    graphics.fillRect(xCoord, yCoord, tooltipWidth, 30);
                    graphics.drawRect(xCoord, yCoord, tooltipWidth, 30);
                    graphics.drawText(tooltip, xCoord + 2, yCoord);
            //doRedraw logic prevents infinite loop
            if (doRedraw) {
                //System.out.println("redrawing screen: " + System.currentTimeMillis());
                doRedraw = false;

    second: [2]

    package ..;
    Display a 'Tooltip" (String) at a specified location for s specified time
    This Tooltip can also be removed.
    Note that in my testing, the display time is not consistent.
    Following example shows it being added and removed using focus events.
    ButtonField bf = new ButtonField("Test") {
        MyTooltip _tooltip;
        protected void onFocus(int direction) {
            if ( _tooltip != null ) {
                _tooltip = null;
            // Display tooltip at 50,50 for 5 seconds
            _tooltip = MyTooltip.addToolTip(UiApplication.getUiApplication(), "Press to test", 50, 50, 5);;
        protected void onUnfocus() {
            if ( _tooltip != null ) {
                // We have displayed a Tooltip - remove it
                _tooltip = null;
    import net.rim.device.api.ui.UiApplication;
    import net.rim.device.api.ui.Manager;
    import net.rim.device.api.ui.Graphics;
    import net.rim.device.api.ui.Font;
    import net.rim.device.api.ui.Screen;
    import net.rim.device.api.ui.component.LabelField;
    import net.rim.device.api.ui.container.VerticalFieldManager;
    import net.rim.device.api.ui.container.PopupScreen;
    class MyTooltip extends PopupScreen{
        int _x;
        int _y;
        TooltipThread _tooltipThread;
        private MyTooltip(Manager manager) {
        public void sublayout(int width, int height)    {
            System.out.println("Tooltip x: " + Integer.toString(_x) + ", y: " + Integer.toString(_y));
        protected void applyTheme() {
            // Overriden to suppress Border etc.
        public void removeToolTip() {
            if ( _tooltipThread != null ) {
        private void display(UiApplication uiApp, int x, int y, int displayTime) {
            _x = x;
            _y = y;
            _tooltipThread = new TooltipThread(uiApp, this, displayTime);
        public static MyTooltip addToolTip(UiApplication uiApp, String toolTipString, int x, int y, int displayTime) {
            VerticalFieldManager manager = new VerticalFieldManager(Manager.FIELD_VCENTER|Manager.NON_FOCUSABLE) {
                protected void paint(Graphics graphics) {
                    graphics.setColor(0x00FFFFFF); // White
                    graphics.setColor(0x00000000); // Black
            MyTooltip toolTip = new MyTooltip(manager);
            LabelField label = new LabelField(' ' + toolTipString + ' ', LabelField.NON_FOCUSABLE);
            label.setFont(Font.getDefault().derive(Font.PLAIN, 16));
            toolTip.display(uiApp, x, y, displayTime);
            return toolTip;
        class TooltipThread extends Thread {
            Object _notifyObject = new Object(); // Used to allow user to dismiss this Tooltip
            PopupScreen _tooltip; // Screen we are going to display
            UiApplication _ourApplication; // access to pushGlobalScreen and dismissStatus from our Application
            int _displayTime; // in seconds
            public TooltipThread(UiApplication ourApplication, PopupScreen tooltip, int displayTime) {
                _tooltip = tooltip;
                _ourApplication = ourApplication;
                _displayTime = displayTime;
            public void run() {
                _ourApplication.pushGlobalScreen(_tooltip, 999, false);
                synchronized(_notifyObject) {
                    try {
                        _notifyObject.wait(_displayTime * 1000);
                    } catch (Exception e) {
            public void dismiss() {
                // notify the waiting object to stop the Thread waiting
                synchronized(_notifyObject) {


    Streaming Multimedia on BlackBerry



    This article applies to the following:

    • BlackBerry® Device Software 4.2.1 and later




    This article describes how to create a solid streaming media application and how to use the StreamingPlayer class, which is an open-source application programming interface (API) containing classes and methods that support streaming media.

    Basic Streaming Media

    There are two methods that can be used to stream media.


    Streaming media over RTSP

    Real Time Streaming Protocol (RTSP) was first implemented in BlackBerry Device Software 4.3 for BlackBerry smartphones that operate on Code Division Multiple Access (CDMA) networks. RTSP is now supported by all BlackBerry smartphones running BlackBerry Device Software 4.5 and later. There are two ways to stream media content over RTSP.


    • Using the browser (starts the Media application on the BlackBerry smartphone)String url = "rtsp://";Browser.getDefaultSession().displayPage(url);
    • Using the Mobile Media API that is specified in JSR 135 (plays within an application)String url = "rtsp://";Player player = Manager.createPlayer(url);player.start();

    Streaming media over HTTP

    Hypertext Transfer Protocol (HTTP) is a protocol that can stream media content and provide real-time playback. Like RTSP, there are two ways to stream media content over HTTP.


    • Using the browser (starts the Media application on the BlackBerry smartphone)
      • String url = "";
      • Browser.getDefaultSession().displayPage(url);
    • Using the Mobile Media API that is specified in JSR 135 (plays within an application)
      • String url = "";
      • Player player = Manager.createPlayer(url);player.start();

    Advantages of streaming media over HTTP

    • API calls are simple to use.
    • This method hides many complex details.

    Limitations of streaming media over HTTP

    • Raw data in the buffer cannot be accessed.
    • The data flow from the buffer to the media player cannot be controlled.
    • There is no seek() support prior to BlackBerry Device Software 5.0.
    • There is no access to the raw data stream.

    Advanced streaming media

    The Mobile Media API (JSR 135) defines advanced APIs that you can use to control media streaming and allow flexibility in development. These APIs can be found in the package.

    Components of advanced streaming media

    The following diagram illustrates the different components and classes that are involved in streaming media and the data flow between a remote media source and the media player.



    Source Media

    The media file that is located on a content server.


    Download Thread

    A thread that connects to the source media and downloads the media file to the media buffer.

    Media Buffer

    A circular byte buffer for storing downloaded data until it is sent to media player for playback.


    An instance of the class. The SourceStream acts as an input stream for the media player by providing methods such as read() and seek().


    An instance of the DataSource class, and performs the following procedure:

    1. Open a connection to the remote source media.
    2. Start the download thread.
    3. Initialize and return SourceStream objects to play.
    4. Close the connection.


    An instance of The Player object plays media content as the content is downloaded. You can initialize a Playerobject by invoking source).



    The code sample that is included this article shows a complete implementation of all the components and classes that are mentioned. The code sample also includes a StreamingPlayer class and a StreamingPlayerListener interface that you can use as an API or extend to meet special use cases.

    Implementing the DataSource

    DataSource is an abstract class and has six methods. Each of the following methods is invoked by the Player object:


    public void connect()

    • Opens connections and input/output (I/O) streams

    public void disconnect()

    • Closes connections, I/O streams, and so on

    public String getContentType()

    • Returns the content type of the source media

    public SourceStream[] getStreams()

    • Returns SourceStream objects

    public void start()

    • Starts the download thread and begins downloading data

    public void stop()

    • Stops downloading data

    Implementing the SourceStream

    public ContentDescriptor getContentDescriptor()

    • Returns a ContentDescriptor object based on the content type of the media

    public long getContentLength()

    • Returns the content length.

    public int getSeekType()

      • Allows the Player to seek to nearby locations from the current position. SourceStream RANDOM_ACCESSIBLE must be set because video files can have audio and video at different offsets for each frame and the BlackBerry Device Software requires both for smooth playback. If -1 is returned by getContentLength(), the seek calls will only be to a previous position in the media file.

    public int read(byte[] b, int off, int len)

    • Sends data to the Player.
    • Blocks or resumes the feed,depending on the status of the buffer

    public long seek(long where)

    • Called by the Player to seek to a point between 0 and the content length
    • Implementation varies based the following connection types:
    • HTTP streaming
      • Uses this method only if seek() is feasible.
      • seek() point is within the buffered data. Otherwise, return the current position.
    • FileConnection streaming
      • Uses this method with mark()reset() and skip()

    public long tell()

    • Returns the current position in the stream

    How to handle user-initiated seek()

    There are two types of user-initiated seek calls. In both cases, Player.setMediaTime(long microseconds) must be invoked, which in turn position).

    • Seek calls within available data
      • Invoke seek() within the buffer using mark()reset() or skip()
    • Seek calls beyond the data that is available
      • Block the feed to the Player.
      • Stop downloading data.
      • Close the HTTP connection.
      • Reopen the connection using the HTTP range header to get data from the seek position.
      • Start downloading using the new connection.
      • Resume the feed to the Player when buffer contains enough information.

    Stream control

    Because media is streaming over a wireless network, there must be a mechanism to stop data feed to the Player when the buffer runs out of space due to of network delay. There must also be a way to determine how much of the buffer should be filled before restarting or resuming playback. Downloaded data in the buffer must be held as long as possible to allow for backward seek calls made by the Player, but when buffer is full the data must be discarded to download more data. You can use the following variables to control the feed to the Player:

    1. initialBufferDetermines how much data to buffer before playback starts for the first time. This variable can be determined dynamically by the following criteria:
      • Connection type
      • Bit rate
      • Bandwidth and latency
    2. restartThresholdDetermines when to resume the data feed to the Player based on the data that is available in the buffer. This variable can be determined dynamically by the following criteria:
      • Connection type
      • Bit rate
      • Bandwidth and latency
    3. bufferCapacityDetermines the size of the buffer where data is stored. This variable can be determined dynamically by the following criteria:
      • Connection type
      • Bit rate
      • Bandwidth and latency
      • If a buffer is too small, it can frequently run out of space.
      • If a buffer too big, it can waste system resources.
    4. bufferLeakSizeVideo playback requires the Player to seek back from the current position because audio and video data for the same frame are at different offsets. To accommodate this situation, downloaded data is stored until the Player is at the end of the buffer and the buffer is full. This method requires that more data must be downloaded for the playback to continue. In this situation, the oldest data is discarded first to create space for downloading more data.bufferLeakSize determines how much data is discarded each time this occurs.

    Creating a Player from a DataSource

    To create a Player from a DataSource, use the following code:

    Player player = Manager.createPlayer(new MyDataSource());player.start();


    Using the right transport method

    Wi-Fi® technology is the preferred transport because it is fast and free. If a Wi-Fi connection becomes available during a streaming session, it is recommended that the Player dynamically switch to the Wi-Fi connection after prompting the BlackBerry smartphone user to do so. If a Wi-Fi connection is not available, transport methods that are used by wireless service providers, such as Wireless Application Protocol (WAP/WAP2) or Transmission Control Protocol (TCP), are recommended. Using the BlackBerry® Mobile Data System (BlackBerry MDS) or the BlackBerry® Internet Service is not recommended because media streaming results in large data usage through these transport methods. Both the BlackBerry MDS and BlackBerry Internet Service also result in added latency because the data travels through the BlackBerry® Infrastructure.


    A complete implementation of a streaming media application is available to download. This example application uses the StreamingPlayer class andStreamingPlayerListener class as libraries, and can be used in your application to stream media over HTTP. This application will only play the media files that are supported by the target BlackBerry smartphone. Make sure that you type the web page and content type of your media file on the Options screen of the application before pressing play.


    Note: The API needs an implementation of a thread safe Circular Byte Buffer. You can copy the implementation as to package and then complile the project. For an example, click here.



    Refer to attachment section below to download the example application, including the libraries.





  • Copyright © 1996-2010 All rights reserved.
    iDream theme by Templates Next | Powered by WordPress