Saturday, April 25, 2009

How To : Access device event log on Storm 4.7

1 comments

How To Your BlackBerry's Event Log displays your system's recently run events and processes. If you're experiencing a problem with your BlackBerry or having an issue with a specific application or service, information from the Event Log can be helpful for troubleshooting. And it can be a good BlackBerry hygiene to clear out the log, to keep your device running smoothly.

To delete your list of events, hit the BlackBerry MENU key while any event is highlighted and then click "Clear Log." A dialogue box will then pop up asking if you're sure you want to delete the log. Once you confirm the deletion, your log will be cleared.

To access your Event Log on BB Storm 4.7 simulator, Press and hold the "?123" key to lock the numeric keyboard, the press ", 5 , 5"     ie.(comma 5 comma 5)

To access your Event Log in your bb device, go to your Home Screen, hold down the ALT key and then type "LGLG."

Thursday, April 23, 2009

Code : Create your own VirtualKeyboard for BBStorm

4 comments

Problem :

Code using component pack 4.7.0.39 and the Storm simulator 2.11.0.72. I have created an EditField with the FILTER_REAL_NUMERIC flag (and no other flags) and when the field has focus the virtual keyboard pops up as expected but it is missing the number '1'. I didn't add any other filters to the field.

Missing number 1

I have another EditField using the FILTER_NUMERIC flag instead, and it works fine. It seems that for real numbers it just replaces the '1' with the '.' key and leaves no way to insert that number, and if i tilt the simulator sideways the full keyboard is shown and this one has all the numbers.

Solution :

Well I have finally resolved this by developing my own home grown virtual keyboard.  This should work until RIM fixes the bug with their virtual keyboard.  In case anyone else is having the same problem, I have provide the code for it here:

 

public class MyVirtualKeyboard extends VerticalFieldManager
{
    // 1---2---3
    // 4---5---6
    // 7---8---9
    // .---0---c
    private ButtonField[] numbers = new ButtonField[]
    {
        new ButtonField("1", ButtonField.CONSUME_CLICK),
        new ButtonField("2", ButtonField.CONSUME_CLICK),
        new ButtonField("3", ButtonField.CONSUME_CLICK),
        new ButtonField("4", ButtonField.CONSUME_CLICK),
        new ButtonField("5", ButtonField.CONSUME_CLICK),
        new ButtonField("6", ButtonField.CONSUME_CLICK),
        new ButtonField("7", ButtonField.CONSUME_CLICK),
        new ButtonField("8", ButtonField.CONSUME_CLICK),
        new ButtonField("9", ButtonField.CONSUME_CLICK),
        new ButtonField(".", ButtonField.CONSUME_CLICK),
        new ButtonField("0", ButtonField.CONSUME_CLICK),
        new ButtonField("c", ButtonField.CONSUME_CLICK),
    };
    private ButtonField close = new ButtonField("Close",
        ButtonField.CONSUME_CLICK);
    private FieldChangeListener listener = new FieldChangeListener()
    {
        public void fieldChanged(Field f, int ctx)
        {
            if (ctx == FieldChangeListener.PROGRAMMATIC)
                return;
            String val = ((ButtonField) f).getLabel();
            if (Character.isDigit(val.charAt(0)) || val.equals("."))
                caller.setCharacter(val);
            else if (val.equals("c"))
                caller.removeLastCharacter();
        }
    };
    private Caller caller;
    public MyVirtualKeyboard(Caller caller)
    {
        this.caller = caller;
        // 4 rows of buttons will be displayed
        int buttonIndex = 0;
        for (int i = 0; i < 4; i++)
        {
            HorizontalFieldManager row = new HorizontalFieldManager();
            for (int j = 0; j < 3; j++)
            {
                numbers[buttonIndex].setChangeListener(listener);
                row.add(numbers[buttonIndex++]);
            }
            add(row);
        }
        close.setChangeListener(new FieldChangeListener()
        {
            public void fieldChanged(Field field, int ctx)
            {
                MyVirtualKeyboard.this.caller.closeMe();
            }
        });
        add(close);
    }
}

Here is the interface I created callled 'Caller':

public interface Caller
{
    public void closeMe();
    public void setCharacter(String character);
    public void removeLastCharacter();
}

 

Here is how I invoke it (this code is in my MainScreen subclass, which is implementing FocusChangeListener and my call back interface Caller):

public void focusChanged(Field field, int ctx)    {
        currentlyEditing = null;
        if (field != checkAmt && field != taxAmt)
            return;
        if (ctx == FocusChangeListener.FOCUS_GAINED)
        {
            currentlyEditing = (BasicEditField) field;
            MyVirtualKeyboard keyboard = new MyVirtualKeyboard(this);
            popup = new PopupScreen(keyboard);
            getUiEngine().pushScreen(popup);
        }
    }

Here is the callback methods on the main screen class that take the input from the popup keyboard:

public void setCharacter(String character)
    {
        String currText = currentlyEditing.getText();
        currText += character;
        currentlyEditing.setText(currText);
    }
    public void removeLastCharacter()
    {
        String currText = currentlyEditing.getText();
        if (currText.length() == 0)
            return;
        currentlyEditing.setText(currText.substring(0, currText.length() - 1));
    }

  public void closeMe()
    {
        getUiEngine().popScreen(popup);
    }

Also, I have a menu item where if the user needs to display the keyboard, they can:

showKeyboard = new MenuItem("Show Keyboard", 3, 12)       {
            public void run()
            {
                MyVirtualKeyboard keyboard = new MyVirtualKeyboard(
                    MyScreen.this);
                popup = new PopupScreen(keyboard);
                getUiEngine().pushScreen(popup);
            }
        };

 

Enjoy!

Monday, April 20, 2009

What Is - Best practices for designing GPS apps on CDMA networks

1 comments

What Is The BlackBerry 8130 smartphone, BlackBerry 8330 smartphone and BlackBerry 8830 smartphone use the Qualcomm gpsOne chipset. This chip can operate in several modes, some of which are quite different than the modes supported by BlackBerry smartphones operating on the Global System for Mobile communications (GSM) network.

This article explains the modes supported by BlackBerry smartphones operating on the Code Division Multiple Access (CDMA) network and the best practices for writing location-based services applications for the Qualcomm gpsOne chip.

Modes

Depending on the criteria set by an application, a Qualcomm gpsOne chip can be in any of the following modes:

Standalone

  • MS (Mobile Station or Device) operates in standalone-only mode
  • No network or Position Determination Entity (PDE) for position-location-related activity
  • Data demodulation (if required) occurs without an ephemeris download from the PDE
  • Recommended for outdoor use only; requires a clear view of the sky
  • Time To First Fix (TTFF) can be affected by cloud cover and/or urban canyons

MS-based

  • MS-operation in MS-based mode
  • Only seed position is calculated using MS-assisted mode
  • Suitable for applications requiring frequent fixes
  • Operates outdoors and indoors with a partial view of the sky

MS-assisted

  • MS operates in MS-assisted/PDE-based position calculation mode only
  • No MS-based position location fixes for the active sessions
  • No ephemeris downloads from PDE and no data demodulation
  • Suitable for single fixes

Note: Applications that need frequent fixes should not operate in this mode because this may result in data charges from the wireless service provider

  • Operates anywhere with a network connection

There are three more modes that use a combination of MS-Based and MS-Assisted to achieve a location fix.

Speed optimal

  • MS-based position calculation is preferred
  • PDE-based fix/MS-assisted mode is done only if MS-based position calculation fix fails
  • Ephemeris download from PDE is preferred as compared with data demodulation

Accuracy optimal

  • PDE-based position calculation/MS-assisted mode is a preferred option MS-based position calculation only if PDE-based fix failsEphemeris download from PDE is preferred as compared with data demodulation

Data optimal

  • Standalone mode is the preferred option and minimum PDE/network access is allowed
  • Data demodulation is preferred as compared with ephemeris download from PDE
  • MS-assisted position fix if MS-based position calculation fails to generate a fix
  • Data optimal mode disables SA download

Finally, another mode that simply returns the location of the cellular transmission site in contact with the BlackBerry smartphone is known as CellSite. This mode is not part of Qualcomm gpsOne but is worth mentioning. Accuracy of this mode is obviously low: 400m to 2500m in urban areas and will vary by location. CellSite is recommended when accuracy is of least concern.

Java Specification Request (JSR) 179 and Qualcomm gpsOne

JSR179 (also know as Location application programming interface [API]) includes the necessary APIs to use location-based services capabilities of a BlackBerry smartphone. The most important class in JSR179 is the LocationProvider, which is used to obtain location data from the Global Positioning System (GPS) module. An instance is obtained by calling LocationProvider.getInstance(Criteria c). Depending on the Criteria object, the API returns a LocationProvider in one of the above-mentioned modes. It is important to understand what criteria results in which mode. The following table can be used as a reference to determine the mapping between different sets of criteria and Qualcomm gpsOne modes.

Set Horizontal Accuracy()

Set Vertical Accuracy()

Is Allowed To Cost()

set Preferred Power Consumption()

set Preferred Response Time()

Frequency of fix in set Location Listener()

Mapped to QOS > Accuracy threshold

meters

not allowed

not applicable

any

single/multiple

not required

not required

not allowed

medium, high or no requirement

any

single/multiple

not required

not required

allowed

medium, high or no requirement

any

single/multiple

Mapped to QOS > Accuracy threshold

meters

allowed

High

Mapped to QOS > performance

multiple

Mapped to QOS > Accuracy threshold

meters

allowed

medium or no requirement

Mapped to QOS > performance

multiple

Mapped to QOS > Accuracy threshold

meters

allowed

High

Mapped to QOS > performance

Single

Mapped to QOS > Accuracy threshold

meters

allowed

medium or no requirement

Mapped to QOS > performance

Single

Mapped to QOS > Accuracy threshold

meters

allowed

medium or no requirement

QOS == Zero

Single

not required

not required

allowed

low

any

any

Based on the preceding table, the following algorithm is used in the BlackBerry smartphone API implementation:

-if costAllowed = FALSE, mode is standalone
-else if costAllowed=TRUE,
       -if (Sprint or Bell), mode is MS-Based
       -if horizontalAccuracy = 0, mode is Data Optimal
       -if horizontalAccuracy > 0,
             -if multipled fixes requested,
                   -if Telus, mode is MS-based
                   -otherwise,
                         -if powerUsage = HIGH, mode is Speed Optimal;
                         -if powerUsage != HIGH, mode is MS-based
             -else if single fix requested,
                   -if powerUsage = HIGH, mode is Accuracy Optimal;
                  -if powerUsage != HIGH, mode is PDE Calculate
                   -if powerUsage = MEDIUM and preferredResponseTime = 0,
                         mode is AFLT
                   -if powerUsage = LOW mode is Cellsite

Note: Verizon does not support the Standalone mode. For BlackBerry Device Software 4.7 and later, Standalone mode is open to applications that are signed by Research In Motion.

The following is an example obtaining a LocationProvider instance in Standalone mode:

Criteria c = new Criteria();
c.setCostAllowed(false);
LocationProvider provider = LocationProvider.getInstance(c);

Once a LocationProvider instance is obtained, read the location information from the BlackBerry smartphone. There are two ways to read location information from the BlackBerry smartphone:

  1. Call LocationProvider.getLocation(int timeout). If this method is used, a single fix will be returned. The timeout parameter is specified in seconds. A value of -1 indicates that the implementation should use its default timeout value for this provider.

Location loc = provider.getLocation(100);

This method is strongly recommended when frequent fixes are not required.

  1. Implement a LocationListener. To obtain multiple fixes at fixed intervals, implement the LocationListener interface of JSR179. This interface has the following two methods:
    1. locationUpdated(LocationProvider provider,Location location)

Called by the LocationProvider that this listener is registered to. This method will be called periodically according to the interval defined when registering the listener to provide updates of the current location. The provider parameter is the source of the event. The location parameter is the Location object that contains location information of the new fix.

    1. providerStateChanged(LocationProvider provider, int newState)

Called by the LocationProvider that this listener is registered to, if the state of the LocationProvider has changed. The value of the newState parameter can be xLocationProvider.AVAILABLE, LocationProvider.OUT_OF_SERVICE or LocationProvider.TEMPORARILY_UNAVAILABLE.

After implementing a LocationListener , an instance must be created and registered with a LocationProvider object. To register a LocationListener instance, call LocationProvider.setLocationListener(LocationListener listener, int interval, int timeout, int maxAge). The parameters are defined as follows:

    • listener - The LocationListener instance to register
    • interval - The interval in seconds to obtain location data
    • timeout - The timeout value in seconds
    • maxAge - The maximum age of the returned location in seconds

-1 can be passed to use the default value for the interval, maxAge and timeout parameters. The following code demonstrates how to register a LocationListener with default values:

LocationListener locListener = new LocationListenerImpl();
provider.setLocationListener(locListener, -1, -1, -1);

Once a LocationListener is registered, the locationUpdated method should be called automatically at the defined interval.

Provider states

As stated in the preceding text, the system automatically updates the state of a LocationProvider by calling the providerStateChanged() method of the registered LocationListener. The following description indicates how these status codes are interpreted in the BlackBerry smartphone API implementation:

  • TEMPORARILY_UNAVAILABLE - The GPS chipset has stopped looking for a fix. LocationProvider will no longer provide a fix to the application.
  • OUT_OF_SERVICE - Indicates when there is an IT Policy sent to the BlackBerry smartphone to disable GPS.
  • AVAILABLE - Never sent to the application.

Setting up PDE information

CDMA wireless service providers usually provide a PDE server which helps the BlackBerry smartphone in obtaining and computing location information.

Note: All Qualcomm gpsOne modes, except StandAlone and Cellsite, require a connection to a PDE server. To enable a connection to a PDE server, the Internet Protocol (IP) address and the port of the server must be configured using GPSSettings.setPDEInfo(String ip, int port). The following is an example:

// You must replace these values with values provided by your carrier.
GPSSettings.setPDEInfo("127.0.0.1", 80);

Resetting the LocationProvider

A LocationProvider may stop returning fixes when network coverage deteriorates or the BlackBerry smartphone is in an environment that is not suitable for receiving GPS data (for example, indoors). In these scenarios, the GPS chip will go completely cold to preserve battery power and throw a TEMPORARILY_UNAVAILABLE event by calling providerStateChanged()of the registered LocationListener instance. If this event is triggered, an application can reset the provider to restore the GPS chip. The following code demonstrates how to reset a LocationProvider:

provider.setLocationListener(null, 0, 0, 0);
provider.reset();
provider = null;
provider = LocationProvider.getInstance(criteria);
provider.setLocationListener(new LocationListenerImpl(),interval, timeout, maxAge);

After a reset, the application can try to get a fix again; however, if the GPS chip fails to get a fix (if the network coverage or environment has not improved), it will again go cold and will stop getting fixes. It is expected that the application will decide when to reset the provider. It is strongly recommended not to reset the provider at an interval less than three minutes since it can take up to three minutes to get a fix from a cold start.

Note: In some BlackBerry Device Software versions, the TEMPORARILY_UNAVAILABLE state was not always triggered as appropriate. In these cases, it is a good practice to keep track of the timestamp of the last valid fix and to reset the provider if the last valid fix is more than three minutes old.

Keeping the GPS chip ‘hot’

The GPS chip is considered ‘hot’ when it has an active connection with the satellites. A fix can be obtained almost instantly when the chip is hot. To preserve battery power, the chip is configured to go cold if the application does not ask for fixes for some time. From a cold start it may take much longer to get a fix. For applications that require frequent fixes, it is recommended that the application queries for fixes every 10 seconds. Therefore, the LocationListener should be registered with an interval of less than or equal to 10 seconds.

Setting up Verizon credentials

Verizon requires third-party applications to have a valid Client ID and Password for their Location Proxy Server (LPS) to access the Location API. To obtain these credentials, contact Verizon. Verizon credentials can be set in an application by calling GPSSettings.setPDEInfo(String ip, int port) as follows:

GPSSettings.setPDEInfo(";"+clientID+";"+password, 0);

A sample application that implements all the recommendations of this article can be found here.

Tuesday, April 14, 2009

Support : A Field’s font is displayed incorrectly when set in the paint method

0 comments

Support Problem

The Field.setFont(Font font) method should be used to set or change the font used by any field in the BlackBerry API set. A font should not be set or changed within the Field’s paint method. The following code example will NOT work:

LabelField myField = new LabelField("Hi there.")
{
   public void paint(Graphics graphics)
   {
      graphics.setFont(graphics.getFont().derive(Font.BOLD));
      super.paint(graphics);
   }
}

Resolution

The Field’s setFont method should be used in the following way:

LabelField myfield = new LabelField("Hi there.")
myField.setFont(myFont);

This allows for the font used within a specific field to be set. To change a font for the entire application, the Font.setDefaultFont(Font font) method should be used.

Note: This does not mean that the Graphics.setFont method should not be used. If you are performing custom drawing actions using the Graphics class on a custom Screen or Field, the setFont method can be used to change the font that is being drawn. Graphics.setFont should not be used to change the font being drawn by existing fields contained within the BlackBerry API set. Under this circumstance, the Field.setFont method should be used.

Wednesday, April 8, 2009

How To : Change fonts in a BlackBerry application

5 comments

How To The BlackBerry device supports multiple fonts in various sizes. These fonts can be used in custom BlackBerry applications and can be changed during runtime. The number of fonts available on a device depends on the model and the BlackBerry Device Software version installed.

The following example illustrates how to use fonts in a custom BlackBerry application and change the font during runtime:

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.*;
public final class FontChange extends UiApplication
{
    private Font font;
    //Get all fonts available on the BlackBerry
    private FontFamily fontFamily[] = FontFamily.getFontFamilies();
    public static void main(String[] args)
    {
            FontChange theApp = new FontChange();
            theApp.enterEventDispatcher();
    }
    public FontChange()
    {
        MainScreen mainScreen;
        FontChangeListener fontChangeListener = new FontChangeListener();
        //Set the current font to the first in the font list.
        font = fontFamily[0].getFont(FontFamily.SCALABLE_FONT, 10);
        Font.setDefaultFont(font);
        mainScreen = new MainScreen();
        //Set the title of the mainscreen.
        LabelField title = new LabelField("Font Test Example",
            LabelField.ELLIPSIS | LabelField.USE_ALL_WIDTH);
        mainScreen.setTitle(title);
        ObjectChoiceField pickFont = new ObjectChoiceField("Select a font:",
            fontFamily, 0);
        pickFont.setChangeListener(null);
        pickFont.setChangeListener(fontChangeListener);
        mainScreen.add(pickFont);
        mainScreen.add(new SeparatorField());
        //RichTextField that displays text in the specified colour.
        RichTextField fontText = new RichTextField
            ("The quick red fox jumps over the lazy brown dog.")
        {
            public void paint(Graphics graphics)
            {
                //Change the colour of the text in the RichTextField to green.
                graphics.setColor(0x00008800);
                super.paint(graphics);
            }
        };
        mainScreen.add(fontText);
        //Display the main screen
        pushScreen(mainScreen);
    }
    //Create a custom FieldChangeListener that will change the current font
    //to what is selected in the ObjectChangeField.
    class FontChangeListener implements FieldChangeListener
    {
        public void fieldChanged(Field field, int context)
        {
            //If the ObjectCoiceField has changed
            if (field instanceof ObjectChoiceField)
            {
                //Get the new font selected in the ObjectChoiceField and set the
                //current font to match what is selected.
                ObjectChoiceField choiceField = (ObjectChoiceField)field;
                font = fontFamily[choiceField.getSelectedIndex()].getFont
                    (FontFamily.SCALABLE_FONT,10);
                Font.setDefaultFont(font);
            }
        }
    }
}

Friday, April 3, 2009

How To : Change the text color of a field

3 comments

How To You can change the color of text in a field for applications that are designed to run on a color BlackBerry device. When you define a field, you can choose a color that will not change during the life of the field. To allow a field's color to change dynamically, extend one of the existing fields, or create your own field.

Below are samples that utilize the RichTextField and change the color of the text in the field. The color in Example 1 below will stay the same for the life of the field. The code in Example 2 below allows the color to be programmatically set, or set to a random value.

Example 1

//RichTextField that displays text in the specified color.
RichTextField fontText = new RichTextField("This text will be green.")
{
    public void paint(Graphics graphics)
    {
        graphics.setColor(0x00008800);
        super.paint(graphics);
    }
};

Example 2

/**
* Custom Field - FontField
*
*/
import net.rim.device.api.ui.*;
import net.rim.device.api.system.*;
import net.rim.device.api.ui.component.*;
import java.util.*;
public class FontField extends RichTextField
{
    //Set the initial text color to black.
    private int color = 0x00000000;
    //Initialize the random number generator.
    private Random randColor = new Random();
    //Only one RichTextField contstructor in this sample for brevity.
    public FontField(String text)
    {
        super(text);
    }
    //Set the color of the text in this field.
    public void setColor(int newColor)
    {
        color = newColor;
    }
    //Get the current text color.
    public int getColor()
    {
        return color;
    }
    //Randomly generate a new text color.
    public void randomizeColor()
    {
        int r = Math.abs(randColor.nextInt()) % 255;
        int g = Math.abs(randColor.nextInt()) % 255;
        int b = Math.abs(randColor.nextInt()) % 255;
        color = (255<<24) | (r<<16) | (g<<8) | b;
    }
    //Set the foreground and then call paint method of the parent class.
    public void paint(Graphics graphics)
    {
        graphics.setColor(color);
        super.paint(graphics);
    }
}