Você está na página 1de 184

BlackBerry Tablet OS SDK for Adobe AIR

Version: 1.1.1
Development Guide

Published: 2011-09-04 SWD-1840131-1005031135-001

Contents
1 Overview of the BlackBerry Tablet OS SDK for Adobe AIR............................................................................... Developing Adobe AIR applications for BlackBerry Tablet OS.......................................................................... BlackBerry Tablet OS security architecture...................................................................................................... Accessing restricted functionality.............................................................................................................. Folders accessible by an application................................................................................................................. 2 Managing your application through the application life cycle......................................................................... Understanding the application life cycle.......................................................................................................... Saving the application state.............................................................................................................................. Responding to application deactivation and activation.................................................................................... Respond to deactivation and activation.................................................................................................... Responding to application window state......................................................................................................... Listen for a change in application window state....................................................................................... Responding to low memory conditions............................................................................................................ Respond to low memory conditions.......................................................................................................... Respond to low battery notifications............................................................................................................... Respond to low battery notifications........................................................................................................ 3 ActionScript APIs............................................................................................................................................... 4 Updating Flash Builder...................................................................................................................................... Configure updates for Flash Builder in a Mac environment............................................................................. Configure updates for Flash Builder in a Windows environment..................................................................... Check for updates to the BlackBerry Tablet OS plug-in.................................................................................... 5 Organizing your UI with containers.................................................................................................................. Placing a child component within a container flow.......................................................................................... Aligning a child component within a container flow........................................................................................ Adjusting the size of a child parallel to the container flow............................................................................... Adjusting the size of a child perpendicular to the container flow.................................................................... Docking a child component.............................................................................................................................. Using containers to design a simple layout...................................................................................................... Create a container..................................................................................................................................... Create the orientation handler function................................................................................................... Create and add subcontainers................................................................................................................... Add UI controls.......................................................................................................................................... Adjust the opposite size of UI components............................................................................................... Use spacers to define child layout............................................................................................................. 7 7 7 8 9 12 12 13 13 14 14 15 15 16 16 17 19 20 20 20 20 22 22 23 24 24 25 25 26 27 28 30 31 32

Code sample: Using containers to design a simple layout........................................................................ 6 Choosing a button for your application............................................................................................................ Create a toggle button...................................................................................................................................... Create a check box............................................................................................................................................ Code sample: Creating a check box.................................................................................................................. Code sample: Creating an icon button............................................................................................................. Create a label button........................................................................................................................................ Formatting the text on a label button.............................................................................................................. Format the label text for each button state.............................................................................................. Code sample: Formating the label text for each button state................................................................... Using the Toggleswitch class............................................................................................................................ Create a toggle switch............................................................................................................................... Code sample: Creating a toggle switch...................................................................................................... Create a segmented control............................................................................................................................. Code sample: Creating a segmented control.................................................................................................... Create a radio button group............................................................................................................................. Code sample: Creating a radio button group.................................................................................................... 7 Displaying data in lists....................................................................................................................................... Create a List...................................................................................................................................................... Code sample: Creating a list............................................................................................................................. Adding an item to a list..................................................................................................................................... Removing an item from a list............................................................................................................................ Updating an item in a list.................................................................................................................................. Create a tile list................................................................................................................................................. Code sample: Creating a tile list....................................................................................................................... Creating a section tile list.................................................................................................................................. Create a SectionDataProvider object........................................................................................................ Create a section tile list............................................................................................................................. Remove an item from a section tile list..................................................................................................... Code sample: Creating a section tile list calendar..................................................................................... Creating a custom list....................................................................................................................................... Create a custom cell renderer................................................................................................................... Apply a custom cell renderer to a list........................................................................................................ Code sample: Creating a custom cell renderer.......................................................................................... 8 Using the picker to implement complex lists.................................................................................................... Create and populate a DataProvider object for a picker..................................................................................

32 37 38 39 41 42 42 43 44 45 46 47 48 49 51 52 54 56 56 58 59 59 59 60 61 62 63 64 66 67 68 69 70 71 74 74

Create a picker.................................................................................................................................................. Update data in a picker..................................................................................................................................... Code sample: Creating a picker calendar.......................................................................................................... Code sample: Creating a picker clock............................................................................................................... 9 Providing feedback and activity status to the user........................................................................................... Create a progress bar........................................................................................................................................ Code sample: Creating a progress bar.............................................................................................................. Create an activity indicator............................................................................................................................... Code Sample: Creating an activity indicator..................................................................................................... Code sample: Creating a percentage bar.......................................................................................................... 10 Capturing variable input with a slider............................................................................................................... Create a volume slider...................................................................................................................................... Code sample: Creating a volume slider............................................................................................................ 11 Skinning your UI components........................................................................................................................... Change the default skin of a UI component..................................................................................................... Create a custom button skin class.................................................................................................................... Apply a custom button skin.............................................................................................................................. Code sample: Creating a custom button skin...................................................................................................

76 78 79 81 85 85 86 87 88 89 91 91 92 94 94 96 97 98

12 Capturing text input.......................................................................................................................................... 102 Create a text input field.................................................................................................................................... 102 13 Creating dialog boxes........................................................................................................................................ Customizing buttons in a dialog box................................................................................................................. Create a dialog box........................................................................................................................................... Code sample: Creating a dialog box.................................................................................................................. 14 Responding to events and gestures.................................................................................................................. Respond to an event......................................................................................................................................... Code sample: Detecting a swipe gesture event................................................................................................ Code sample: Detecting a multitouch gesture event....................................................................................... Code sample: Detecting a rotation gesture event............................................................................................ 15 Localizing your application and using resource bundles................................................................................... Creating a resource bundle............................................................................................................................... Localize an application...................................................................................................................................... Code sample: Localizing an application............................................................................................................ Load a resource bundle.................................................................................................................................... 104 104 105 107 108 109 110 112 113 115 115 117 119 120

Code sample: Loading a resource bundle......................................................................................................... 122 16 In App Payments............................................................................................................................................... License models.................................................................................................................................................. Registering digital goods with BlackBerry App World...................................................................................... Creating an application that sells digital goods................................................................................................ Set up the UI.............................................................................................................................................. Create a class to store the properties for your digital goods.................................................................... Retrieve and display a list of digital goods................................................................................................ Initiate a purchase..................................................................................................................................... Check for existing purchases..................................................................................................................... Code sample: Creating an application that sells digital goods.................................................................. Distributing digital goods.................................................................................................................................. Distributing digital goods from a content server....................................................................................... Testing your application................................................................................................................................... Live testing................................................................................................................................................. Creating a sandbox account...................................................................................................................... Download an application before you make it available for distribution................................................... 124 124 125 125 126 127 128 130 133 135 140 140 140 141 141 141

17 The blackberry-tablet.xml file........................................................................................................................... 143 18 Signing your application.................................................................................................................................... Assigning a version number to your application............................................................................................... Configure application signing and create debug tokens using the setup wizard in Flash Builder.................... Configure application signing manually in Flash Builder........................................................................... Configure application signing through a proxy server in Flash Builder..................................................... Sign your application in Flash Builder............................................................................................................... Configure application signing from the command line..................................................................................... Using a proxy server from the command line........................................................................................... Sign your application from the command line.................................................................................................. Package your application from the command line........................................................................................... Application Signing Errors................................................................................................................................. Attempt to rename [value1] to [value2] failed.......................................................................................... Code signing request failed because Application-Development-Mode in Manifest is present and is not set to false................................................................................................................................................. Code signing request failed because Common Name in developer certificate is not [value]................... Code signing request failed because this file has been previously signed................................................ Code signing request failed because Package-Author in Manifest is not set to [value]............................ Code signing request failed because value of Package-Name in Manifest is not allowed........................ 146 146 147 147 149 150 153 154 155 155 156 156 156 156 157 157 157

-cskpass and -csjpin must be specified if -register is specified.................................................................. cskpass required........................................................................................................................................ Developer certificate and private key not found in keystore or store password not supplied................. Incomplete certificate chain...................................................................................................................... Key associated with [value] not a private key........................................................................................... Keystore load: store password incorrect................................................................................................... keytool error: java.io.FileNotFoundException: certificate.p12 <Access is denied>................................... keytool error: java.io.IOException: Incorrect AVA Format........................................................................ keytool error: java.lang.Exception: Key pair not generated, alias <author> already exists....................... Missing parameter for [option_name] option........................................................................................... No BAR file or CSJ file specified................................................................................................................. No key name specified............................................................................................................................... No manifest............................................................................................................................................... Only one of -setup, -register, or -verify can be specified.......................................................................... Server is not responding............................................................................................................................ Unable to open BAR file............................................................................................................................. 19 Using debug tokens.......................................................................................................................................... Create a debug token manually using Flash Builder......................................................................................... Import a debug token using Flash Builder........................................................................................................ Install a debug token using Flash Builder.......................................................................................................... Create a debug token from the command line................................................................................................. Install a debug token from the command line.................................................................................................. Configure your application for use with a debug token from the command line............................................ 20 Backup and restore your code signing keys...................................................................................................... Back up code signing keys using Flash Builder.................................................................................................. Restore code signing keys using Flash Builder.................................................................................................. Back up code signing keys manually................................................................................................................. Restore code signing keys manually................................................................................................................. Default location for code signing keys..............................................................................................................

157 158 158 158 159 159 159 160 160 160 161 161 161 161 162 162 163 163 168 168 169 170 171 172 172 172 173 173 173

21 Retrieve the PIN of a BlackBerry tablet............................................................................................................ 174 22 Retrieving the IP address of the BlackBerry PlayBook tablet............................................................................ 175 23 Enable development mode............................................................................................................................... 176 24 Provide feedback.............................................................................................................................................. 177 25 Document revision history................................................................................................................................ 178

26 Legal notice....................................................................................................................................................... 180

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Overview of the BlackBerry Tablet OS SDK for Adobe AIR

The BlackBerry Tablet OS SDK for Adobe AIR lets you to create applications for the BlackBerry PlayBook tablet, which runs the BlackBerry Tablet OS. This SDK allows you to create Adobe AIR applications that leverage the Adobe AIR 2.5 runtime environment that is built in to the BlackBerry Tablet OS. The BlackBerry Tablet OS is a multitasking operating system built upon the reliability and power of QNX Neutrino RTOS. Designed specifically to run applications developed using Adobe Flash and Adobe ActionScript, the BlackBerry Tablet OS offers developers the opportunity to create new and compelling applications and games, or to simply adapt existing ones to a tablet platform. Adobe AIR applications are built upon Flash and ActionScript technologies commonly associated with web content. However, because they run in the Adobe AIR runtime environment rather than in a plug-in to a web browser, they function as standalone applications. Additional ActionScript APIs, for use only within the Adobe AIR runtime environment, allow your application to access to a richer set of functionality than browser-based applications. For more information about Adobe AIR application development, visit http://www.adobe.com/products/air/.

Developing Adobe AIR applications for BlackBerry Tablet OS


The BlackBerry Tablet OS SDK for Adobe AIR allows you to optimize your Adobe AIR applications for the BlackBerry Tablet OS. This SDK provides APIs that extend Adobe ActionScript 3.0 and allow you to develop applications that have the look and feel of native BlackBerry PlayBook tablet applications and take advantage of some of the unique features of the OS. These APIs provide some unique UI components and predefined skins and enable you to listen for events specific to the BlackBerry Tablet OS, such as a swipe down event from the top bezel (the touch-sensitive frame around the display area of the screen). The BlackBerry Tablet OS supports the Adobe AIR 2.5 mobile device profile. The Adobe AIR 2.5 mobile profile was developed to provide the critical improvements in performance and reduction in processor usage that were necessary to bring Adobe Flash based applications to mobile devices such as smartphones and tablets. APIs have been added to ActionScript 3.0 to allow Flash applications to access some of the functionality that is unique to mobile devices, such as access to accelerometer and geolocation information and support for touch and gesture events. The BlackBerry PlayBook tablet includes the Adobe AIR 2.5 runtime environment. Applications developed for this runtime should be fully functional on the BlackBerry PlayBook tablet with no additional development required, save for adjusting the application for the unique screen size of the tablet.

BlackBerry Tablet OS security architecture

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

The BlackBerry Tablet OS is a microkernel operating system. Microkernel operating systems implement the minimum amount of software in the kernel space to manage access to basic computing functions such as CPU access, memory management, and so on. Higher-level system services, such as socket communication and device drivers, run in the user space. By running higher-level services in the user space, the BlackBerry Tablet OS can manage processes in isolation from each other. This helps prevent damage to the kernel and other applications. The microkernel architecture of the BlackBerry Tablet OS enables the following features: The BlackBerry Tablet OS is designed to be tamper resistant. The kernel performs an integrity test when the OS starts. If the integrity test reveals damage to the kernel, the BlackBerry Tablet OS does not start. The BlackBerry Tablet OS is designed to be resilient. The kernel can restart a process without negatively affecting other processes. All applications run in the user space. The BlackBerry Tablet OS is designed to be secure. The kernel validates requests for system resources. An authorization manager evaluates requests from applications to access the capabilities of the BlackBerry tablet. For example, when an application requests access to the camera, the authorization manager displays a dialog box that specifies the capability requested, and gives the user the opportunity to grant or refuse access to that capability. The BlackBerry Tablet OS is designed to verify the authenticity of an application. All applications that run on a BlackBerry tablet must be signed by the RIM Signing Authority and a Developer Certificate. For more information about accessing the RIM Signing Authority, see Signing your application.

Accessing restricted functionality


The BlackBerry tablet has functionality that can capture rich information from its environment, like the GPS receiver, a microphone, and so on. To help protect against potentially malicious code, users must grant your application access to the functionality. If an application uses APIs that access restricted functionality, and the application does not request access to a device capability, the application fails. You should make sure you test your application's behavior for cases when a user denies the application access to a particular capability. You must specify the device capabilities required for your application by adding one action element per device capability to your blackberry-tablet.xml file. For more information about creating a blackberry-tablet.xml file, see The blackberry-tablet.xml file. The following table lists values for the action element. You can use these values to specify the capabilities and APIs that are that are required by your application: Value access_internet access_shared Capability Access remote resource by using a network connection Access the shared file system API Any API that accesses the Internet. The following APIs might require this permission if they try to access the shared directory:
flash.filesystem.FileStream flash.filesystem.File

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Value

Capability

API
flash.media.CameraRoll flash.media.CameraUI qnx.media.MediaControl flash.media.Sound qnx.system.Device.pin qnx.system.Device.serialNum ber flash.sensors.Geolocation flash.media.Microphone qnx.media.MediaControl flash.media.Camera flash.media.CameraUI

play_audio read_device_identif ying_information read_geolocation record_audio set_audio_volume use_camera

Access the audio controls Access the PIN and serial number of the tablet.

Access the current location of the tablet Access the audio stream from the microphone Access the volume control Access data from one or more cameras

Sample blackberry-tablet.xml file


<qnx> <icon> <image>my_icon.png</image> </icon> <author>My Company</author> <authorId>gYAAgIqK0RLL5u4I9NanyxBUuCI</authorId> <category>core.games</category> <splashscreen>img/spalsh_landscape.jpg:img/splash_portrait.jpg</splashscreen> <action>use_camera</action> <action>read_geolocation</action> <action>play_audio</action> <buildId>349</buildId> <platformVersion>1.0.0.0</platformVersion> </qnx>

Folders accessible by an application


The following table contains descriptions of the folders that an application can accesss. Each application has access to its own working directory in the file system, and might be able to access the shared folder. All path references in your application are relative to the root of the working folder. The Adobe AIR API property File.userDirectory maps to the root of the working folder.

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Folder app

Description This folder contains the files that were installed with your application. These files were packaged with you BAR file. Your application has readonly access to this folder. The Adobe AIR API property File.applicationDirectory maps to the folder app/air. This folder contains the application's private data. The application has full access to read and write files in this folder. The Adobe AIR API property
File.applicationStorageDirectory maps to this folder.

data

tmp

logs shared shared/bookmarks shared/books shared/clipboard shared/documents

This folder contains the application's temporary working files. The application should remove these files regularly. The BlackBerry Tablet OS might remove these files any time the application is not running. This folder contains system logs for an application. Stdin and stdout are redirected to this directory. This folder contains subfolders that contain shared data by type. An application cannot write to this directory. This folder contains web browser bookmarks that can be shared among applications. This folder contains eBook files that can be shared among applications. This folder contains data copied or cut from another application. This folder contains documents that can be shared among applications. The Adobe AIR API properties File.documentsDirectory and File.desktopDirectory map to this folder. This folder contains web browser downloads. This folder contains miscellaneous data that can be shared among applications. This folder contains music files that can be shared among applications. This folder contains photos that can be shared among applications. This folder contains videos that can be shared among applications. This folder contains audio recordings that can be shared among applications.

shared/downloads shared/misc shared/music shared/photos shared/videos shared/voice

10

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

11

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Managing your application through the application life cycle

The life cycle of an application refers to the stages that an application can move through, from the time it is invoked until it is terminated. It is important to understand the implications of the various states and transitions of the life cycle on your application so that you can respond to them appropriately in your code. The life cycle of your application normally has three stages: it starts, runs for a period of time, and then ends. The BlackBerry Tablet OS is a multithreaded, multitasking platform so it can run multiple applications at the same time. While your application is running in the foreground, it is active. However, it can be interrupted when another application opens and replaces yours as the active application. When your application loses focus it is not terminated, but it may be deactivated and pushed to the background. A background application can reactivatedreturned to the foregroundat any time, or may be closed by the user. The application may terminated by the system, without ever becoming active again. When an application needs to move from one stage of the lifecycle to another, the BlackBerry Tablet OS notifies the application using the Adobe AIR event system. The events that an application receives can vary if a user changes the Application behavior setting on the tablet. The following table lists the default events that the OS sends to an application to indicate a change in the application lifecycle. Lifecycle stage Application startup Foreground Background Exit Event Event.ACTIVATE Event.ACTIVATE Event.DEACTIVATE when another application receives the foreground Event.EXITING

During the application life cycle, other events might cause your application to terminate prematurely (that is, before the user has closed it). For example, when the battery drains, the tablet shuts down and closes all open applications. Alternatively, if a user has too many applications open, it could create a low memory situation. The BlackBerry Tablet OS handles low memory conditions by closing idle background applications so it can reclaim memory resources.

Understanding the application life cycle


The life cycle of an application refers to the stages that an application can move through, from the time it is invoked until it is terminated. It is important to understand the implications of the various states and transitions of the life cycle on your application so that you can respond to them appropriately in your code. In its simplest form, the life cycle of your application has three stages: it starts, runs for a period of time, and then ends. While the application is running in the foreground, it is active. While your application is running and active, it can be interrupted at any time, when another application opens and replaces yours as the active application. The BlackBerry Tablet OS is a multithreaded, multitasking platform. When your application loses focus it is not terminated, but is instead deactivated and pushed to the background; the application is still running, but it is no

12

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

longer the top application on the stack. A background application can be reactivatedthat is, returned to the foregroundat any time, or may be closed by the user, or occasionally terminated by the system, without ever becoming active again. During the application life cycle, other events might cause your application to terminate prematurely (that is, before the user has closed it). For example, when the battery drains, the tablet shuts down and closes all open applications. In addition, there are memory considerations that your application should account for. If, for example, a user has too many applications open, it could create a low memory situation. The BlackBerry Tablet OS handles low memory conditions by closing idle background applications so it can reclaim the necessary memory resources.

Saving the application state


Saving the application state ensures that when the user returns to the application, the application returns to the same condition it was in when it lost focus. A mobile application can experience a number of interruptions during its life cyclelosing application focus, change in application window state, low memory events, and low battery eventsthat must be managed. It is important that your application listen for these events and respond by saving the application state; any pertinent information about the current conditions of the applicationfor example, the screen element currently in focus, or any user-entered datacan be saved. When the user returns to the application, the saved state can be reloaded and the user can then continue on as before. The type of information you should save about the application state depends upon the application, and upon the likely expectations of your user. For example, for an e-reader application, the user might simply expect to return to the same page of the same book they were reading. In a text editor application or on a settings page, the user might expect that any text entered would still be available, even if those changes were not saved manually. In an interactive game, such as a driving game, you might save much more data about the state of the application. In each case, to decide what data to save and when to save it, you must first determine what data is necessary for the user to continue when the application is reloaded. It is also wise to save the application state after other significant events; for example, in a game application, you might save the state each time the user completes a level.

Responding to application deactivation and activation


The BlackBerry Tablet OS can deactivate your application and move it to the background at any time. For example, a user may leave your application to open another application. You should not assume that the user appropriately saved their activity in your application before the application moves to the background. When the OS deactivates your application, you should first save the application state. In addition, your application should stop any unnecessary processes (such as updating the UI in real-time) to preserve system resources. When the OS activates your application again, you can reload the saved state, and restart any suspended processes. By default, the NativeApplication object dispatches one of the following events when your application changes its stage in the lifecycle:

13

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Property
Event.DEACTIVATE Event.ACTIVATE

Description Dispatched when another application becomes the active application. Dispatched when the application becomes the active application.

Respond to deactivation and activation


1. 2. Import the required classes and interfaces.
import flash.events.*;

Set up event listeners to listen for the Event.DEACTIVATE and Event.ACTIVATE events.
NativeApplication.nativeApplication.addEventListener(Event.DEACTIVATE, onDeactivate); NativeApplication.nativeApplication.addEventListener(Event.ACTIVATE, onActivate);

3.

Define the callback function called when the application loses focus. This function should save the state of the application and stop any unnecessary processes.
public function onDeactivate(event:Event):void { // Save state // Suspend processes }

4.

Define the callback function called when the application regains focus. This function should save the reload the state of the application and restarted any processes that were stopped.
public function onActivate(event:Event):void { // Reload state // Restart processes }

Responding to application window state


The BlackBerry Tablet OS application window has three states that can be changed at any time. For example, a user may minimize an application to toggle to a new application or close it from the thumbnail view. Your application should listen for these changes in application window state and respond accordingly by, for example, saving the application state. In addition, your application should stop any unnecessary processes (such as updating the UI in real-time) to preserve system resources. When the OS activates your application again, you can reload the saved state, and restart any suspended processes. The IowWindowEvent class defines events that are associated with the change in application window state. Property
NORMAL

Description The application window is full screen on the device and is active.

14

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Property
THUMBNAIL HIDDEN

Description The application window is a thumbnail on the device and is not active. This happens when a user minimizes the application or is toggling between applications. The application window is not visible on the device. This happens when another application is currently full screen.

Listen for a change in application window state


1. 2. Import the required classes and interfaces.
import flash.events.*;

Set up an event listener to listen for a change in application window state.


var win:IowWindow = IowWindow.getAirWindow(); win.addEventListener(IowWindowEvent.WINDOW_STATE_CHANGED, stateChanged );

3.

Define a callback function called when the application window state has changed.
function stateChanged(event:IowWindowEvent):void { switch( win.state ) { case IowWindowState.NORMAL: trace( "Application is full screen" ); break; case IowWindowState.THUMBNAIL: trace( "App is minimized" ); break; case IowWindowState.HIDDEN: trace( "App is hidden" ); break; } }

Responding to low memory conditions


Low memory conditions occur most often when the user has many, memory intensive applications open and running in the background. Alternatively, applications might hold memory unnecessarily if they do not suspend processes when moved to the background. When the system runs low on memory, the BlackBerry Tablet OS attempts to reclaim resources by closing background applications. The OS attempts to close the application that been in the background the longest, and continues to close applications until it reclaims enough memory for normal system operation.

15

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

When the OS tries to terminate an application due to low memory, it terminates the application's processes and destroys the associated NativeApplication instance. However, the application window remains in the list of background applications. From the user's perspective, the application appears to be running in the background. When the user returns the application to the foreground, the OS restarts the application and creates a new instance of NativeApplication. When the system runs low on memory, the QNXApplication class dispatches the QNXApplicationEvent.LOW_MEMORY event. You should create a listener to process this event. When you receive a LOW_MEMORY event, your application should immediately save state, release resources, destroy its objects. This way the user's application data should be preserved if your application is terminated. If your application receives focus again, the user expects to return to the application in the state it was in when it was pushed to the background. Your application should detect whether it was terminated due to low memory, then load the saved state if appropriate.

Respond to low memory conditions


1. Import the required packages.
import qnx.system; import qnx.events;

2.

Set up an event listener to listen for the QNXApplicationEvent.LOW_MEMORY event.


QNXApplication.qnxApplication.addEventListener( QNXApplicationEvent.LOW_MEMORY, onLowMemory);

3.

Define the callback function called when a low memory event occurs.
public function onLowMemory(event:Event):void { // Save state // Release resources }

Respond to low battery notifications


1. Import the required packages.
import qnx.system.Device; import qnx.events.DeviceBatteryEvent;

2.

Define variables for the battery level and battery state.


public static var bLevel:int; public static var bState:int;

3.

Set the deviceBatteryMonitoring property to true to access the values for the battery level and state and then initialize the values of the bLevel and bState variables.

16

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Device.device.batteryMonitoringEnabled = true; bLevel = Device.device.batteryLevel; bState = Device.device.batteryState;

4.

Set up event listeners to listen for the DeviceBatteryEvent.LEVEL_CHANGE and DeviceBatteryEvent.STATE_CHANGE events.
Device.device.addEventListener(DeviceBatteryEvent.LEVEL_CHANGE, onLevelChange); Device.device.addEventListener(DeviceBatteryEvent.STATE_CHANGE, onStateChange);

5.

Define the callback methods for the event listeners. In the following code sample, the appropriate variable is updated to reflect the new level or state of the battery.
public function onLevelChange(evt:DeviceBatteryEvent):void { bLevel = evt.batteryLevel; evaluate(); } public function onStateChange(evt:DeviceBatteryEvent):void { bState = evt.batteryState; evaluate(); }

6.

Evaluate the new battery properties and respond as appropriate.


public function evaluate() { if( bState == DeviceBatteryState.UNPLUGGED || bLevel < 10) { // Save state displayWarning(); } }

Respond to low battery notifications


1. Import the required packages.
import qnx.system.Device; import qnx.events.DeviceBatteryEvent;

2.

Define variables for the battery level and battery state.


public static var bLevel:int; public static var bState:int;

3.

Set the deviceBatteryMonitoring property to true to access the values for the battery level and state and then initialize the values of the bLevel and bState variables.
Device.device.batteryMonitoringEnabled = true; bLevel = Device.device.batteryLevel; bState = Device.device.batteryState;

17

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

4.

Set up event listeners to listen for the DeviceBatteryEvent.LEVEL_CHANGE and DeviceBatteryEvent.STATE_CHANGE events.
Device.device.addEventListener(DeviceBatteryEvent.LEVEL_CHANGE, onLevelChange); Device.device.addEventListener(DeviceBatteryEvent.STATE_CHANGE, onStateChange);

5.

Define the callback methods for the event listeners. In the following code sample, the appropriate variable is updated to reflect the new level or state of the battery.
public function onLevelChange(evt:DeviceBatteryEvent):void { bLevel = evt.batteryLevel; evaluate(); } public function onStateChange(evt:DeviceBatteryEvent):void { bState = evt.batteryState; evaluate(); }

6.

Evaluate the new battery properties and respond as appropriate.


public function evaluate() { if( bState == DeviceBatteryState.UNPLUGGED || bLevel < 10) { // Save state displayWarning(); } }

18

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

ActionScript APIs

While the BlackBerry Tablet OS SDK for Adobe AIR extends the Adobe ActionScript API in many important areas, you must use the ActionScript 3.0 APIs for data storage, networking, and device sensor functions. The following table lists some resources that you can use to learn more about ActionScript APIs. You must explicitly request permission from your user to use device sensors. For more information, see Accessing restricted functionality. Component Data storage Description The BlackBerry Tablet OS supports the following approaches to data storage Local shared object (in the flash.net.SharedObject package) Encrypted local store (in the flash.data.EncryptedLocalStore package) File system (in the flash.filesystem package) SQLite (in the flash.data package) You can use the flash.net package to send and receive data over a network connection. You can use the flash.sensors.Accelerometer class to register an event listener for accelerometer events. The BlackBerry Tablet OS reports movement in three perpendicular planes relative to the device. You can use the flash.sensors.Geolocation class to register an event listener that processes changes in the geoposition of the device. For more information, see Detecting geolocation changes in the ActionScript 3.0 Developer's Guide.

Network communication Accelerometer

Geolocation

For more information, see the ActionScript 3.0 Reference for the Adobe Flash Platform.

19

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Updating Flash Builder

Configure updates for Flash Builder in a Mac environment


Before you can upgrade the BlackBerry Tablet OS SDK plug-in on Mac OS, you need to change an Adobe Flash Builder configuration file. The upgrade process reverts the file to its original state when the update is complete. You only need to change the configuration file the first time you upgrade the plug-in. Subsequent upgrades work normally without this task. Before you begin: Close Adobe Flash Builder before you edit the config.ini file described in the steps below. 1. 2. In a text editor, open the config.ini file in <Flash Builder Installation Directory>/eclipse/configuration folder. The default location of this file is /Applications/Adobe Flash Builder 4.5/eclipse/configuration/config.ini Put a number sign (#) before the osgi.configuration.area parameter.
#osgi.configuration.area=@user.home/Documents/Adobe Flash Builder 4.5/cascaded/ 308971/configuration

3. 4. 5. 6. 7.

Save the file and exit the text editor. In Adobe Flash Builder, on the Flash Builder menu, click Preferences. In the list of preference categories, expand Install/Update > Available Software Sites. In the list of available software sites, select the BlackBerry Tablet OS update site check box. Click OK.

Configure updates for Flash Builder in a Windows environment


1. 2. 3. 4. In Adobe Flash Builder, on the Window menu, click Preferences. In the list of preference categories, expand Install/Update > Available Software Sites. In the list of available software sites, select the BlackBerry Tablet OS update site check box. Click OK.

Check for updates to the BlackBerry Tablet OS plug-in


After you enable the update site in Adobe Flash Builder, you should see it in the list of available software update sites. If it does not appear in the list of update sites, you should add it manually. The update site is located at http:// www.blackberry.com/go/eclipseupdate/flashbuilder4.5 Before you begin: Register for access to the BlackBerry Developer Zone. 1. 2. In Adobe Flash Builder, on the Help menu, click Install New Software. On the Available Software screen, in the Work with drop-down list, click BlackBerry Tablet OS update site.

20

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

3. 4. 5. 6. 7. 8. 9.

If the list of available software is populated, expand the BlackBerry Tablet OS Support item. Select the BlackBerry Tablet OS Plugin for Adobe Flash Builder item. Click Next. On the Install Details screen, click Next. On the Review Licenses screen, accept or decline the license agreements. Click Next. On the Login required window, enter your BlackBerry Developer Zone login information. Click OK. On the Security Warning window, click OK or Cancel. On the Software Updates window, click Restart Now.

21

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Organizing your UI with containers


contain other containers, called subcontainers.

You can use the Container class to create a container to organize the UI components of your application. The Container class handles the positioning, size, and layout of any UI component that it contains. A container can also

Containers are also useful for resizing and laying out child components to respond to orientation changes. An orientation change occurs when the user tilts the device, such as when the user switches from portrait to landscape mode. A parent container refers to any container that contains one or more subcontainers. A child container refers to any container that is nested within a parent container. To understand how child components are arranged and sized within a parent container, you must understand the following concepts: Placing a child component within a flow Aligning a child within a flow Adjusting the size of a child parallel to the container flow Adjusting the size of a child perpendicular to the container flow Docking a child component

Placing a child component within a container flow


Container flow is the layout orientation and direction of all child components relative to the near edge of the parent container. A container can define two flow directions: vertical and horizontal. In a container with a vertical flow, the near edge is the top edge of the container. In a container with a horizontal flow, the near edge is the left edge of the container.The flow position is the position of a child component within the flow of a parent container. If a parent container's flow property is set to ContainerFlow.HORIZONTAL, the container's children (which may also be containers) will appear horizontally opposed, or side by side within the container.

If a container uses a vertical flow (ContainerFlow.VERTICAL) all subcomponents within this container will appear vertically-opposed, or one on top of another.The mySub container is show below.

22

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Components appear in the order in which you add them to a container, such that the top-most component in a container is the component that is first added to the container. This is always true unless a component is docked.

Aligning a child component within a container flow


The opposite position refers to the position of a child in the direction opposite to the flow of the container.You can define the opposite position of a child by setting the align property of the parent container. The align property determines the alignment of each subcomponent in the direction opposite to the flow of the container. In a container with a vertical flow, the align property specifies the horizontal position (x coordinate) of the subcomponent, relative to the left edge of the container. In a container with a horizontal flow, the align property specifies the vertical position (y coordinate) of the subcomponent relative to the top edge of the container. The align property has the following values: ContainerAlign.NEAR ContainerAlign.MID ContainerAlign.FAR Each value represents a position relative to the initial edge of the container. You can specify the ContainerAlign.NEAR property to place a subcomponent closest to the initial edge of a parent container. You can specify the ContainerAlign.FAR property to place a subcomponent furthest from the initial edge of the parent container. The ContainerAlign.MID value is the default. The following figure illustrates each align property in a single container. You can use the container's padding property to set the amount of space (in pixels) between each subcomponent.

23

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Adjusting the size of a child parallel to the container flow


Flow size refers to the size of a child component in the direction of the flow of the parent container. For example, the height of a button in a container with a vertical flow, or the width of a button in a container with a horizontal flow. The container sets the flow size for a child only if the child implements IContainable and the child's IContainable.size property is not 0. Otherwise, the child component's flow size is not changed during layout operations.

Adjusting the size of a child perpendicular to the container flow


Opposite size refers to the size of a child in the direction opposite to the flow of the parent container. For example, the height of a button in the container with a horizontal flow, or the width of a button in a parent container with a vertical flow.

24

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

The parent container will only resize a child component in the opposite direction if the child implements IContainable and IContainable.sizeMod is set to SizeMode.BOTH. When SizeMode.BOTH is set, any container alignment settings are ignored, and the opposite size for a child is set to fill the available remaining container space in the opposite direction. For an example of a component that implements opposite size, see Adjust the opposite size of UI components The following illustration shows the opposite size and flow size of subcomponents as it relates to the flow direction of a parent container.

Docking a child component


You can dock a child component to anchor it adjacent to any edge of the parent container. If a component implements IContainment, you can set its containment property to dock it to any edge of the stage. When a resize event occurs, all docked components are laid out first, in the order in which they are added to the parent. The remaining child objects are placed in the remaining container space.

Using containers to design a simple layout


You can use a simple hierarchy of parent and child containers to design an effective layout for your application. Creating an application layout that uses multiple containers and basic UI controls involves the following tasks: Create a container Create the orientation handler function Create and add subcontainers Add UI components Adjust the opposite size of UI components Use spacers to define child layout
25

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

The complete application is shown below. The sample application uses four simple containers, and some basic UI controls to define a wizard-like application layout:

Refer to Code sample: Using containers to design a simple layout for the complete sample application.

Create a container
You can create a single main container to hold all other UI components. In this task, you define the main container and add it to the stage. 1. Import the required classes.
import import import import import import import import import import flash.display.Sprite; flash.events.Event; flash.text.TextFieldAutoSize; flash.text.TextFormat; qnx.ui.buttons.LabelButton; qnx.ui.core.* qnx.ui.data.DataProvider; qnx.ui.listClasses.List; qnx.ui.text.Label; qnx.ui.text.TextInput;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frrate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class ContainerTest extends Sprite {

4.

Create the main container variable.


private var myMain:Container;

26

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

5.

Create a constructor for your class, and invoke initializeUI().


public function ContainerTest() { initializeUI(); }

6.

Create the function initializeUI. The initializeUI function sets up the UI components that are used by the application.
private function initializeUI():void {

7.

In the initializeUI function, instantiate the main container.


myMain = new Container();

8.

In the initializeUI function, set the debug color to a hexadecimal color value. The debugColor property is useful for visualizing the bounds of each container while you develop your application. Each container can use a different color value to allow you to tweak the details of the layout.
myMain.debugColor = 0xFFCC00;

9.

A component will only overlap a margin if the container runs out of space. The margin values are specified using literals, however, it's a good idea to use variables to allow you to change a container's margins at run time. The myMain container's flow property is set to ContainerFlow.HORIZONTAL to specify that the container's children (which may also be containers) will appear horizontally-opposed, or side-by-side within the container.
myMain.margins = Vector.<Number>([20,20,20,20]); myMain.flow = ContainerFlow.HORIZONTAL;

In the initializeUI function, set the margins and the flow for the container. The margins property takes a Vector of four numbers indicating, in order, margins for the left, top, right, and bottom edges of the container.

10. In the initializeUI function, add the container to the stage.


} addChild(myMain);

Create the orientation handler function


When the user re-orients the device by switching from landscape mode to portrait mode, the StageOrientationEvent.ORIENTATION_CHANGE system event is dispatched and the stage.width and stage.height device properties are swapped. You must set up an event listener to capture the StageOrientationEvent.ORIENTATION_CHANGE event in order to rotate and resize your application. In this task, you create an event listener and a function to handle device orientation changes. Before you begin: Create a container 1. Import the required classes

27

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

import flash.events.StageOrientationEvent; import flash.display.StageAlign; import flash.display.StageScaleMode;

2.

Create the onReorient function and add the call to setSize. The setSize method calls the layout function which adjusts the layout of the subcomponents according to the properties that are defined by each parent container. Call this method only after each container and each subcomponent is defined and added to the display list. Otherwise, the call will have no effect.
private function onReorient(event:StageOrientationEvent):void { myContainer.setSize(stage.stageWidth, stage.stageHeight); }

3.

In the constructor for your class, create an event listener to handle stage events. In the code sample below, an event is dispatched whenever a UI component is added to the stage.
addEventListener(Event.ADDED_TO_STAGE, handleAddedToStage);

4.

Create the handleAddedToStage. This function is called by the event listener every time an item is added to the stage. The handleAddedToStage function creates an event listener to listen for reorientation events that occur whenever the user changes the orientation of the device. When an StageOrientationEvent.ORIENTATION_CHANGE event is detected, the onReorient function is called. The handleAddedToStage function then explicitly calls the onReorient function.
private function handleAddedToStage(e:Event):void { removeEventListener(Event.ADDED_TO_STAGE,handleAddedToStage); stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; stage.addEventListener(StageOrientationEvent.ORIENTATION_CHANGE, onReorient); onReorient(new StageOrientationEvent(StageOrientationEvent.ORIENTATION_CHANGE,true,true)); }

Create and add subcontainers


You can add multiple subcontainers to a parent container. Each subcontainer can use a distinct debug color. This task demonstrates how to add three subcontainers, as shown in the diagram.

28

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Before you begin: Create the orientation handler function 1. In the body of the class, add the variables for three subcontainers: mySub, mySubRight, and mySubBottom.
private var mySub:Container; private var mySubRight:Container; private var mySubBottom:Container;

2.

In the initializeUI function, create the first subcontainer: mySub. The mySub container uses a vertical flow (ContainerFlow.VERTICAL) meaning that all components within this container will appear vertically. The size and sizeUnit properties determine the size of the subcontainer. In the following code sample, size is set to 50 and sizeUnit is set to SizeUnit.PERCENT indicating that mySub will take up 50% of the main container. The default value of sizeUnit is SizeUnit.PIXELS.
mySub = new Container(); mySub.debugColor = 0xFF3300; mySub.margins = Vector.<Number>([20,40,20,40]); mySub.flow = ContainerFlow.VERTICAL; mySub.padding = 10; mySub.size = 50; mySub.sizeUnit = SizeUnit.PERCENT; mySub.align = ContainerAlign.NEAR;

3.

In the initializeUI function, create the second subcontainer: mySubRight.The mySubRight subcontainer takes up the right-side of the stage.
mySubRight = new Container(); mySubRight.margins = Vector.<Number>([10,10,10,10]); mySubRight.size = 50; mySubRight.debugColor = 0x0033FF; mySubRight.sizeUnit = SizeUnit.PERCENT; mySubRight.flow = ContainerFlow.VERTICAL; mySubRight.align = ContainerAlign.MID; mySubRight.padding = 10;

29

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

4.

In the initializeUI function, create the third subcontainer: mySubBottom. Set the containment property to Containment.DOCK_BOTTOM. Docked children are handled first in layout operations. You can dock a subcomponent to any of the four edges of a container, in the background of the stage (Containment.BACKGROUND), or you can specify that the component is not repositioned by the parent container (Containment.UNCONTAINED).
mySubBottom = new Container(); mySubBottom.margins = Vector.<Number>([5,5,5,5]); mySubBottom.debugColor = 0x33FF33; mySubBottom.size = 12; mySubBottom.sizeUnit = SizeUnit.PERCENT; mySubBottom.flow = ContainerFlow.HORIZONTAL; mySubBottom.align = ContainerAlign.FAR; mySubBottom.containment = Containment.DOCK_BOTTOM;

5.

In the initializeUI function, add the subcontainers to the main container. The mySub and mySubRight containers are added to the stage first, but not positioned. The third subcontainer, mySubBottom is added and docked to the bottom of the main container. It is positioned first leaving the remainder of the stage for the other two subcontainers.
myMain.addChild(mySub); myMain.addChild(mySubRight); myMain.addChild(mySubBottom);

Add UI controls
You can add UI controls to each of the subcontainers. Before you begin: Create and add the subcontainers. 1. In the body of the class, add the UI control variables.
private private private private var var var var firstLabel:Label; secondLabel:Label; thirdLabel:Label; fourthLabel:Label;

private var firstInput:TextInput; private var leftButton:LabelButton; private var rightButton:LabelButton;

2.

In the initializeUI function, create and add the UI components.


var labelFormat:TextFormat = new TextFormat(); labelFormat = new TextFormat(); labelFormat.size = 22; firstLabel = new Label(); firstLabel.format = labelFormat; firstLabel.text = "First label";

30

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

firstLabel.size=35; firstLabel.sizeUnit = SizeUnit.PERCENT; firstLabel.autoSize = TextFieldAutoSize.LEFT; mySub.addChild(firstLabel); secondLabel = new Label(); secondLabel.format = labelFormat; secondLabel.text = "Second label"; secondLabel.size=35; secondLabel.sizeUnit = SizeUnit.PERCENT; secondLabel.autoSize = TextFieldAutoSize.LEFT; mySub.addChild(secondLabel); thirdLabel = new Label(); thirdLabel.format = labelFormat; thirdLabel.text = "Third label"; thirdLabel.size=35; thirdLabel.sizeUnit = SizeUnit.PERCENT; thirdLabel.autoSize = TextFieldAutoSize.LEFT; mySub.addChild(thirdLabel);

3.

In the initializeUI function, create and add the mySubRight subcontainer's UI components. Add a spacer to the container before the first label is added. The spacer provides padding above the label.
firstInput = new TextInput; firstInput.width = 200; fourthLabel = new Label(); fourthLabel.format = labelFormat; fourthLabel.text = "Fourth label:"; fourthLabel.width = 200; fourthLabel.size=30; fourthLabel.sizeUnit = SizeUnit.PIXELS; mySubRight.addChild(new Spacer(60)); mySubRight.addChild(fourthLabel); mySubRight.addChild(firstInput);

Adjust the opposite size of UI components


You can adjust the opposite flow size of a UI control by setting the SizeMode property. Before you begin: Add UI controls 1. In the initializeUI function, create a button. In the following code sample, the Back button specifies SizeMode.BOTH for its SizeMode property. After a layout call, the Back button will expand vertically (if the container uses a horizontal flow) to fill the space in the container.

31

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

leftButton = new LabelButton(); leftButton.label = "Back"; leftButton.size = 100; leftButton.sizeUnit = SizeUnit.PIXELS; leftButton.sizeMode = SizeMode.BOTH;

2.

Specify a size for the component (using the size property) to resize the component when a layout call occurs. In the following example, the Next button does not specify the SizeMode property. This button will not resize after a layout call.
rightButton = new LabelButton(); rightButton.label = "Next"; rightButton.size = 100;

Use spacers to define child layout


You can use spacers to position UI components in the direction of the flow of the parent container. A spacer is a simple, invisible component that adds space between components. Before you begin: Adjust the opposite size of UI components 1. In the initializeUI function, add a spacer to a container. By default, the spacer's size property is set to 100, and the SizeUnit property is set to SizeUnit.PERCENT indicating that the spacer will take up the entire container flow, until another component is added. In the following example, the spacer pushes all other components to the right-edge of the container.
mySubBottom.addChild(new Spacer());

2. 3.

Add a button to the container.


mySubBottom.addChild(leftButton);

Add another spacer to the container. The spacer, which is instantiated when it is added to the container, is set to three pixels in size.
mySubBottom.addChild(new Spacer(3,SizeUnit.PIXELS));

4.

Add another button.


mySubBottom.addChild(rightButton);

Code sample: Using containers to design a simple layout


The following code listing builds the sample container layout application below:

32

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

package { import import import import import import import import import import import import import import import import

flash.display.Sprite; flash.events.Event; flash.text.TextFieldAutoSize; flash.text.TextFormat; qnx.ui.buttons.LabelButton; qnx.ui.core.Container; qnx.ui.core.ContainerAlign; qnx.ui.core.ContainerFlow; qnx.ui.core.Containment; qnx.ui.core.SizeMode; qnx.ui.core.SizeUnit; qnx.ui.core.Spacer; qnx.ui.data.DataProvider; qnx.ui.listClasses.List; qnx.ui.text.Label; qnx.ui.text.TextInput;

//Orientation Handler import flash.events.StageOrientationEvent; import flash.display.StageAlign; import flash.display.StageScaleMode; [SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] // A simple container layout example public class ContainerTest extends Sprite { //containers private var myMain:Container; private var mySub:Container; private var mySubRight:Container; private var mySubBottom:Container;

33

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

//the left-side of the screen labels private var firstLabel:Label; private var secondLabel:Label; private var thirdLabel:Label; private var fourthLabel:Label; //text input for second sub container private var firstInput:TextInput; // back and next buttons private var leftButton:LabelButton; private var rightButton:LabelButton; private var myList:List; private var myDP:DataProvider; public function ContainerTest() { addEventListener(Event.ADDED_TO_STAGE,handleAddedToStage); initializeUI(); } private function handleAddedToStage(e:Event):void { removeEventListener(Event.ADDED_TO_STAGE,handleAddedToStage); stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; // stage is available, we can now listen for events stage.addEventListener(StageOrientationEvent.ORIENTATION_CHANGE,

onReorient);

// force a reorientation call onReorient(new StageOrientationEvent(StageOrientationEvent.ORIENTATION_CHANGE,true,true)); } private function initializeUI():void { // create main container myMain = new Container(); myMain.margins = Vector.<Number>([20,20,20,20]); myMain.flow = ContainerFlow.HORIZONTAL; myMain.debugColor = 0xFFCC00; addChild(myMain); // create subcontainer on left side of the screen mySub = new Container(); mySub.margins = Vector.<Number>([20,40,20,40]); mySub.flow = ContainerFlow.VERTICAL; mySub.debugColor = 0xFF3300; mySub.padding = 10; mySub.size = 50;

34

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

mySub.sizeUnit = SizeUnit.PERCENT; mySub.align = ContainerAlign.NEAR; // create second subcontainer on left side of the screen mySubRight = new Container(); mySubRight.margins = Vector.<Number>([10,10,10,10]); mySubRight.size = 50; mySubRight.debugColor = 0x0033FF; mySubRight.sizeUnit = SizeUnit.PERCENT; mySubRight.flow = ContainerFlow.VERTICAL; mySubRight.align = ContainerAlign.MID; mySubRight.padding = 10; // create subcontainer as the bottom frame mySubBottom = new Container(); mySubBottom.margins = Vector.<Number>([5,5,5,5]); mySubBottom.debugColor = 0x33FF33; mySubBottom.size = 12; mySubBottom.sizeUnit = SizeUnit.PERCENT; mySubBottom.flow = ContainerFlow.HORIZONTAL; mySubBottom.align = ContainerAlign.FAR; mySubBottom.containment = Containment.DOCK_BOTTOM; // add subcontainers to main container myMain.addChild(mySub); myMain.addChild(mySubRight); myMain.addChild(mySubBottom); // create and add UI components to the left container var labelFormat:TextFormat = new TextFormat(); labelFormat.size = 22; firstLabel = new Label(); firstLabel.format = labelFormat; firstLabel.text = "First label"; firstLabel.size=35; firstLabel.sizeUnit = SizeUnit.PERCENT; firstLabel.autoSize = TextFieldAutoSize.LEFT; mySub.addChild(firstLabel); secondLabel = new Label(); secondLabel.format = labelFormat; secondLabel.text = "Second label"; secondLabel.size=35; secondLabel.sizeUnit = SizeUnit.PERCENT; secondLabel.autoSize = TextFieldAutoSize.LEFT; mySub.addChild(secondLabel); thirdLabel = new Label(); thirdLabel.format = labelFormat; thirdLabel.text = "Third label"; thirdLabel.size=35; thirdLabel.sizeUnit = SizeUnit.PERCENT;

35

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

thirdLabel.autoSize = TextFieldAutoSize.LEFT; mySub.addChild(thirdLabel); // create and add UI components for right side firstInput = new TextInput; firstInput.width = 200; fourthLabel = new Label(); fourthLabel.format = labelFormat; fourthLabel.text = "Fourth label:"; fourthLabel.width = 200; fourthLabel.size=30; fourthLabel.sizeUnit = SizeUnit.PIXELS; mySubRight.addChild(new Spacer(60)); mySubRight.addChild(fourthLabel); mySubRight.addChild(firstInput); // create and add back and next buttons leftButton = new LabelButton(); leftButton.label = "Back"; leftButton.size = 100; leftButton.sizeUnit = SizeUnit.PIXELS; leftButton.sizeMode = SizeMode.BOTH; rightButton = new LabelButton(); rightButton.label = "Next"; rightButton.size = 100; // add spacer then button then spacer then button mySubBottom.addChild(new Spacer()); mySubBottom.addChild(leftButton); mySubBottom.addChild(new Spacer(3,SizeUnit.PIXELS)); mySubBottom.addChild(rightButton);

private function onReorient(event:StageOrientationEvent):void { myMain.setSize(stage.stageWidth, stage.stageHeight); }

36

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Choosing a button for your application


The BlackBerry Tablet OS SDK API provides the following button types: Class
Button

The BlackBerry Tablet OS SDK API Reference contains a variety of button implementations. Each implementation is skinnable and customizable.

Image

Description The Button class is the most basic button type and the base class for all buttons. The BackButton class is a simple button that contains a back arrow. You can use this button to provide navigation in your application. The CheckBox class is a simple check box implementation. The IconButton class is a button that contains an icon. The LabelButton class is button that contains a String. The RadioButton class is a simple radio button implementation. The radio button remains in the selected state when pressed. The listener for the RadioButton runs when a button is selected.

BackButton

CheckBox IconButton

LabelButton

RadioButton

SegmentedControl

The SegmentedControl class is a group of interconnected radio buttons that force the user to select a single option from a group or related choices.

37

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Class
ToggleSwitch

Image

Description The ToggleSwitch class is a simple toggle switch implementation where the switch can be dragged along a track from one state to another.

Create a toggle button


You can use the toggle property to create a simple toggle button. When the toggle property is set to true, the button maintains the down state when pressed. When the button is pressed again, the button is released and returns to the up state. 1. Import the required classes.
import flash.display.Sprite; qnx.ui.Buttons.Button;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class MyToggle extends Sprite {

4. 5.

In the body of the class, create a variable.


var myButton:Button;

Create a constructor for your class and invoke initializeUI()


public function MyToggle() { initializeUI(); }

6.

Create a function called initializeUI to set up the toggle switch control.


private function initializeUI():void {

7.

In the initializeUI function, set the position and size of the button. The setPosition method takes the x and y position of the button, in pixels. The setSize method takes the width and height settings, in pixels.
myButton = new Button(); myButton.setPosition(200, 200); myButton.setSize(100, 50);

8.

In the initializeUI function, set the toggle property to true.


myButton.toggle = true;

38

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

9.

In the initializeUI function, add an event listener for the click event.
myButton.addEventListener(MouseEvent.CLICK, myButtonEvent);

10. In the initializeUI function, add the button to the stage.


} this.addChild(myButton);

11. Create the myButtonEvent function. In the following code sample, a trace is sent to the console indicating that the button has been pressed. The myButton.selected property is called to return the state of the button. When the button is in the down state (when it has been clicked) the selected property returns true.
function myButtonEvent(event:MouseEvent):void { trace ("myButton has been clicked, current toggle state is:" + myButton.selected); } }

Create a check box


1. Import the required classes.
import flash.display.Sprite; import flash.events.MouseEvent; import qnx.ui.buttons.CheckBox; import qnx.ui.buttons.LabelButton;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class CheckBoxSample extends Sprite {

4.

In the body of your class, create the instance variables.


private var myCheckBox:CheckBox; private var myButton:LabelButton; private var myText:TextInput;

5.

Create a constructor for your class and invoke initializeUI().


public function CheckBoxSample() { initializeUI(); }

6.

Create the initializeUI function to set up and initialize the UI controls.

39

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

private function initializeUI():void {

7.

In the initializeUI function, create and position the check box. For a check box, the width property sets the width for both the check box and the text label. The width property is mandatory. You must specify a width value or the check box will not render.
myCheckBox = new CheckBox(); myCheckBox = new CheckBox(); myCheckBox.setPosition(128, 300); myCheckBox.width = 150;

8.

In the initializeUI function, set the label for the check box. The label property takes a String. The labelPadding property takes an integer to specify the number of pixels between the check box and the label.
myCheckBox.label = "Disable login"; myCheckBox.labelPadding = 5;

9.

In the initializeUI function, set the LabelPlacement property. In the code sample below, the label is placed directly above the CheckBox instance.
myCheckBox.labelPlacement = LabelPlacement.TOP;

10. In the initializeUI function, add an event listener to trap mouse click events. The event listener will call the disableButton function whenever the user clicks the check box.
myCheckBox.addEventListener(MouseEvent.CLICK, disableButton);

11. In the initializeUI function, add the check box to the stage.
this.addChild(myCheckBox);

12. In the initializeUI function, create the LabelButton and add it to the stage. This label button is disabled when the user selects the check box.
myButton = new LabelButton(); myButton = new LabelButton(); myButton.setPosition(175, 300); myButton.width = 100; myButton.label = "Login"; this.addChild(myButton);

13. In the initializeUI function, create the text input field and add it to the stage.
myText = new TextInput(); myText.setPosition(175, 250); myText.width = 150; } this.addChild(myText);

40

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

14. Create the disableButton function. When the user clicks the check box, the disableButton function is called and the enabled property for the myButton and myText buttons are toggled.
function disableButton(event:MouseEvent):void { myButton.enabled = !myButton.enabled; myText.enabled = !myText.enabled; }

Code sample: Creating a check box


The following code sample uses a CheckBox object to disable a button and text input field.
package { import flash.display.Sprite; import flash.events.MouseEvent; import import import import qnx.ui.buttons.CheckBox; qnx.ui.buttons.LabelButton; qnx.ui.buttons.LabelPlacement; qnx.ui.text.TextInput;

[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] public class CheckBoxSample extends Sprite { private var myCheckBox:CheckBox; private var myButton:LabelButton; private var myText:TextInput; public function CheckBoxSample() { initializeUI(); } private function initializeUI():void { myCheckBox = new CheckBox(); myCheckBox.setPosition(128, 350); myCheckBox.width = 200; myCheckBox.label = "Disable login"; myCheckBox.labelPadding = 5; myCheckBox.labelPlacement = LabelPlacement.TOP; myCheckBox.addEventListener(MouseEvent.CLICK, disableButton); this.addChild(myCheckBox); myButton = new LabelButton(); myButton.setPosition(175, 300); myButton.width = 100; myButton.label = "Login"; this.addChild(myButton);

41

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

myText = new TextInput(); myText.setPosition(175, 250); myText.width = 150; this.addChild(myText);

private function disableButton(e:MouseEvent):void { myButton.enabled = !myButton.enabled; myText.enabled = !myText.enabled; } }

Code sample: Creating an icon button


The following code sample describes how to create an icon button. In the code sample below, the setIcon method is called to place an icon on a button. The image asset is located in the src/assets folder in the project.
package { import flash.display.Sprite; import qnx.ui.buttons.IconButton; [SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] public class IconButtonTest extends Sprite { private var myIconButton:IconButton; public function IconButtonTest() { initializeUI(); } private function initializeUI():void { var myIconButton:IconButton = new IconButton(); myIconButton.setIcon("../assets/icon.gif"); myIconButton.width = 100; myIconButton.setPosition(30, 30); } this.addChild(myIconButton);

Create a label button


1.
42

Import the required classes.

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

import flash.display.Sprite; import qnx.ui.buttons.LabelButton;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class LabelButtonSample extends Sprite {

4.

Create a constructor for your class and invoke initializeUI().


public function LabelButtonSample() { initializeUI(); }

5.

Create the initializeUI function to set up and initialize the UI controls.


{ private function initializeUI():void

6.

In the initializeUI function, create and set up the button. The label property takes a String. This is the text that appears on the button. You must set the width of the button according to the length of the text, otherwise the label will overrun the bounds of the button. You can use a TextFormat object to apply formatting to the label text. For more information about applying a format object to a label, see Format the label text for each button state.
var myButton:LabelButton; myButton = new LabelButton(); myButton.setPosition(175, 300); myButton.width = 100; myButton.label = "Login";

7.

In the initializeUI function, add the button to the stage.


} this.addChild(myButton);

Formatting the text on a label button


You can format the label text on a button by applying a TextFormat object to a button. Because a button has multiple states (one for each user-interaction), and because button states typically supply unique skins for each state, you must create and apply a TextFormat object to each button state. You can accomplish this by calling the setTextFormatForState method and specifying a TextFormat object and a button state.

43

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Format the label text for each button state


The following task demonstrates how to create a TextFormat object for the up, down, and disabled button states and how to use the setTextFormatForState method to apply the TextFormat object to each button state. 1. Import the required classes.
import import import import import flash.display.Sprite; flash.text.TextFormat; flash.text.TextFormatAlign; qnx.ui.buttons.LabelButton; qnx.ui.skins.SkinStates;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class LabelButtonStatesSample extends Sprite {

4.

Create a constructor for your class and invoke initializeUI()


public function LabelButtonStatesSample() { initializeUI(); }

5.

Create the initializeUI function to set up and initialize the UI controls.


private function initializeUI():void {

6.

In the initializeUI function, create an instance of the TextFormat object for the up button state. In the following code sample, the font color is set to red. The default skin color for the up state is grey.
var format:TextFormat = new TextFormat(); format.font = "Myriad Pro"; format.size = 16; format.color = 0xcc0000; format.align = TextFormatAlign.CENTER;

7.

In the initializeUI function, create an instance of the TextFormat object for the down button state. In the following code sample, the font color is set to white. The default skin color for the down state is blue.
var formatDown:TextFormat = new TextFormat(); formatDown.font = "Myriad Pro"; formatDown.size = 16; formatDown.color = 0xFFFFFF; formatDown.align = TextFormatAlign.CENTER;

8.

In the initializeUI function, create an instance of the TextFormat object for the disabled button state. In the following code sample, the font color is set to dark grey. The default skin color for the down state is grey.

44

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

var formatDisable:TextFormat = new TextFormat(); formatDisable.font = "Myriad Pro"; formatDisable.size = 16; formatDisable.color = 0xCCCCCC; formatDisable.align = TextFormatAlign.CENTER;

9.

In the initializeUI function, create a LabelButton instance.


var myButton:LabelButton = new LabelButton();

10. In the initializeUI function, call the setTextFormatForState for each button state. The setTextFormatForState matches the TextFormat object with the button state. In the code sample, only the up, down, and disabled button states are assigned unique TextFormat objects. The other button states are not implemented.
myButton.setTextFormatForState(formatDisable,SkinStates.DISABLED); myButton.setTextFormatForState(format,SkinStates.UP); myButton.setTextFormatForState(formatDown,SkinStates.DOWN);

11. In the initializeUI function, add the button label and position the button on the stage.
myButton.label = "OK"; myButton.x = 175;

12. In the initializeUI function, add the button to the stage.


} this.addChild(myButton);

Code sample: Formating the label text for each button state
The following code sample describes how to apply a TextFormat object to each button state.
package { import import import import import

flash.display.Sprite; flash.text.TextFormat; flash.text.TextFormatAlign; qnx.ui.buttons.LabelButton; qnx.ui.skins.SkinStates;

[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] public class LabelButtonSample extends Sprite { public function LabelButtonStatesSample() { initializeUI(); } private function initializeUI():void { // create a text format for up, disabled, selected, etc. // red label text 45

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

var format:TextFormat = new TextFormat(); format.font = "Myriad Pro"; format.size = 16; format.color = 0xcc0000; format.align = TextFormatAlign.CENTER; // create a text format for the down state // white label text var formatDown:TextFormat = new TextFormat(); formatDown.font = "Myriad Pro"; formatDown.size = 16; formatDown.color = 0xFFFFFF; formatDown.align = TextFormatAlign.CENTER; // create a text format for the disabled state // grey label text var formatDisable:TextFormat = new TextFormat(); formatDisable.font = "Myriad Pro"; formatDisable.size = 16; formatDisable.color = 0xCCCCCC; formatDisable.align = TextFormatAlign.CENTER; var myButton:LabelButton = new LabelButton(); // set the formats for each state you want to address myButton.setTextFormatForState(formatDisable,SkinStates.DISABLED); myButton.setTextFormatForState(format,SkinStates.UP); myButton.setTextFormatForState(formatDown,SkinStates.DOWN); myButton.label = "OK"; myButton.x = myButton.y = 175; } this.addChild(myButton);

Using the Toggleswitch class


The ToggleSwitch class allows you to create a simple toggle switch. The toggle switch is a sliding button that the user can drag from one state to another. Internally, it defines two states: default and selected. You can define your own states by setting the defaultLabel and selectedLabel properties. In the following illustrations, a toggle switch is defined using Light and Dark states.

46

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Create a toggle switch


1. Import the required classes.
import flash.display.Sprite; import flash.events.Event; import import import import qnx.ui.buttons.LabelButton; qnx.ui.buttons.ToggleSwitch; qnx.ui.skins.buttons.RoundedButtonSkinBlack; qnx.ui.skins.buttons.RoundedButtonSkinWhite;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class ToggleSample extends Sprite {

4.

Create the variables for the myToggle toggle switch and the myButton label button.
private var myToggle:ToggleSwitch; private var myButton:LabelButton;

5.

Create a constructor for your class and invoke initializeUI().


public function ToggleSample() { initializeUI(); }

6.

Create the initializeUI function to set up and initialize the UI controls.


private function initializeUI():void {

7.

In the initializeUI function, add the LabelButton object. In the following code sample, the LabelButton class named myLabel.
var myButton:LabelButton = new LabelButton(); myButton.label = "myButton"; myButton.setPosition(200, 150); this.addChild(myButton);

8.

In the initializeUI function, create a new ToggleSwitch instance and set the position on the stage.
var myToggle:ToggleSwitch = new ToggleSwitch(); myToggle.setPosition(200, 200);

47

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

9.

In the initializeUI function, define the toggle states. You can define the toggle states by assigning a String to the defaultLabel and selectedLabel properties. In the following code sample, the Light and Dark states represent the light and dark color themes. You also set the selected property to false, indicating that the toggle will be set to the default label on initialization.
myToggle.defaultLabel = "Light"; myToggle.selectedLabel = "Dark"; myToggle.selected = false;

10. In the initializeUI function, add an event listener for the toggle switch.
myToggle.addEventListener(Event.SELECT, themeChange);

11. In the initializeUI function, add the ToggleSwitch to the stage.


} this.addChild(myToggle);

12. Add the themeChange function that is called by the event listener. The themeChange function sets the skin for the button myButton based on the current state.
function themeChange(event:Event):void { if (myToggle.selected == true) { myButton.setSkin(RoundedButtonSkinBlack); } else { } }

myButton.setSkin(RoundedButtonSkinWhite);

Code sample: Creating a toggle switch


The following code sample uses a ToggleSwitch object to change a button theme from dark to light.
package { import flash.display.Sprite; import flash.events.Event; import import import import qnx.ui.buttons.LabelButton; qnx.ui.buttons.ToggleSwitch; qnx.ui.skins.buttons.RoundedButtonSkinBlack; qnx.ui.skins.buttons.RoundedButtonSkinWhite;

[SWF(height="600", width="1024", frameRate="30",backgroundColor="#FFFFFF")] public class ToggleSample extends Sprite { private var myToggle:ToggleSwitch; private var myButton:LabelButton;

48

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

public function ToggleSample() { initializeUI(); } private function initializeUI():void { myToggle = new ToggleSwitch(); myToggle.setPosition(200, 200); myToggle.defaultLabel = "Light"; myToggle.selectedLabel = "Dark"; myToggle.selected = false; // listen the select event the toggle switch dispatches myToggle.addEventListener(Event.SELECT, themeChange); this.addChild(myToggle); myButton = new LabelButton(); myButton.label = "myButton"; myButton.setPosition(200, 150); } this.addChild(myButton);

/** @private **/ private function themeChange( e:Event ):void { // if the toggle is selected, set the button skin to black, else white if ( myToggle.selected == true ) { myButton.setSkin(RoundedButtonSkinBlack); } else { } }

myButton.setSkin(RoundedButtonSkinWhite);

Create a segmented control


1. Import the required classes.
import import import import flash.display.Sprite; flash.events.Event; qnx.ui.buttons.SegmentedControl; qnx.ui.data.DataProvider;

49

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class SegmentedControlExample extends Sprite {

4.

Create a constructor for your class and invoke initializeUI().


public function SegmentedControlExample() { initializeUI(); }

5.

Create the initializeUI function to set up and initialize the UI controls.


private function initializeUI():void {

6.

In the initializeUI function, create and populate the array. The array contains the objects that define the text that appears on each button in the segmented control. Each object must contain a label property. In the following code sample, the array contains the names of only three days. The remaining day names will be added later.
var buttonArray:Array=[]; buttonArray.push({label:"Monday"}); buttonArray.push({label:"Tuesday"}); buttonArray.push({label:"Thursday"});

7.

In the initializeUI function, create and configure the segmented control.


var mySegment:SegmentedControl = new SegmentedControl(); mySegment.x = 200; mySegment.y = 200; mySegment.width = 500; mySegment.height = 50;

8.

In the initializeUI function, instantiate the DataProvider class and associate it with the segmented control that you just created.
mySegment.dataProvider = new DataProvider(buttonArray);

9.

Add an entry in the DataProvider for Wednesday. You can use the addItemAt method to add a button to the segmented control at a given index. The label property "Wednesday" is added in the second last index within the segmented control.
mySegment.addItemAt({label: "Wednesday" }, mySegment.dataProvider.length -1)

10. Add an entry in the DataProvider for Friday. You can use the addItem method to append a button to the segmented control.
mySegment.addItem({label: "Friday" });

50

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

11. In the initializeUI function, set the button that is initially selected.
mySegment.selectedIndex = 2;

12. In the initializeUI function, add the segmented control to the stage.
} this.addChild(mySegment);

Code sample: Creating a segmented control


This code sample provides an example of a SegmentedControl object that contains a button for each day of the week.
package { import flash.display.Sprite; import import import import qnx.ui.buttons.SegmentedControl; qnx.ui.data.DataProvider; qnx.ui.skins.buttons.SegmentedControlSkinBlack; qnx.ui.skins.buttons.RoundedButtonSkinBlack;

[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] public class SegmentedControlExample extends Sprite { public function SegmentedControlExample() { initializeUI(); } private function initializeUI():void { // create an array for the segmented control with objects //that have label properties var buttonArray:Array=[]; buttonArray.push({label:"Monday"}); buttonArray.push({label:"Tuesday"}); buttonArray.push({label:"Thursday"}); // create a segemented control var mySegment:SegmentedControl = new SegmentedControl(); mySegment.x = 200; mySegment.y = 200; mySegment.width = 500; mySegment.height = 50; // set the data provider mySegment.dataProvider = new DataProvider(buttonArray); // set the selected index to be the 3 item in the dataProvider mySegment.selectedIndex = 2; 51

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

// add the control to the disply list this.addChild(mySegment); // add an item at the index mySegment.addItemAt({label: "Wednesday" }, mySegment.dataProvider.length // add an item to the end mySegment.addItem({label: "Friday" })

-1)

Create a radio button group


1. Import the required classes.
import flash.display.Sprite; import flash.events.MouseEvent; import qnx.ui.buttons.RadioButton; import qnx.ui.buttons.RadioButtonGroup;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class RadioButtonSample extends Sprite {

4.

Create a constructor for your class and invoke initializeUI().


public function RadioButtonSample() { initializeUI(); }

5.

Create the initializeUI function to set up and initialize the UI controls.


private function initializeUI():void {

6.

In the initializeUI function, create three radio buttons. These buttons will become the first radio button group. In the following code sample, the groupname property is set to rbg1_meals13. This is the name of the RadioButtonGroup object that will contain the radio buttons. You must specify the name of the RadioButtonGroup for each button to associate the button with a parent group. Otherwise, all radio buttons on the screen will be part of the same array. You will create the RadioButtonGroup in a later step.

52

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

var rb1:RadioButton = new RadioButton(); rb1.setPosition(100, 100) rb1.label = "Meal option 1"; rb1.groupname = "rbg1_meals13"; addChild( rb1 ); var rb2:RadioButton = new RadioButton(); rb2.setPosition(rb1.x, rb1.y + 40); rb2.label = "Meal option 2"; rb2.groupname = "rbg1_meals13"; addChild( rb2 ); var rb3:RadioButton = new RadioButton(); rb3.setPosition(rb1.x, rb2.y + 40); rb3.label = "Meal option 3"; rb3.groupname = "rbg1_meals13"; addChild( rb3 );

7.

In the initializeUI function, create the second set of radio buttons. These buttons will become the second radio button group: rbg1_meals46.
var rb4:RadioButton = new RadioButton(); rb4.setPosition(300, 100) rb4.label = "Meal option 4"; rb4.groupname = "rbg1_meals46"; addChild( rb4 ); var rb5:RadioButton = new RadioButton(); rb5.setPosition(rb4.x, rb4.y + 40); rb5.label = "Meal option 5"; rb5.groupname = "rbg1_meals46"; addChild( rb5 ); var rb6:RadioButton = new RadioButton(); rb6.setPosition(rb4.x, rb5.y + 40); rb6.label = "Meal option 6"; rb6.groupname = "rbg1_meals46"; addChild( rb6 );

8.

In the initializeUI function, create the first radio button group, rbg1. Use the getGroup method to instantiate the radio button group by specifying a unique name for the radio button group. It's important to use a unique name for each radio button group. Call the setSelectedRadioButton method to set the initial selection. When the application loads, the radio button rb2 will be selected.
var rbg1:RadioButtonGroup; rbg1 = RadioButtonGroup.getGroup("rbg1_meals13"); rbg1.addEventListener(MouseEvent.CLICK, rbg1Change); rbg1.setSelectedRadioButton(rb2);

9.

In the initializeUI function, create the second radio button group.


var rbg2:RadioButtonGroup; rbg2 = RadioButtonGroup.getGroup("rbg1_meals46"); rbg2.addEventListener(MouseEvent.CLICK, rbg2Change);

53

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

10. In the initializeUI function, create the event listener functions. The functions trap mouse-click events for each radio button group.
function rbg1Change(event:MouseEvent):void { trace("rb1 change event"); } function rbg2Change(event:MouseEvent):void{ trace("rb2 change event"); }

Code sample: Creating a radio button group


package { import flash.display.Sprite; import flash.events.MouseEvent; import qnx.ui.buttons.RadioButton; import qnx.ui.buttons.RadioButtonGroup; [SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] public class RadioButtonSample extends Sprite { public function RadioButtonSample() { initializeUI(); } private function initializeUI():void { var rb1:RadioButton = new RadioButton(); rb1.setPosition(100, 100) rb1.label = "Meal option 1"; rb1.groupname = "rbg1_meals13"; addChild( rb1 ); var rb2:RadioButton = new RadioButton(); rb2.setPosition( rb1.x, rb1.y + 40 ); rb2.label = "Meal option 2"; rb2.groupname = "rbg1_meals13"; addChild( rb2 ); var rb3:RadioButton = new RadioButton(); rb3.setPosition( rb1.x, rb2.y + 40 ); rb3.label = "Meal option 3"; rb3.groupname = "rbg1_meals13"; addChild( rb3 ); var rb4:RadioButton = new RadioButton(); rb4.setPosition( 300, 100 ) 54

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

rb4.label = "Meal option 4"; rb4.groupname = "rbg1_meals46"; addChild( rb4 ); var rb5:RadioButton = new RadioButton(); rb5.setPosition( rb4.x, rb4.y + 40 ); rb5.label = "Meal option 5"; rb5.groupname = "rbg1_meals46"; addChild( rb5 ); var rb6:RadioButton = new RadioButton(); rb6.setPosition( rb4.x, rb5.y + 40 ); rb6.label = "Meal option 6"; rb6.groupname = "rbg1_meals46"; addChild( rb6 ); var rbg1:RadioButtonGroup; rbg1 = RadioButtonGroup.getGroup( "rbg1_meals13" ); rbg1.addEventListener( MouseEvent.CLICK, rbg1Change ); rbg1.setSelectedRadioButton( rb2 ); var rbg2:RadioButtonGroup; rbg2 = RadioButtonGroup.getGroup( "rbg1_meals46" ); rbg2.addEventListener( MouseEvent.CLICK, rbg2Change ); rbg2.setSelectedRadioButton( rb5 );

private function rbg1Change( event:MouseEvent ):void { trace("rb1 change event"); } private function rbg2Change( event:MouseEvent ):void { trace("rb2 change event"); }

55

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Displaying data in lists

The BlackBerry Tablet OS SDK contains convenient and flexible list implementations that you can use to display data and to provide the user with a selectable, scrollable list of input choices. The qnx.ui.listClasses package contains classes that you can use to create a number of different list types, with each list inheriting from the base List class. Class
List

RoundList SectionList TileList SectionTileList DropDown

Description The List class is the base list class that provides simple list functionality. You can use the ListSelectionMode class to define how the user interacts with the list, and the ScrollDirection class to define how the list scrolls. The RoundList class is a simple list class that has no scroll bar, and continues to scroll from the beginning after the final cell is reached. The SectionList class is a list implementation that contains sections, where each section contains zero or more list items. The TileList displays list items laid out in a grid format. The SectionTileList class is a variation of the SectionList that uses tiles instead of list items. The DropDown class is a simple drop-down list implementation.

Create a List
1. Import the required classes.
import flash.display.Sprite; import import import import qnx.ui.data.DataProvider; qnx.ui.listClasses.List; qnx.ui.listClasses.ListSelectionMode; qnx.ui.listClasses.ScrollDirection;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class ListSample extends Sprite {

4.

Create a constructor for your class and invoke initializeUI().

56

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

public function ListSample() { initializeUI(); }

5.

Create the initializeUI function to set up and initialize the UI controls.


private function initializeUI():void {

6.

In the initializeUI function, create the array of objects. By default, the List object looks for the label property within the List object data. The label property contains the String that will appear inside each list cell. In the following code sample, the array is populated with an object for each month of the year, where each object contains a label property.
var arrMonth:Array=[]; arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: "January"}); "February"}); "March"}); "April"}); "May"}); "June"}); "July"}); "August"}); "September"}); "October"}); "November"}); "December"});

7.

In the initializeUI function, instantiate the List class and position it on the stage. You must provide a height and width for the list, otherwise it will not render.
var myList:List = new List(); myList.setPosition(100, 200); myList.width = 300; myList.height = 100; myList.columnWidth = 100;

8. 9.

In the initializeUI function, set the selectionMode property to allow multiple selections.
myList.selectionMode = ListSelectionMode.MULTIPLE;

In the initializeUI function, set the scrollDirection property to ScrollDirection.HORIZONTAL to allow the list to scroll horizontally.
myList.scrollDirection = ScrollDirection.HORIZONTAL;

10. In the initializeUI function, assign a DataProvider to the list. In the following code sample, a new DataProvider instance is created using the array of objects that you created in step 5.
myList.dataProvider = new DataProvider(arrMonth);

11. In the initializeUI function, add the List object to the stage.

57

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

this.addChild(myList);

Code sample: Creating a list


package { import import import import import flash.display.Sprite; qnx.ui.data.DataProvider; qnx.ui.listClasses.List; qnx.ui.listClasses.ListSelectionMode; qnx.ui.listClasses.ScrollDirection;

[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] public class ListSample extends Sprite { public function ListSample() { initializeUI(); } private function initializeUI():void { // create an array for objects var arrMonth:Array=[]; // add objects with a arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: label property "January"}); "February"}); "March"}); "April"}); "May"}); "June"}); "July"}); "August"}); "September"}); "October"}); "November"}); "December"});

//create a new list var myList:List = new List(); // set the position of x and y myList.setPosition(100, 200); // set the width myList.width = 400; // set the height myList.height = 100; myList.columnWidth = 100; 58

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

myList.selectionMode = ListSelectionMode.MULTIPLE; myList.scrollDirection = ScrollDirection.HORIZONTAL; myList.dataProvider = new DataProvider(arrMonth); //add the list to the display list this.addChild(myList);

Adding an item to a list


Call the addItemAt method to add an item to a list at a given index. In the following code sample, a new item is added to the list at the second index. The addItemAt method takes the object data to add and the index location to place the new data.
myList.addItemAt({label: "Q1 FY11"}, 2);

You can append a child to the list by calling the addItem method. You can add multiple children to a given item by calling the addItemsAt method. In the following code sample, a new array of data is added at the second index. The addItemsAt method takes an array of object data and the index location to place the new data. The array data is inserted into the existing data array.
myList.addItemsAt(myNewArray, 4)

Removing an item from a list


You can remove data from a list at runtime. Call the removeItem method and specify a valid object to remove the object from a list. In the following code sample, an object with the label property "January" is removed from the list.
myList.removeItem({label: "January"});

To remove an item at a given index, use the removeItemAt method.


myList.removeItemAt(2)

To remove all items in the list, use the removeAll method.

Updating an item in a list


You can update the data in a list at runtime. To update an item with a given item use the updateItem method. In the following code sample, an object with the label property "January" is updated with a new object that contains the label property "Q1 FY11".
myList.updateItem({label: "January"}, {label: "Q1 FY11"} );

59

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

You can use the updateItemAt method to update an item at a given index.
myList.updateItemAt({label: "Q1 FY11"}, 1)

You can call the updateItemsAt method to update the data in the array starting at the fourth index, using a new array of data. The updateItemsAt method takes an array of object data and the index location at which to update the new data. The array data is inserted into the existing data array.
myList.updateItemsAt(myNewArray, 4)

Create a tile list


1. Import the required classes.
import flash.display.Sprite; import qnx.ui.data.DataProvider; import qnx.ui.listClasses.TileList;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024",frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class TileListSample extends Sprite {

4.

Create a constructor for your class and invoke initializeUI().


public function TileListSample() { initializeUI(); }

5.

Create the initializeUI function to set up and initialize the UI controls.


private function initializeUI():void {

6.

In the initializeUI function, create the array. The following code sample creates an array of month names named arrMonth.
var arrMonth:Array=[]; arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: "January"}); "February"}); "March"}); "April"}); "May"}); "June"}); "July"}); "August"});

60

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label:

"September"}); "October"}); "November"}); "December"});

7.

In the initializeUI function, create a background for the TileList instance.


var bg:Sprite = new Sprite(); bg.graphics.lineStyle(2,0xCCCCCC); bg.graphics.beginFill(0x333333,1); bg.graphics.drawRect(0,0,420,320); bg.graphics.endFill(); bg.x = 90; bg.y = 190; addChild(bg);

8.

In the initializeUI function, create the TileList instance and position it on the stage. You must set a height and width for the list. By default, each tile is 100 pixels wide.
var myTileList:TileList = new TileList(); myTileList.setPosition(100, 200); myTileList.width = 400; myTileList.height = 300;

9.

In the initializeUI function, set the number of columns and the cell padding for the TileList. The cell padding specifies the amount of pixels between each TileList cell.
myTileList.columnCount = 3; myTileList.cellPadding = 5;

10. In the initializeUI function, specify the data provider for the TileList.In the code sample below, you create a new DataProvider instance by passing in the arrMonth array that you created in step 3.
myTileList.dataProvider = new DataProvider(arrMonth);

11. In the initializeUI function, add the TileList instance to the stage.
} this.addChild(myTileList);

Code sample: Creating a tile list


The following code sample provides an example of a TileList object that contains the names of all months of the year.
{ package import flash.display.Sprite; import qnx.ui.data.DataProvider; import qnx.ui.listClasses.TileList;

61

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] public class TileListSample extends Sprite { public function TileListSample() { initializeUI(); } private function initializeUI():void { var arrMonth:Array=[]; arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: "January"}); "February"}); "March"}); "April"}); "May"}); "June"}); "July"}); "August"}); "September"}); "October"}); "November"}); "December"});

var bg:Sprite = new Sprite(); bg.graphics.lineStyle(2,0xCCCCCC); bg.graphics.beginFill(0x333333,1); bg.graphics.drawRect(0,0,420,320); bg.graphics.endFill(); bg.x = 90; bg.y = 190; this.addChild(bg); var myTileList:TileList = new TileList(); myTileList.setPosition(100, 200); myTileList.width = 400; myTileList.height = 300; myTileList.columnCount = 3; myTileList.cellPadding = 5; myTileList.dataProvider = new DataProvider(arrMonth); this.addChild(myTileList);

Creating a section tile list


The SectionTileList list contains one or more sections, where each section contains one or more list items. Conceptually, and in the context of the API, a section is called an item, and each item contains children. When you add a child to a SectionList, you must first determine which item to add the child to.

62

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

To accomodate both item and child data, the SectionTileList class uses the SectionDataProvider data structure to store data. The SectionDataProvider class contains the structure and functionality that is required to create and maintain a list structure with multiple sections.

Create a SectionDataProvider object


This task demonstrates how to create a SectionDataProvider object to contain month and day data for a calendar. 1. Import the required classes.
import flash.display.Sprite; import qnx.ui.data.SectionDataProvider;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class SectionTileSample extends Sprite {

4.

Creat the constructor.


public function SectionTileSample() { }

5.

Create the createDataProvider function to create a SectionDataProvider object instance.


{ private function createDataProvider():SectionDataProvider

6.

In the createDataProvider function, create an array. In the following code sample, the arrMonth array is a simple array of objects.
var arrMonth:Array=[]; arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: "January"}); "February"}); "March"}); "April"}); "May"}); "June"}); "July"}); "August"}); "September"}); "October"}); "November"}); "December"});

7.

In the createDataProvider function, create a SectionDataProvider object.

63

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

var mySDP:SectionDataProvider = new SectionDataProvider();

8.

In the createDataProvider function, populate the SectionDataProvider object. In the following code sample, a for loop is used to create an object for each month of the year. The label property of each object is set using the array of month names that you created in a previous step. Each object is added to the SectionDataProvider object by calling the addItem method. The second for loop adds 31 children to each item by calling the addChildToItem method.
for( var i:int = 0; i < arrMonth.length; i++ ) { var section:Object = new Object(); section.label = arrMonth[i].label; mySDP.addItem( section ); for( var j:int = 1; j<32; j++ ) { mySDP.addChildToItem( {label: j}, section ); } } }

Create a section tile list


1. Import the required classes.
import flash.display.Sprite; import qnx.ui.data.SectionDataProvider; import qnx.ui.listClasses.SectionTileList;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class SectionTileSample extends Sprite {

4.

Create a constructor for your class and invoke initializeUI().


public function SectionTileSample() { initializeUI(); }

5.

Create the initializeUI function to set up and initialize the UI controls.


private function initializeUI():void {

64

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

6.

In the initializeUI function, create and populate a SectionDataProvider instance.


var arrMonth:Array=[]; arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: "January"}); "February"}); "March"}); "April"}); "May"}); "June"}); "July"}); "August"}); "September"}); "October"}); "November"}); "December"});

var mySDP:SectionDataProvider = new SectionDataProvider(); for( var i:int = 0; i < arrMonth.length; i++ ) { var section:Object = new Object(); section.label = arrMonth[i].label; mySDP.addItem( section ); for( var j:int = 1; j<32; j++ ) { mySDP.addChildToItem( {label: j}, section ); }

7.

In the initializeUI function, create the SectionTileList instance and position it on the stage.
var mySectionTileList:SectionTileList = new SectionTileList(); mySectionTileList.setPosition(100, 200); mySectionTileList.width = 520; mySectionTileList.height = 300;

8.

In the initializeUI function, set the number of columns and the cell padding. In the following code sample, the section tile list contains 5 columns. The cell padding is set to 5 pixels. Each tile is 100 pixels wide by default. The width of the list is set to 520 pixels to accomodate the tiles and the padding.
mySectionTileList.columnCount = 5; mySectionTileList.cellPadding = 5;

9.

In the initializeUI function, specify the SectionDataProvider instance for the section tile list.
mySectionTileList.dataProvider = createDataProvider();

10. In the initializeUI function, add the SectionTileList instance to the stage.

65

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

this.addChild(mySectionTileList);

Remove an item from a section tile list


The following code sample demonstrates how to create a function to remove extra day children from month items that contains less than 31 days. Before you begin: This task builds on the application that you created in the previous task. 1. Import the required classes.
import flash.display.Sprite; import qnx.ui.data.SectionDataProvider; import qnx.ui.listClasses.SectionTileList;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3. 4.

Create the arrMonth SectionDataProvider instance, and mySectionTileList object that you created when you created and populated the list. In the SectionTileSample class, create a function called normalizeDays. In the normalizeDays function, call removeChildFromIndexAt to remove extra days from months that contain fewer than 31 days. In the following code sample, the removeChildFromIndexAt method is called to remove the 31st, 30th, and 29th days (remember that the array is zero-based) from the month object in the first index position of the array.
function normalizeDays():void{ mySectionTileList.removeChildFromIndexAt(1, 30); mySectionTileList.removeChildFromIndexAt(1, 29); mySectionTileList.removeChildFromIndexAt(1, 28); }

5.

Add the remaining code to the normalizeDays function to remove excess days from each remaining month.
mySectionTileList.removeChildFromIndexAt(3, 30); mySectionTileList.removeChildFromIndexAt(5, 30); mySectionTileList.removeChildFromIndexAt(8, 30); mySectionTileList.removeChildFromIndexAt(10, 30);

6.

In the constructor of your application, call the normalizeDays function.


normalizeDays();

66

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Code sample: Creating a section tile list calendar


The following code sample provides an example of a calendar that was implemented using the SectionTileList class.
package { import flash.display.Sprite; import qnx.ui.data.SectionDataProvider; import qnx.ui.listClasses.SectionTileList; [SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] public class SectionTileSample extends Sprite { private var mySectionTileList:SectionTileList; public function SectionTileSample() { initializeUI(); normalizeDays(); } private function initializeUI():void { //create and setup section list mySectionTileList = new SectionTileList(); mySectionTileList.setPosition(100, 200); mySectionTileList.width = 520; mySectionTileList.height = 300; mySectionTileList.columnCount = 5; mySectionTileList.cellPadding = 5; mySectionTileList.dataProvider = createDataProvider(); } this.addChild(mySectionTileList);

private function createDataProvider():SectionDataProvider { var arrMonth:Array=[]; arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: "January"}); "February"}); "March"}); "April"}); "May"}); "June"}); "July"}); "August"}); "September"}); "October"}); "November"}); "December"}); 67

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

var mySDP:SectionDataProvider = new SectionDataProvider(); for( var i:int = 0; i < arrMonth.length; i++ ) { //add month names var section:Object = new Object(); section.label = arrMonth[i].label; mySDP.addItem( section ); //add day numbers, all 31 for now for( var j:int = 1; j<32; j++ ) { mySDP.addChildToItem( {label: j}, section ); } return(mySDP); } private function normalizeDays():void { //TODO: account for leap years mySectionTileList.removeChildFromIndexAt(1, 30); mySectionTileList.removeChildFromIndexAt(1, 29); mySectionTileList.removeChildFromIndexAt(1, 28); mySectionTileList.removeChildFromIndexAt(3, 30); mySectionTileList.removeChildFromIndexAt(5, 30); mySectionTileList.removeChildFromIndexAt(8, 30); } } mySectionTileList.removeChildFromIndexAt(10, 30);

Creating a custom list


You can extend the CellRenderer or AlternatingCellRenderer classes in order to create a custom look and feel for your list. The CellRenderer class is used to draw the table cells that make up a list. The AlternatingCellRenderer class extends the CellRenderer class to provide alternating colors for the cells in a list. The following code sample demonstrates how to create a custom list class that extends the AlternatingCellRenderer class, add a check box control to each cell, add an event listener and logic to define how each cell behaves when the user clicks the check box, and create a List object that uses the setSkin method to set the new class as the skin for the list.

68

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Create a custom cell renderer


1. Import the required classes.
import import import import flash.display.Sprite; qnx.ui.data.DataProvider; qnx.ui.listClasses.List; qnx.ui.listClasses.ListSelectionMode;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create the MyCustomCellRenderer class. In your application signature, extend the AlternatingCellRenderer class.
public class MyCustomCellRenderer extends AlternatingCellRenderer {

4.

Create the constructor.


public function MyCustomCellRenderer() { }

5.

Override the init function. The init function is called when the list is instantiated. You can add custom logic inside this function to customize each cell in the list.
override protected function init():void {

6. 7.

In the init function, call the init function of the super class (AlternatingCellRenderer).
super.init();

In the init function, create a CheckBox object. The x and y coordinates are relative to the edge of the cell. The CheckBox appears in every cell in the list.
private var myCB:CheckBox; myCB = new CheckBox(); myCB.x = 250; myCB.y = 10; this.addChild(myCB)

8.

In the init function, add an event listeners to capture mouse click events and mouse down events.
myCB.addEventListener(MouseEvent.CLICK, onClick); myCB.addEventListener( MouseEvent.MOUSE_DOWN, onMouseDown);

9.

Add the onClick function. The onClick function dispatches a new event that bubbles up whenever the check box control is selected.

69

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

private function onClick(event:MouseEvent):void { dispatchEvent( new Event( Event.SELECT, true, true ) ); }

10. Add the onMouseDown function. The onMouseDown function calls the stopImmediatePropagation method which stops the event from propagating to the parent container, or in this case, the cell. This allows the user to select the check box control without selecting the cell.
private function onMouseDown(event:MouseEvent):void { event.stopImmediatePropagation(); }

Apply a custom cell renderer to a list


Before you begin: The following code sample demonstrates how to apply a custom AlternatingCellRenderer class to a list. This code sample assumes that the MyCustomCellRenderer class exists in the same project. 1. Import the required classes.
import flash.display.Sprite; import qnx.ui.data.DataProvider; import qnx.ui.listClasses.List; import qnx.ui.listClasses.ListSelectionMode;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


public class CustomListSample extends Sprite {

4.

Create a constructor for your class and invoke initializeUI().


public function CustomListSample() { initializeUI(); }

5.

Create the initializeUI function to set up and initialize the UI controls.


private function initializeUI():void {

6.

Create and populate the array. The following code sample creates an array of grocery items.
var arrItems:Array=[]; arrItems.push({label: "Apples"});

70

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

arrItems.push({label: arrItems.push({label: arrItems.push({label: arrItems.push({label: arrItems.push({label: arrItems.push({label: arrItems.push({label: arrItems.push({label: arrItems.push({label: arrItems.push({label:

"Potatoes"}); "Oranges"}); "Tomatoes"}); "Carrots"}); "Eggplant"}); "Celery"}); "Milk"}); "Ham"}); "Cheese"}); "Bacon"});

7.

Create and set up the List object. In the following code sample, the selectionMode property is set to ListSelectionMode.MULTIPLE to allow the user to select multiple items in the list at one time.
var myList:List = new List(); myList.setPosition(100, 200); myList.width = 300; myList.height = 300; myList.dataProvider = new DataProvider(arrItems); myList.selectionMode = ListSelectionMode.MULTIPLE;

8. 9.

Apply the AlternatingCellRenderer class to the List.


myList.setSkin(MyCustomCellRenderer);

Add the List object to the stage.


} this.addChild(myList);

Code sample: Creating a custom cell renderer


You can apply a custom CellRenderer to a List object by calling the setSkin method. The following code sample shows a custom cell renderer that places a check box control inside of each list cell.
package { import flash.events.Event; import flash.events.MouseEvent; import qnx.ui.buttons.CheckBox; import qnx.ui.listClasses.AlternatingCellRenderer; public class MyCustomCellRenderer extends AlternatingCellRenderer { private var myCB:CheckBox; public function MyCustomCellRenderer() { } override protected function init():void { 71

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

super.init(); myCB = new CheckBox(); myCB.x = 250; myCB.y = 10; this.addChild(myCB); myCB.addEventListener( MouseEvent.CLICK, onClick ); //add this listener in order to block the mouse // down event from the list myCB.addEventListener( MouseEvent.MOUSE_DOWN, onMouseDown);

//this will prevent the cell from being selected private function onMouseDown(event:MouseEvent):void { event.stopImmediatePropagation(); } private function onClick(event:MouseEvent):void { dispatchEvent( new Event( Event.SELECT, true, true ) ); }

The following code listing creates a simple grocery list. The list calls the custom cell renderer above to place a check box on each list cell.
package { import flash.display.Sprite; import qnx.ui.data.DataProvider; import qnx.ui.listClasses.List; import qnx.ui.listClasses.ListSelectionMode; [SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] public class CustomListSample extends Sprite { public function CustomListSample() { initializeUI(); } private function initializeUI():void { var arrItems:Array=[]; arrItems.push({label: arrItems.push({label: arrItems.push({label: arrItems.push({label: arrItems.push({label: 72 "Apples"}); "Potatoes"}); "Oranges"}); "Tomatoes"}); "Carrots"});

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

arrItems.push({label: arrItems.push({label: arrItems.push({label: arrItems.push({label: arrItems.push({label: arrItems.push({label:

"Eggplant"}); "Celery"}); "Milk"}); "Ham"}); "Cheese"}); "Bacon"});

var myList:List = new List(); myList.setPosition(100, 200); myList.width = 300; myList.height = 300; myList.selectionMode = ListSelectionMode.MULTIPLE; myList.dataProvider = new DataProvider(arrItems); myList.setSkin(MyCustomCellRenderer); } this.addChild(myList);

73

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Using the picker to implement complex lists

The Picker class provides a scrollable, selectable list that you can use to display complex data in multiple columns. Users can select a value from a Picker object by first clicking on the Picker to open it, then swiping up or down to scroll a list to the desired value.

Create and populate a DataProvider object for a picker


You can create a DataProvider object that contains the day, month, and year data for the Picker object. 1. Import the required classes.
import import import import import flash.display.Sprite; flash.events.Event; qnx.ui.data.DataProvider; qnx.ui.picker.Picker; qnx.ui.text.Label;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class PickerSample extends Sprite {

4.

Create a constructor for your class and invoke createDataProvider()


public function PickerSample() { createDataProvider(); }

5.

Create the createDataProvider function to set up and initialize the UI controls.


private function createDataProvider():DataProvider {

6.

In the createDataProvider function. Create the array variables.

74

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

var arrDay:Array=[]; var arrMonth:Array=[]; var arrYear:Array=[];

7.

number of days in a month is not provided.

In the createDataProvider function, populate the arrDay array with the day data and use it to create the dayDP DataProvider. This code sample assumes a simple month data model. The logic used to determine the
for (var i:int=1; i<32; i++) { arrDay.push({label: i.toString()}); } var dayDP:DataProvider=new DataProvider(arrDay);

8.

In the createDataProvider function, populate the arrMonth array with the month data and use it to create the monthDP DataProvider instance.
arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: "January"}); "February"}); "March"}); "April"}); "May"}); "June"}); "July"}); "August"}); "September"}); "October"}); "November"}); "December"});

var monthDP:DataProvider=new DataProvider(arrMonth);

9.

In the createDataProvider function, populate the arrYear array with the year data and use it to create the yearDP DataProvider.
var monthDP:DataProvider=new DataProvider(arrMonth); for (var l:int=1900; l<2011; l++) { arrYear.push({label: l.toString()}); } var yearDP:DataProvider=new DataProvider(arrYear);

10. In the createDataProvider function, create the main calendar array, dpp, using the day, month, and year data that you created in the previous steps. The dpp array is an array of arrays.
var dpp:Array = new Array(); dpp.push(dayDP); dpp.push(monthDP); dpp.push(yearDP); var returnDataProvider:DataProvider = new DataProvider(dpp);

75

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

return(returnDataProvider);

Create a picker
1. Import the required classes.
import import import import import flash.display.Sprite; flash.events.Event; qnx.ui.data.DataProvider; qnx.ui.picker.Picker; qnx.ui.text.Label;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class PickerSample extends Sprite {

4.

Create a constructor for your class. Invoke the initializeUI() function.


public function PickerSample() { initializeUI(); }

5.

Create the createDataProvider function to create and populate the DataProvider object. For more information about creating the following DataProvider instance, refer to Create and populate a DataProvider object for a picker.
private function createDataProvider():DataProvider { var arrDay:Array=[]; var arrMonth:Array=[]; var arrYear:Array=[]; for (var i:int=1; i<32; i++) { arrDay.push({label: i.toString()}); } var dayDP:DataProvider=new DataProvider(arrDay); arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: "January"}); "February"}); "March"}); "April"}); "May"}); "June"}); "July"});

76

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label:

"August"}); "September"}); "October"}); "November"}); "December"});

var monthDP:DataProvider=new DataProvider(arrMonth); for (var l:int=1900; l<2011; l++) { arrYear.push({label: l.toString()}); } var yearDP:DataProvider=new DataProvider(arrYear); var dpp:Array = new Array(); dpp.push(dayDP); dpp.push(monthDP); dpp.push(yearDP); var returnDataProvider:DataProvider = new DataProvider(dpp); return(returnDataProvider);

6.

Create the initializeUI function to set up and initialize the UI controls.


private function initializeUI():void {

7.

In the initializeUI function, create and configure the Picker object.


var calPicker:Picker = new Picker(); calPicker.width=400; calPicker.height=50; calPicker.x=calPicker.y=300;

8.

In the initializeUI function, add the DataProvider to the Picker by calling the createDataProvider function.
calPicker.dataProvider=createDataProvider(); addChild(calPicker);

9.

In the initializeUI function, set the width of each list in the picker. The first argument in the setListWidth method is the index value of the list. This array is zero-based, and the value 0 represents the first list in the picker. The second argument represents the width of the list.
calPicker.setListWidth(0,25); calPicker.setListWidth(1,50); calPicker.setListWidth(2,25);

10. In the initializeUI function, add the event listeners for the open, close, and select events.

77

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

calPicker.addEventListener(Event.OPEN,handleOpen); calPicker.addEventListener(Event.CLOSE,handleClose); calPicker.addEventListener(Event.SELECT,handleSelect);

11. In the initializeUI function, set the initial index values of the picker. The selectedIndices method takes an array of index values. In the code sample below, the values represent 1 January 2010. You can call this method at any time to set the current index of the picker.
} calPicker.selectedIndices=[0,0,110];

12. Create the handleSelect function to print the selected items to the console. The handleSelect function uses the selectedItems method to capture the currently selected item in each of the three arrays. It uses the selectedIndices method to capture the current index value.
function handleSelect(e:Event):void { for (var j:int = 0; j <calPicker.selectedItems.length; j++) { trace("calPicker.selectedItems " +calPicker.selectedItems[j].label); selItem = calPicker.selectedItems[j].label; } trace("calPicker.selectedIndices "+calPicker.selectedIndices); selIndex = calPicker.selectedIndices; trace("calPicker.selectedItems "+calPicker.selectedItems); selObj = calPicker.selectedItems; }

13. Create the handleOpen and handleClose functions to handle open and close events.
function handleOpen(e:Event):void { trace("Picker.open event captured"); } function handleClose(e:Event):void { trace("Picker.close event captured"); }

Update data in a picker


You can create a new DataProvider instance and apply it to a Picker at run time. For example, you can create a DataProvider object that contains French month names, then use the updateItemAt method to replace the English month name array. Before you begin: Create a Picker object. 1.
78

Create the new array and DataProvider.

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

var arrMonth_fr:Array = new Array(); arrMonth_fr.push({label: arrMonth_fr.push({label: arrMonth_fr.push({label: arrMonth_fr.push({label: arrMonth_fr.push({label: arrMonth_fr.push({label: arrMonth_fr.push({label: arrMonth_fr.push({label: arrMonth_fr.push({label: arrMonth_fr.push({label: arrMonth_fr.push({label: arrMonth_fr.push({label: "Janvier"}); "Fevrier"}); "Mars"}); "Avril"}); "Mai"}); "Juin"}); "Juillet"}); "Aout"}); "Septembre"}); "Octobre"}); "Novembre"}); "Decembre"});

var month_frDP:DataProvider=new DataProvider(arrMonth_fr);

2.

Call the updateItemAt method to update the second column of the picker with the new array of month names.
calPicker.updateItemAt(month_frDP, 1);

Code sample: Creating a picker calendar


The following code sample demonstrates how to create a Picker that contains calendar data.
package { import flash.display.Sprite; import flash.events.Event; import qnx.ui.data.DataProvider; import qnx.ui.picker.Picker; import qnx.ui.text.Label; [SWF(height="600", width="1024", frameRate="30", backgroundColor="#BBBBBB")] public class PickerSample extends Sprite { private var calPicker:Picker; public function PickerSample() { initializeUI(); } private function initializeUI():void { calPicker = new Picker(); calPicker.width=400; calPicker.height=50; calPicker.x=calPicker.y=300; calPicker.dataProvider=createDataProvider();

79

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

addChild(calPicker); calPicker.setListWidth(0,25); calPicker.setListWidth(1,50); calPicker.setListWidth(2,25); calPicker.selectedIndices=[0,0,110]; calPicker.addEventListener(Event.OPEN,handleOpen); calPicker.addEventListener(Event.CLOSE,handleClose); calPicker.addEventListener(Event.SELECT,handleSelect); } traceItems(); function createDataProvider():DataProvider arrDay:Array=[]; arrMonth:Array=[]; arrYear:Array=[];

private { var var var

for (var i:int=1; i<32; i++) { arrDay.push({label: i.toString()}); } var dayDP:DataProvider=new DataProvider(arrDay); arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: "January"}); "February"}); "March"}); "April"}); "May"}); "June"}); "July"}); "August"}); "September"}); "October"}); "November"}); "December"});

var monthDP:DataProvider=new DataProvider(arrMonth); for (var l:int=1900; l<2011; l++) { arrYear.push({label: l.toString()}); } var yearDP:DataProvider=new DataProvider(arrYear); var dpp:Array = new Array(); dpp.push(dayDP); dpp.push(monthDP); dpp.push(yearDP);

80

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

var returnDataProvider:DataProvider = new DataProvider(dpp); return(returnDataProvider);

private function traceItems():void { for (var j:int = 0; j <calPicker.selectedItems.length; j++) { trace("Picker.selectedItems " +calPicker.selectedItems[j].label); } trace("Picker.selectedIndices "+calPicker.selectedIndices); trace("Picker.selectedItems "+calPicker.selectedItems);

private function handleSelect(e:Event):void { traceItems(); } private function handleOpen(e:Event):void { trace("Picker.open event captured"); } private function handleClose(e:Event):void { trace("Picker.close event captured"); }

Code sample: Creating a picker clock


The following code listing provides an example of a clock, implemented using the picker. The picker is updated using the system time. The user can interact with the picker by scrolling through the lists, however the picker always resets to the system time after a period of time.
package { import import import import import

flash.display.Sprite; flash.events.Event; flash.events.TimerEvent; flash.utils.Timer; flash.utils.setInterval;

import qnx.ui.data.DataProvider; import qnx.ui.picker.Picker; [SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] public class PickerClock extends Sprite { 81

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

private var picker:Picker; private var timer:Timer; public function PickerClock() { initializeUI(); updatePicker(); // create a timer to run every 6 seconds timer = new Timer(60000); timer.addEventListener(TimerEvent.TIMER,handleTimerTick); timer.start(); // simple function that outputs the selected items traceItems();

private function initializeUI():void { // Create the picker and add the main DataProvider picker = new Picker(); picker.x = 300; picker.y = 175; picker.dataProvider = createDataProvider(); addChild(picker); // To customize column widths, // all widths are added up and then used for // a ratio against the component set width picker.height=50; picker.width = 200; picker.setListWidth(0,25); picker.setListWidth(1,25); picker.setListWidth(2,25); picker.addEventListener(Event.OPEN,handleOpen); picker.addEventListener(Event.CLOSE,handleClose); picker.addEventListener(Event.SELECT,handleSelect); picker.setListBackgroundSkin(SkinAssets.PickerListBgBlack); } picker.isOpen = true;

private function handleTimerTick(e:TimerEvent):void { updatePicker(); } private function createDataProvider():DataProvider { // Create three arrays to handle hours, mins, AM PM var arrHour:Array=[]; var arrMin:Array=[]; var arrAmPm:Array=[]; //hours

82

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

for (var i:int=1; i<13; i++) { arrHour.push({label: i.toString()}); } var HourDP:DataProvider=new DataProvider(arrHour); //mins arrMin.push({label: arrMin.push({label: arrMin.push({label: arrMin.push({label: arrMin.push({label: arrMin.push({label: arrMin.push({label: arrMin.push({label: arrMin.push({label: arrMin.push({label: "00"}); "01"}); "02"}); "03"}); "04"}); "05"}); "06"}); "07"}); "08"}); "09"});

for (var k:int=10; k<60; k++) { arrMin.push({label: k.toString()}); } var MinDP:DataProvider=new DataProvider(arrMin); arrAmPm.push({label: "AM"}); arrAmPm.push({label: "PM"}); var AmPmDP:DataProvider=new DataProvider(arrAmPm); // Populate the main array var dpp:Array = new Array(); dpp.push(HourDP); dpp.push(MinDP); dpp.push(AmPmDP); var returnDataProvider:DataProvider = new DataProvider(dpp); return(returnDataProvider);

private function handleSelect(e:Event):void { traceItems(); } private function handleOpen(e:Event):void { trace("Picker.open event captured"); } private function handleClose(e:Event):void { trace("Picker.close event captured"); } private function traceItems():void

83

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

for (var j:int = 0; j <picker.selectedItems.length; j++) { trace("Picker.selectedItems " +picker.selectedItems[j].label); } trace("Picker.selectedIndices "+picker.selectedIndices); trace("Picker.data "+picker.data);

private function updatePicker():void { trace("PickerClock.updatepicker"); var mins:Number = new Date().minutes; var hours:Number = new Date().hours; var ampm:Number = 0; //add 1 if hour is 1 am if (hours == 0) { picker.selectedIndices=[11, mins, ampm]; } else if (hours == 1) { picker.selectedIndices=[0, mins, ampm]; } else if (hours > 12) { ampm = 1; hours = hours - 12; picker.selectedIndices=[hours - 1, mins, ampm]; } else { } }

picker.selectedIndices=[hours - 1, mins, ampm];

84

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Providing feedback and activity status to the user

You can provide temporal feedback and pending activity status indications to the user by using the ProgressBar class, PercentageBar class, and the ActivityIndicator class. The ProgressBar class is a horizontal track that takes a percentage value to represent the current progress of an ongoing operation. When you set the progress property, the track fill changes to represent the current status of the operation. The PercentageBar class contains a label that displays the current percentage value of the track. A PercentageBar object is shown in the following illustration:

The ActivityIndicator class is an animation that you can enable or disable to indicate to the user that an activity is currently in progress. For example, you could create an ActivityIndicator instance to display during timeconsuming or processor-intensive operations. An ActivityIndicator instance is shown in the following illustration.

Create a progress bar


1. Import the required classes.
import flash.display.Sprite; import qnx.ui.progress.ProgressBar;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class ProgressSample extends Sprite {

4.

Create a constructor for your class and invoke initalizeUI().


public function ProgressSample() { initializeUI(); }

5.

Create the initializeUI function to set up and initialize the UI controls.


85

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

private function initializeUI():void {

6.

In the initializeUI function, create and position the ProgressBar object instance.
var myProgress:ProgressBar; myProgress = new ProgressBar(); myProgress.setPosition(400, 300); myProgress.width = 200;

7. 8.

In the initializeUI function, add the ProgressBar instance to the stage.


this.addChild(myProgress);

In the initializeUI function, set the progress value.You can use the progress property to update the fill position of the progress bar. The progress property takes a percentage value as a decimal. For example, 0.5 indicates 50% and 1 indicates 100%. You should write a function that periodically sets the progress property to reflect the current state of your operation.
} myProgress.progress = .5;

Code sample: Creating a progress bar


package { import flash.display.Sprite; import qnx.ui.buttons.IconButton; import qnx.ui.progress.PercentageBar; [SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] public class ProgressSample extends Sprite { private var myPercentage:PercentageBar; public function ProgressSample() { initializeUI(); } private function initializeUI():void { myPercentage = new PercentageBar(); myPercentage.setPosition(400, 300); myPercentage.width = 200; myPercentage.progress = .5; this.addChild(myPercentage);

86

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Create an activity indicator


1. Import the required classes.
import flash.display.Sprite; import flash.events.MouseEvent; import qnx.ui.buttons.LabelButton; import qnx.ui.progress.ActivityIndicator;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class ActivityIndicatorSample extends Sprite {

4.

Create a constructor for your class, and invoke initializeUI().


public function ActivityIndicatorSample() { initializeUI(); }

5.

Create the initializeUI function to set up and initialize the UI controls.


private function initializeUI():void {

6.

In the initializeUI function, create the ActivityIndicator instance and add it to the stage.
var myActivity:ActivityIndicator = new ActivityIndicator(); myActivity.setPosition(260, 225); this.addChild(myActivity);

7.

In the initializeUI function, create a LabelButton instance and add it to the stage. In the following code sample, the LabelButton instance is used to enable and disable the activity indicator.
var myAnimate:LabelButton = new LabelButton(); myAnimate.setPosition(200, 300); myAnimate.label = "Animate"; myAnimate.width = 150; this.addChild(myAnimate);

8.

In the initializeUI function, add an event listener to capture button click events.
} myAnimate.addEventListener(MouseEvent.CLICK, onClick);

87

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

9.

Create the onClick function. The onClick function uses the isAnimating property of the ActivityIndicator to determine if the activity indicator is currently animating. If the activity indicator is currently animating, then the button label text is toggled and the animation is turned off by calling the animate method with a Boolean argument.
function onClick():void { if (!myActivity.isAnimating()) { myAnimate.label = "Stop"; myActivity.animate(true); } else { myAnimate.label = "Animate"; myActivity.animate(false); }

Code Sample: Creating an activity indicator


package { import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import qnx.ui.buttons.LabelButton; import qnx.ui.progress.ActivityIndicator; [SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] public class ActivityIndicatorSample extends Sprite { private var myActivity:ActivityIndicator; private var myAnimate:LabelButton; public function ActivityIndicatorSample() { initializeUI(); } private function initializeUI():void { myActivity = new ActivityIndicator(); myActivity.setPosition(260, 225); this.addChild(myActivity); myAnimate= new LabelButton(); myAnimate.setPosition(200, 300); 88

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

myAnimate.label = "Animate"; myAnimate.width = 150; this.addChild(myAnimate); } myAnimate.addEventListener(MouseEvent.CLICK, onClick);

private function onClick(e:MouseEvent):void { if (!myActivity.isAnimating()) { myAnimate.label = "Stop"; myActivity.animate(true) } else { myAnimate.label = "Animate"; myActivity.animate(false); } }

Code sample: Creating a percentage bar


package { import flash.display.Sprite; import flash.events.TimerEvent; import flash.utils.Timer; import qnx.ui.progress.PercentageBar; [SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] public class myPercentageSample extends Sprite { private var myPercentage:PercentageBar; private var timer:Timer; private var counter:int; public function myPercentageSample() { initializeUI(); } private function initializeUI():void { myPercentage = new PercentageBar(); myPercentage.setPosition(400, 300); myPercentage.width = 200; myPercentage.progress = 0; this.addChild(myPercentage); // counter to keep track of how many times the timer has ticked

89

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

counter = 0; timer = new Timer(100,100); timer.addEventListener(TimerEvent.TIMER,handleTimerTick); timer.addEventListener(TimerEvent.TIMER_COMPLETE,handleTimerComplete); timer.start(); } private function handleTimerComplete(e:TimerEvent):void { timer.removeEventListener(TimerEvent.TIMER,handleTimerTick); timer.removeEventListener(TimerEvent.TIMER_COMPLETE,handleTimerComplete); counter = 0; } private function handleTimerTick(e:TimerEvent):void { counter++; myPercentage.progress = counter/100; }

90

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Capturing variable input with a slider

10

The Slider class enables the user to input variable data by dragging a thumb across a track. The VolumeSlider class is used to adjust volume levels for media playback. A volume slider control is shown in the illustration below:

Create a volume slider


1. Import the required classes.
import flash.display.Sprite; import qnx.ui.slider.VolumeSlider; import qnx.ui.events.SliderEvent;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30",backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class SliderSample extends Sprite {

4. 5.

Create the VolumeSlider variable.


private var myVSlider:VolumeSlider;

Create a constructor for your class and invoke initializeUI().


public function SliderSample() { initializeUI(); }

6.

Create the initializeUI function to set up and initialize the UI controls.


private function initializeUI():void {

7.

In the initializeUI function, create the VolumeSlider object and position it on the stage.
var myVSlider:VolumeSlider = new VolumeSlider(); myVSlider.x = 50; myVSlider.y = 50;

8. 9.

In the initializeUI function, set the initial value of the slider control.
myVSlider.value = 50;

In the initializeUI function, add the event listeners. The event listeners use event types that are defined in the SliderEvent class to capture slider movement, slider start, and slider stop events.

91

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

myVSlider.addEventListener( SliderEvent.MOVE, sliderChange ); myVSlider.addEventListener( SliderEvent.START, sliderStart ); myVSlider.addEventListener( SliderEvent.END, sliderStop );

10. In the initializeUI function, add the VolumeSlider object to the stage.
} this.addChild( myVSlider );

11. Create the event functions. The functions in the following code sample are used to output the current slider value and thumb state to the console. The values change as the user drags the slider. The thumb skin icon changes as the user drags the thumb from the left edge of the track to the right edge of the track.
function sliderChange( event:SliderEvent ) : void { var newlevel:int = Math.round( event.target.value ); trace( "slider value: ", newlevel ); } function sliderStart( event:SliderEvent ) : void { var newlevel:int = Math.round( event.target.value ); trace( "started moving at: ", newlevel ); } function sliderStop( event:SliderEvent ) : void { var newlevel:int = Math.round( event.target.value ); trace( "stopped moving at: ", newlevel ); }

Code sample: Creating a volume slider


package { import flash.display.Sprite; import qnx.ui.events.SliderEvent; import qnx.ui.slider.VolumeSlider; [SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] public class SliderSample extends Sprite { /** @private **/ private var myVSlider:VolumeSlider; public function SliderSample() { initializeUI(); } private function initializeUI():void 92

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

myVSlider = new VolumeSlider(); myVSlider.setPosition(300, 300); myVSlider.minimum = 0; myVSlider.maximum = 100; myVSlider.value = 50; // listen to the when the slider moves myVSlider.addEventListener( SliderEvent.MOVE, sliderChange ); myVSlider.addEventListener( SliderEvent.START, sliderStart ); // listen to the end of the slider event myVSlider.addEventListener( SliderEvent.END, sliderStop ); this.addChild( myVSlider );

private function sliderChange( event:SliderEvent ) : void { var newlevel:int = Math.round( event.target.value ); trace( "slider value: ", newlevel ); } private function sliderStart( event:SliderEvent ) : void { var newlevel:int = Math.round( event.target.value ); trace( "started moving at: ", newlevel ); } private function sliderStop( event:SliderEvent ) : void { var newlevel:int = Math.round( event.target.value ); trace( "stopped moving at: ", newlevel ); }

93

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Skinning your UI components

11

The BlackBerry Tablet OS contains a set of skin classes that provide a customizable and consistent, look and feel for your application. The OS defines two distinct color themes: light and dark. The tablet uses the light themed component skins by default. Each UI component in the OS was designed to enable a specific user-interaction. For example, the picker is useful for inputting complex numbers such as dates or IP addresses. The user can expand the picker component in order to scroll through a set of vertical scrolling lists. Because UI components vary in their complexity, most UI components differ from one another in the way that they implement skinning. For example, a basic button component is simple to skin when compared to a section tile list or a picker, both of which are comprised of many parts. Each skin object consists of one or more graphic assets, where a graphic asset provides the bitmap or vector data that is used to render each state of the skin. For example, a button skin should contain assets to define the up, down, selected, and disabled states that appear when the user interacts with the button. These component states are defined in the qnx.ui.skins.SkinStates class. An asset uses 9 slice scaling which allows it to be resized with little or no distortion. Most skins in the SDK derive from the qnx.ui.skins.UISkin class. The qnx.ui.skins.UISkin class registers skins for certain states and handles the state changes so that the appropriate skin is associated with the current state. All skinnable UI component parts in the SDK use one of the following skin types: Skin type
ICellRenderer

ISkin

Description The ICellRenderer class is used to render the cells in all list types. When you create a skin for the list class, your skin must implement ICellRenderer interface. The ISkin class is the default skin for all components such as buttons and thumbs. When you create a skin for a button class, your skin must implement ISkin interface.

In order to create your own custom skin, you must create a skin class that implements the qnx.ui.skins.ISkin interface. The quickest way to create a custom skin is to extend qnx.ui.skins.ISkin. This gives your skin class a functional base for handling state changes and for associating skins with states. Each asset must be registered with the skin. To register assets, you must override the protected functioninitializeStates() in your skin class. You can then register each skin asset by associating an asset with the intended UI component state.

Change the default skin of a UI component


You can change the color scheme of a segmented control from light (default) to dark by changing the component's skin. 1. Import the required classes.
import flash.display.Sprite; import qnx.ui.buttons.SegmentedControl;

94

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

import qnx.ui.data.DataProvider; import qnx.ui.skins.buttons.SegmentedControlSkinBlack; import qnx.ui.skins.buttons.RoundedButtonSkinBlack;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class SkinSample extends Sprite {

4.

Create a constructor for the class and invoke initializeUI().


public function SkinSample() { initializeUI(); }

5.

Create the initializeUI function to set up and initialize the UI controls.


private function initializeUI():void {

6.

In the initializeUI function, create a SegmentedControl object instance.


var buttonArray:Array=[]; buttonArray.push({label:"Monday"}); buttonArray.push({label:"Tuesday"}); buttonArray.push({label:"Wednesday"}); buttonArray.push({label:"Thursday"}); buttonArray.push({label:"Friday"}); var mySegment:SegmentedControl = new SegmentedControl(); mySegment.x = 200; mySegment.y = 200; mySegment.width = 500; mySegment.height = 50; mySegment.dataProvider = new DataProvider(buttonArray); mySegment.selectedIndex = 2; this.addChild(mySegment);

7.

In the initializeUI function, call the setBackgroundSkin method, passing in the SegmentedControlSkinBlack skin asset class. This changes the background skin of the SegmentedControl instance to the dark color scheme asset.
mySegment.setBackgroundSkin(SegmentedControlSkinBlack);

8.

In the initializeUI function, call the setButtonSkin method, passing in the RoundedButtonSkinBlack skin asset class. This changes the skin of each button in the SegmentedControl instance to use the asset from the dark color scheme.

95

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

mySegment.setButtonSkin(RoundedButtonSkinBlack);

After you finish: For more information about the light and dark color scheme assets, see the SkinAssets class in the qnx.ui.skins package.

Create a custom button skin class


In the following task you create a custom button skin and apply it to a set of buttons. 1. Import the required classes.
import qnx.ui.skins.SkinAssets; import qnx.ui.skins.UISkin; import qnx.ui.skins.SkinStates;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

In your class signature, extend the UISkin class. The UISkin class implements the qnx.ui.skins.ISkin interface and provides the base functionality required for loading and registering your skin assets.
public class CustomButtonSkin extends UISkin {

4.

Create the constructor.


public function CustomButtonSkin() { super(); }

5.

Override the initializeStates method.The initializeStates function is used to register your skin assets to associate them with UI component states.
override protected function initializeStates():void {

6.

Create variables for the skin assets. In the following code sample, you create skin assets for the up, down, selected, and disabled skin states.
protected protected protected protected var var var var upSkin:Sprite; selectedSkin:Sprite; disabledSkin:Sprite; downSkin:Sprite;

7.

In the initializeStates function, create the skin assets. Each skin is instantiated as a Sprite object. Each skin is filled using a different hexadecimal color code to create a unique look for each button state. The drawRoundRect method is used and each button skin will have a rounded edge.

96

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

upSkin = new Sprite(); upSkin.graphics.beginFill(0xFF6600); upSkin.graphics.drawRoundRect(0,0,50,50, 10,10); upSkin.graphics.endFill(); downSkin = new Sprite(); downSkin.graphics.beginFill(0x333333); downSkin.graphics.drawRoundRect(0,0,50,50, 10,10); downSkin.graphics.endFill(); disabledSkin = new Sprite(); disabledSkin.graphics.beginFill(0xCC0000); disabledSkin.graphics.drawRoundRect(0,0,50,50, 10,10); disabledSkin.graphics.endFill(); selectedSkin = new Sprite(); selectedSkin.graphics.beginFill(0x000000); selectedSkin.graphics.drawRoundRect(0,0,50,50, 10,10); selectedSkin.graphics.endFill();

8.

In the initializeStates function, register your skin assets by calling the setSkinState method for each skin asset. The setSkinState method takes a skin state constant and a skin asset. It associates the skin asset with the UI component state, such that when a button is pressed, or a list is rendered, the appropriate skin asset is displayed. In the code sample below, each skin asset is associated with the proper state.
setSkinState(SkinStates.UP, upSkin); setSkinState(SkinStates.SELECTED,selectedSkin); setSkinState(SkinStates.DISABLED, disabledSkin); setSkinState(SkinStates.DOWN, downSkin);

9.

In the initializeStates function, set the default skin state by calling the showSkin method.
} showSkin(upSkin);

Apply a custom button skin


Before you begin: Create a custom button skin. This example assumes that you created the custom button skin class CustomButtonSkin in the same project as the following sample application. Otherwise, you'd need to import the class into your sample application. 1. Import the required classes.
import qnx.ui.buttons.Button; import qnx.ui.buttons.LabelButton;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.

97

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class ButtonSample extends Sprite {

4.

Create a constructor for the class and invoke initializeUI().


public function ButtonSample() { initializeUI(); }

5.

Create the initializeUI function to set up and initialize the UI controls.


private function initializeUI():void {

6.

In the initializeUI function, create a toggle button that calls the setSkin method.In the following code sample, the setSkin method takes the name of the custom skin class.
var myToggleButton:Button; myToggleButton = new Button(); myToggleButton.setPosition(200, 200); myToggleButton.setSize(100, 50); myToggleButton.toggle = true; myToggleButton.setSkin(CustomButtonSkin); addChild(myToggleButton);

7.

In the initializeUI function, create a label button that calls the setSkin method.
var myLabelButton:LabelButton; myLabelButton = new LabelButton(); myLabelButton.setPosition(200, 300); myLabelButton.setSize(150, 50); myLabelButton.label = "My Label Button"; myLabelButton.setSkin(CustomButtonSkin); } addChild(myLabelButton);

8.

Build and run the application. The buttons are rounded and the colours appears as you defined them the custom skin class. When you click the buttons, notice that each button state is also skinned.

Code sample: Creating a custom button skin


This code sample contains a small sample application that uses a custom button skin class. When you build and run this sample application, you must make sure that both the ButtonSample class and the CustomButtonSkin class are located in the same source project. Otherwise, you must import the CustomButtonSkin class into your sample application.

98

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

The sample application ButtonSample creates two buttons and adds them to the stage. Each button calls the setSkin method to set the custom skin CustomButtonSkin class as the button skin.
package { import flash.display.Sprite; import flash.events.MouseEvent; import qnx.ui.buttons.Button; import qnx.ui.buttons.LabelButton; [SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] public class ButtonSample extends Sprite { private var myToggleButton:Button; private var myLabelButton:LabelButton; public function ButtonSample() { initializeUI(); } private function initializeUI():void { myToggleButton = new Button(); myToggleButton.setPosition(200, 200); myToggleButton.setSize(100, 50); myToggleButton.toggle = true; myToggleButton.setSkin(CustomButtonSkin); addChild(myToggleButton); myLabelButton = new LabelButton(); myLabelButton.setPosition(200, 300); myLabelButton.setSize(150, 50); myLabelButton.label = "My Label Button"; myLabelButton.setSkin(CustomButtonSkin); addChild(myLabelButton); } }

The CustomButtonSkin class is listed below.


package { import flash.display.Sprite; import flash.geom.Rectangle; import qnx.ui.skins.SkinAssets;

99

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

import qnx.ui.skins.SkinStates; import qnx.ui.skins.UISkin; public class CustomButtonSkin extends UISkin { /** @private **/ protected var upSkin:Sprite; /** @private **/ protected var selectedSkin:Sprite; /** @private **/ protected var disabledSkin:Sprite; /** @private **/ protected var downSkin:Sprite; /** @private **/ protected var gridRect:Rectangle; public function CustomButtonSkin() { super(); } override protected function initializeStates():void { gridRect = new Rectangle(8,8,30,30); upSkin = new Sprite(); upSkin.graphics.beginFill(0xFF6600); upSkin.graphics.drawRoundRect(0,0,50,50, 10,10); upSkin.graphics.endFill(); upSkin.scale9Grid = gridRect; downSkin = new Sprite(); downSkin.graphics.beginFill(0x333333); downSkin.graphics.drawRoundRect(0,0,50,50, 10,10); downSkin.graphics.endFill(); downSkin.scale9Grid = gridRect; disabledSkin = new Sprite(); disabledSkin.graphics.beginFill(0xCC0000); disabledSkin.graphics.drawRoundRect(0,0,50,50, 10,10); disabledSkin.graphics.endFill(); disabledSkin.scale9Grid = gridRect; selectedSkin = new Sprite(); selectedSkin.graphics.beginFill(0x000000); selectedSkin.graphics.drawRoundRect(0,0,50,50, 10,10); selectedSkin.graphics.endFill(); selectedSkin.scale9Grid = gridRect; setSkinState(SkinStates.UP, upSkin); setSkinState(SkinStates.SELECTED,selectedSkin); setSkinState(SkinStates.DISABLED, disabledSkin); setSkinState(SkinStates.DOWN, downSkin);

100

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

showSkin(upSkin); } }

101

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Capturing text input

12

The qnx.ui.text package contains the classes required for displaying text on the screen and for gathering text input from the user. The Label class enables you to display formatted text within your application. The Label class cannot be used to gather text input, and it cannot get input focus. The TextInput class enables you to create a text input field that the user can use to enter text. When a TextInput instance gains focus, the virtual keyboard automatically appears enabling the user to enter text into the field. You can define the type of keyboard that appears, depending on the context of the current application.

Create a text input field


When the user clicks in a text input field, the virtual keyboard appears. You can define the type of keyboard for each text input field. The keyboard type defines the layout of the keyboard, including the types of keys, and the Return key type. The following task demonstrates how to create a text input field that enables the following keyboard.

1.

Import the required classes.


import import import import import flash.display.Sprite; qnx.ui.text.KeyboardType; qnx.ui.text.ReturnKeyType; qnx.ui.text.TextInput; qnx.ui.text.TextInputIconMode;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class TextInputSample extends Sprite {

4.

Create a constructor for your class and invoke initializeUI().

102

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

public function TextInputSample() { initializeUI(); }

5.

Create the initializeUI function to set up and initialize the UI controls.


private function initializeUI():void {

6.

In the initializeUI function, instantiate the TextInput class and position the control on the stage.
var myInput:TextInput = new TextInput(); myInput.setPosition(200, 200); myInput.width = 300;

7.

In the initializeUI function, set the keyboard type and keyboard Enter key type. In the following code sample, the text input field is used to type a URL to connect to a remote server. The URL keyboard is specified (by specifying the KeyboardType.URL constant), and the Enter key is set to use the Connect key.
myInput.keyboardType = KeyboardType.URL; myInput.returnKeyType = ReturnKeyType.CONNECT;

8.

In the initializeUI function, set the clearIconMode property. By default, the text input field contains a clear icon that the user can click to clear the text input field. The icon is enabled by default, however you can define when the icon will be available to the user.
myInput.clearIconMode = TextInputIconMode.UNLESS_EDITING;

9.

In the initializeUI function, add the text input field to the stage.
} this.addChild(myInput);

103

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Creating dialog boxes

13

Your application can prompt users when your application state changes. For example, if a user is one of the top scoring players in a game application, you can prompt them to add their name to the leaderboard. You can use one of the pre-defined dialog boxes in the qnx.dialog package to communicate with your user. To optimize visibility for a dialog box in the context of your application, you can control the size, position, and alignnment of a dialog box on the screen. You can set the values for size, position, and alignment by using the contstant values provided in the other classes in the qnx.dialog package. Dialog box
AlertDialog LoginDialog PasswordChangeDialog PopupList PromptDialog

Description This dialog box presents a message and a series of buttons. This dialog box presents two text input boxes, a check box, and a series of buttons. This dialog box presents three text input boxes and a series of buttons. This dialog box presents a list of and a series of buttons. This dialog box presents a text input box and a series of buttons.

When you want to display your dialog, ensure that you pass IowWindow.getAirWindow().group as a parameter when you invoke the show() method. This restricts the dialog box to lock your application only. If you do not specify the window group using the IowWindow class, your dialog will lock the user interface for the tablet until your user dismissis it.
myDialog.show(IowWindow.getAirWindow().group)

For more information about setting properties of the dialog box, see the API Reference for the BlackBerry Tablet OS SDK for Adobe AIR.

Customizing buttons in a dialog box


The appearance of a dialog box is controlled by the BlackBerry Tablet OS. However, you can customize the appearance and behaviour of buttons in a dialog box by invoking Dialog.setButtonPropertyAt() specifying the following parameters: Parameter Property name Value Value Provide one of the constants found in the DialogButtonProperty class. Provide an object that is appropriate to the type of property you want to apply. For example, if you specify the ENABLED property in the first parameter, you must pass a boolean value in this parameter. Similarly, if you specify the SKIN property, you must pass an object that implements the ISkin interface.

104

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Parameter Index

Value Provide the index of the button to which you want to apply the property that you specified in the first parameter. The Adobe AIR runtime assigns an index of 0 to your first button.

Create a dialog box


1. Import the required classes and interfaces.
import import import import import import flash.display.Sprite; flash.events.Event; flash.events.MouseEvent; qnx.dialog.*; qnx.ui.buttons.LabelButton; qnx.ui.text.*;

2.

Add the following statement to your class before the class declaration. This statement sets the width, height, frame rate, and background color of the Stage.
[SWF(width="1024", height="600", backgroundColor="#cccccc", frameRate="30")]

3.

Create an application framework by extending the Sprite class.


public class DialogDemo extends Sprite { public function DialogDemo() { } }

4.

Create an instance variable that refers to a Label object. This label reports which button on the dialog the user presses. Add this statement to your application framework, before your constructor.
private var lblWhichButton:Label = new Label();

5.

Create the initializeUI() method to setup and initialize the UI components.


private function initializeUI():void { }

6.

In initializeUI(), add a button to invoke your dialog box, and center the button on the screen.
var btnShowDialog:LabelButton = new LabelButton(); btnShowDialog.label = "Click here"; btnShowDialog.x = (stage.stageWidth - btnShowDialog.width)/2; btnShowDialog.y = (stage.stageHeight - btnShowDialog.height)/2;

7.

Add an event listener to your button to capture click events. Invoke the ButtonClicked() method when the BlackBerry Tablet OS SDK reports a click event.
btnShowDialog.addEventListener(MouseEvent.CLICK, buttonClicked);

105

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

8.

In initializeUI(), configure the label object you created in step 4. Center the label on the Stage below the button.
lblWhichButton.x = (stage.stageWidth - btnShowDialog.width)/2; lblWhichButton.y = btnShowDialog.y + btnShowDialog.height; lblWhichButton.width = 600; lblWhichButton.text = "";

9.

In initializeUI(), add the button and label to the Stage.


addChild(btnShowDialog); addChild(lblWhichButton);

10. In the constructor for your class, invoke initializeUI().


initializeUI();

11. Create the ButtonClicked() method to respond to click events on your button.
public function ButtonClicked(event:Object):void { }

12. In ButtonClicked(), create an AlertDialog object.


var myDialog:AlertDialog = new AlertDialog(); myDialog.title = "Dialog"; myDialog.message = "This is a small alert dialog"; myDialog.addButton("OK"); myDialog.addButton("Cancel"); myDialog.dialogSize = DialogSize.SIZE_SMALL;

13. Add an event listener to the button in the dialog box to capture click events. Invoke the alertButtonClicked() method when the BlackBerry Tablet OS SDK reports a click event.
myDialog.addEventListener(Event.SELECT, alertButtonClicked);

14. Display the dialog box for the user. myDialog.show(IowWindow.getAirWindow().group)


myDialog.show(IowWindow.getAirWindow().group);

15. Create the alertButtonClicked() method to respond to click events in the dialog.
public function alertButtonClicked(event:Object):void { }

16. In alertButtonClicked(), update the value of the label on the Stage when the user clicks on a button in the dialog.
lblWhichButton.text = "Index of button Clicked: " + e.target.selectedIndex;

After you finish: For a complete code sample, see "Code sample: Create a dialog box".

106

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Code sample: Creating a dialog box


package { import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import qnx.dialog.*; import qnx.display.IowWindow; import qnx.ui.buttons.LabelButton; import qnx.ui.text.*; [SWF(width="1024", height="600", backgroundColor="#cccccc", frameRate="30")] public class Dialogs extends Sprite { private var lblWhichButton:Label = new Label(); public function Dialogs() { var btnShowDialog:LabelButton = new LabelButton(); btnShowDialog.label = "Click here"; btnShowDialog.x = (stage.stageWidth - btnShowDialog.width)/2; btnShowDialog.y = (stage.stageHeight - btnShowDialog.height)/2; btnShowDialog.addEventListener(MouseEvent.CLICK, ButtonClicked); lblWhichButton.x = (stage.stageWidth - btnShowDialog.width)/2; lblWhichButton.y = btnShowDialog.y + btnShowDialog.height; lblWhichButton.width = 600; lblWhichButton.text = "Button index reported here."; addChild(btnShowDialog); addChild(lblWhichButton);

public function ButtonClicked(event:Object):void { var myDialog:AlertDialog = new AlertDialog(); myDialog.dialogSize = DialogSize.SIZE_SMALL; myDialog.addEventListener(Event.SELECT, alertButtonClicked); myDialog.title = "Dialog"; myDialog.message = "This is a small alert dialog"; myDialog.addButton("OK"); myDialog.addButton("Cancel"); myDialog.show(IowWindow.getAirWindow().group); } public function alertButtonClicked(event:Object):void { lblWhichButton.text = "Button Clicked Index: " + event.target.selectedIndex; }

107

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Responding to events and gestures

14

The most common events are those generated by a user. When a user touches the screen or tilts the BlackBerry PlayBook tablet, BlackBerry Tablet OS sends your application a notification of the event. Other events are generated by the BlackBerry Tablet OS. For example, if the battery power level is low, the BlackBerry Tablet OS attempts to notify all applications. The BlackBerry Tablet OS passes event information to your application by using the Adobe Flash event model. In the Flash event model, the BlackBerry Tablet OS attempts to notify an object about an event. If the event is not processed, the BlackBerry Tablet OS notifies the next object in the object hierarchy until the event is processed. You can add an event handler to any object by invoking addEventListener(). For example, when you create a button you can add an event handler:
myButton.addEventListener(event, method)

When the event specified by the event parameter occurs, the BlackBerry Tablet OS invokes the method specified by the method parameter Most applications should listen for low battery power level, low available memory, and foreground status events. For more information about those events, see Managing your application through the application life cycle. The following table describes some of the API packages related to events. For more information, see the API reference for BlackBerry Tablet OS or the Adobe ActionScript 3.0 Reference for the Adobe Flash Platform. API package
qnx.events

qnx.ui.events flash.events

Description This package contains event classes that you can use to capture BlackBerry Tablet OS specific events (for example, low battery power level, and requests to release the media service connection). This package contains event classes that you can use to capture events related to BlackBerry Tablet OS UI components. This package contains event classes that you can use to capture events that are generated by the Adobe AIR runtime, events related to application state (foreground, background), geolocation, and the accelerometer. You can use this package to detect the following gestures: Pan Rotate Swipe Zoom Hold and press Two finger tap

108

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Respond to an event
The following steps demonstrate how to respond to a swipe gesture. 1. Import the required classes and interfaces.
import import import import flash.display.Sprite; flash.events.TransformGestureEvent; flash.ui.Multitouch; flash.ui.MultitouchInputMode;

import qnx.ui.text.Label;

2.

Add the following statement to your class before the class declaration. This statement sets the width, height, frame rate, and background color of the Stage.
[SWF(width="1024", height="600", backgroundColor="#cccccc", frameRate="30")]

3.

Create an application framework by extending the Sprite class.


public class SwipeDemo extends Sprite { public function SwipeDemo() { } }

4.

Create an instance variable that refers to a Label object. This label reports the direction that the user swipes. Add this statement to your application framework, before your constructor.
private var _lblStatus:Label = new Label();

5.

Create the initializeUI() method to setup and initialize the UI components.


private function initializeUI():void { }

6.

In initializeUI(), configure the label object you created in step 5.Center the label on the screen and add it to the Stage.
lblStatus.y = (stage.stageHeight - lblStatus.height)/2; lblStatus.x = (stage.stageWidth - lblStatus.width)/2; lblStatus.width = stage.stageWidth; lblStatus.text = "Drag your finger across the screen"; addChild(lblStatus);

7. 8.

In initializeUI(), set the input mode to GESTURE.


Multitouch.inputMode = MultitouchInputMode.GESTURE;

In initializeUI(), add an event listener for swipe gestures. Invoke the onSwipe() method when the BlackBerry Tablet OS SDK reports a swipe gesture.
stage.addEventListener(TransformGestureEvent.GESTURE_SWIPE, onSwipe);

109

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

9.

In the constructor for your class, invoke initializeUI().


initializeUI();

10. Create the onSwipe() method to process the event.


public function onSwipe(event:TransformGestureEvent):void { }

11. In onSwipe(), create a String variable to hold the interpretation of the swipe event.
var strSwipe:String = "";

12. In onSwipe(), test the event's offsetX property to determine if the user swiped left.
if ( event.offsetX == -1 ) strSwipe = "Swipe direction: Left";

13. Create tests to detect swipes in other directions.


if ( event.offsetX == 1 ) strSwipe = "Swipe direction: Right"; if ( event.offsetY == -1 ) strSwipe = "Swipe direction: Up"; if ( event.offsetY == 1 ) strSwipe = "Swipe direction: Down";

14. Set the text property of the Label on the Stage to display the interpretation of the swipe event.
lblStatus.text = strSwipe;

After you finish: For a complete code sample, see "Code Sample: Detect a swipe gesture event".

Code sample: Detecting a swipe gesture event

package { import import import import

flash.display.Sprite; flash.events.TransformGestureEvent; flash.ui.Multitouch; flash.ui.MultitouchInputMode;

import qnx.ui.text.Label;

110

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

[SWF(width="1024", height="600", backgroundColor="#cccccc", frameRate="30")] public class SwipeDemo extends Sprite { private var lblStatus:Label = new Label(); public function SwipeDemo() { lblStatus.y = (stage.stageHeight - lblStatus.height)/2; lblStatus.x = (stage.stageWidth - lblStatus.width)/2; lblStatus.width = stage.stageWidth; lblStatus.text = "Drag your finger across the screen"; addChild(lblStatus); Multitouch.inputMode = MultitouchInputMode.GESTURE; stage.addEventListener(TransformGestureEvent.GESTURE_SWIPE, onSwipe); } public function onSwipe(event:TransformGestureEvent):void { var strSwipe:String = ""; if if if if } ( ( ( ( event.offsetX event.offsetX event.offsetY event.offsetY == == == == -1 ) strSwipe = "Swipe direction: Left"; 1 ) strSwipe = "Swipe direction: Right"; -1 ) strSwipe = "Swipe direction: Up"; 1 ) strSwipe = "Swipe direction: Down";

lblStatus.text = strSwipe;

111

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Code sample: Detecting a multitouch gesture event

package { import import import import import import import

flash.display.Graphics; flash.display.Sprite; flash.events.TouchEvent; flash.events.TransformGestureEvent; flash.ui.Multitouch; flash.ui.MultitouchInputMode; flash.utils.Dictionary;

[SWF(width="1024", height="600", backgroundColor="#cccccc", frameRate="30")] public class MultiTouchDemo extends Sprite { private var lineColors:Array = [0x731931, 0x401323, 0x262226, 0x54594C, 0x888C65]; private var lines:Dictionary = new Dictionary(); private var touchPointCount:int = 0; public function MultiTouchDemo() { Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT; stage.addEventListener(TouchEvent.TOUCH_BEGIN, onTouchBegin); stage.addEventListener(TouchEvent.TOUCH_MOVE, onTouchMove); stage.addEventListener(TouchEvent.TOUCH_END, onTouchEnd); } public function onTouchBegin(event:TouchEvent):void 112

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

var tPoint:Sprite = new Sprite(); addChild(tPoint); tPoint.graphics.lineStyle(5, lineColors[touchPointCount]); tPoint.graphics.moveTo( event.localX , event.localY); touchPointCount++; lines[event.touchPointID] = tPoint;

} public function onTouchMove(event:TouchEvent):void { var tPoint:Sprite = lines[event.touchPointID] as Sprite; tPoint.graphics.lineTo(event.localX, event.localY); } public function onTouchEnd(event:TouchEvent):void { var tPoint:Sprite = lines[event.touchPointID] as Sprite; this.removeChild(tPoint); touchPointCount--; delete lines[event.touchPointID]; } }

Code sample: Detecting a rotation gesture event


package { import import import import flash.display.Sprite; flash.events.TransformGestureEvent; flash.ui.Multitouch; flash.ui.MultitouchInputMode

[SWF(width="1024", height="600", backgroundColor="#cccccc", frameRate="30")] public class RotateDemo extends Sprite { private var _rotateMe:Sprite = new Sprite(); public function RotateDemo() { Multitouch.inputMode = MultitouchInputMode.GESTURE; _rotateMe.graphics.lineStyle(1,0x83A603); _rotateMe.graphics.beginFill(0xE9D303); _rotateMe.graphics.drawRoundRect(0,0,100,100,20); _rotateMe.graphics.endFill(); _rotateMe.x = (stage.stageWidth - rotateMe.width) /2; _rotateMe.y = (stage.stageHeight - rotateMe.height) /2;

113

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

addChild(rotateMe); } rotateMe.addEventListener( TransformGestureEvent.GESTURE_ROTATE, onRotate );

public function onRotate(event:TransformGestureEvent):void { _rotateMe.rotation += event.rotation; }

114

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Localizing your application and using resource bundles

15

The BlackBerry Tablet OS SDK provides support for localization. You can use the classes in the qnx.locale package to localize your application, load locale-specific images, or load a resource bundle to provide flexibility to a control. The BlackBerry PlayBook tablet sets and maintains a locale value at run time. The locale value represents the language of the current user. You can create a resource bundle for each locale that contains a set of key-value pairs for each locale-specific string in your application. Your application can listen for locale changes, then load locale-specific resources to reflect the user's current locale. You can also include graphic assets in your application's locale folders to load specific images for a given locale. Resource bundles are loaded asynchronously and your application can only load a resource string after a resource bundle has finished loading. The Event.CHANGE event is dispatched only after the reource bundles have loaded, thus decreasing the likelihood that your application will reference a missing resource. In addition to providing locale support, you can use a resource bundle to change the context of a given control, regardless of the locale of the device or application. For example, the keyboard uses resource bundles to load a unique set of key characters depending on the context of the keyboard. The following table provides a brief description of the qnx.locale package. Class
Locale LocaleManager

LocaleResourceBundle

Description You can use the Locale class to represent the locale of the device. You can use the LocaleManager class to interact with the device locale, set the locale of your application, listen for locale change events, and set and return the path to the locale-specific reource bundle. The LocaleResourceBundle class represents the files that contain the resource strings that you can create to provide locale-specific text for your application.

Creating a resource bundle


A resource bundle is a text file that contains key-value pairs. You can translate the text in the foreign language resource bundles to localize the text in your application. In your application source code, you can reference a key in a resource bundle to return a String value. The following code sample shows an English language resource bundle for an application. Each line of the list follows the form key=value.
list-tomato=Tomato list-potato=Potato list-asparagus=Asparagus list-bacon=Bacon list-celery=Celery list-corn=Corn label-title=Grocery List

115

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

The following code sample demonstrates how an application would use a resource bundle. The code statement sets a button label by calling the localeManager.getResource method and passing in the label-title key.
myLabel.text = LocaleManager.localeManager.getResource("label-title");

You can include a resource bundle in your application by creating a locale folder structure in the source folder of your application. The path to the locale folder is relative to your application's .swf file. If you use Adobe Flash Builder as your IDE, you should place the locale folder in the bin-debug folder of your application source directory. By default, Flash Builder does not copy your .properties file to your output folder. You can modify the settings in the File Exclusions preferences, or you can use a build script to copy your locale folder into the root directory of your application at build time. Within the locale folder, you must create a subfolder for each locale that your application supports. Each subfolder must be a valid locale code. The following screen capture shows an application that contains resources for the US English (en_US) and France French (fr_FR) locales. There are no naming restrictions for the bundle.

116

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

For more information about loading and using resource bundles, see Load a resource bundle.

Localize an application
1. Import the required classes and interfaces.
import flash.display.Sprite; import flash.events.Event; import qnx.locale.LocaleManager; import qnx.ui.data.DataProvider;

117

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

import qnx.ui.listClasses.List; import qnx.ui.listClasses.ListSelectionMode; import qnx.ui.text.Label;

2.

Add the following statement to your class before the class declaration. This statement sets the width, height, frame rate, and background color of the Stage.
[SWF(width="1024", height="600", backgroundColor="#cccccc", frameRate="30")]

3.

Create an application framework by extending the Sprite class.


public class MyLocaleChangeSample extends Sprite {

4.

Create instance variables to store a List object, a Label object, and a data provider.
private var myList:List; private var myLabel:Label; private var myDP:DataProvider;

5.

Create a constructor for your class and invoke the initializeUI() method. Also, initialize your data provider.
public function MyLocaleChangeSample() { initializeUI(); myDP = new DataProvier(); }

6.

Create initializeUI() and instantiate a LocaleManager object. In the following code sample, an event listener is added to listen for locale change events.
private function initializeUI():void { //Listen for locale changes. var lm:LocaleManager = LocaleManager.localeManager; lm.addEventListener(Event.CHANGE, onLocaleChange);

7.

Create a label and a list. The Label and List instances will reference Strings in the resource bundle.
myLabel = new Label(); myLabel.setPosition(100, 150); stage.addChild(myLabel); myList = new List(); myList.setPosition(100, 200); myList.width = 400; myList.height = 500; myList.selectionMode = ListSelectionMode.MULTIPLE; stage.addChild(myList); }

8.

Create the onLocaleChange() method. The event listener calls onLocaleChange() function when the device locale changes.
private function onLocaleChange(event:Event):void {

118

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

9.

Add items to your data provider and set the text property of the LabelButton. In this step, the getResource() method is called to return the string that is associated with the specified resource key. The localeManager class returns the resources that are defined for the current locale. This code sample assumes that the resource bundles are present at runtime.
myDP.setItems([{label: {label: {label: {label: {label: {label: LocaleManager.localeManager.getResource("list-tomato")}, LocaleManager.localeManager.getResource("list-potato")}, LocaleManager.localeManager.getResource("list-asparagus")}, LocaleManager.localeManager.getResource("list-bacon")}, LocaleManager.localeManager.getResource("list-celery")}, LocaleManager.localeManager.getResource("list-corn")}]);

myLabel.text = LocaleManager.localeManager.getResource("label-title");

10. Set the dataProvider property of your list to the DataProvider object you populated in step 9.
} myList.dataProvider = myDP;

Code sample: Localizing an application


The following code sample demonstrates how to build localization support into an application.
package { import flash.display.Sprite; import flash.events.Event; import import import import import qnx.locale.LocaleManager; qnx.ui.data.DataProvider; qnx.ui.listClasses.List; qnx.ui.listClasses.ListSelectionMode; qnx.ui.text.Label;

[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] public class MyLocaleChangeSample extends Sprite { private var myList:List; private var myLabel:Label; private var myDP:DataProvider; public function MyLocaleChangeSample() { initializeUI(); myDP = new DataProvider(); } private function initializeUI():void { //Listen for locale changes. var lm:LocaleManager = LocaleManager.localeManager; lm.addEventListener(Event.CHANGE, onLocaleChange); //Create a label. myLabel = new Label(); myLabel.setPosition(100, 150);

119

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

stage.addChild(myLabel); //Create a list. myList = new List(); myList.x = 100 myList.y = 100; myList.width = 400; myList.height = 500; myList.selectionMode = ListSelectionMode.MULTIPLE; stage.addChild(myList);

//This function is called when the locale of the device changes. private function onLocaleChange(event:Event):void { myDP.setItems([{label: LocaleManager.localeManager.getResource("list-tomato")}, {label: LocaleManager.localeManager.getResource("list-potato")}, {label: LocaleManager.localeManager.getResource("list-asparagus")}, {label: LocaleManager.localeManager.getResource("list-bacon")}, {label: LocaleManager.localeManager.getResource("list-celery")}, {label: LocaleManager.localeManager.getResource("list-corn")}]); myList.dataProvider = myDP; myLabel.text = LocaleManager.localeManager.getResource("label-title");

Load a resource bundle


1. Import the required classes and interfaces.
import flash.display.Sprite; import flash.events.Event; import import import import qnx.locale.LocaleManager; qnx.locale.LocaleResourceBundle; qnx.ui.buttons.SegmentedControl; qnx.ui.data.DataProvider;

2.

Add the following statement to your class before the class declaration. This statement sets the width, height, frame rate, and background color of the Stage.
[SWF(width="1024", height="600", backgroundColor="#cccccc", frameRate="30")]

3.

Create an application framework by extending the Sprite class.


public class MyLocaleSample extends Sprite {

4.

Create an instance variable that refers to a SegmentedControl and a DataProvider. This SegmentedControl object uses resource strings to create button labels.
private var mySegmented:SegmentedControl; private var myDP:DataProvider;

5.

Create a constructor for your class and invoke the initializeUI() method and initialize your data provider.

120

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

public function MyLocaleSample() { initializeUI(); myDP = new DataProvider(); }

6.

Create initializeUI() and instantiate the SegmentedControl object.


private function initializeUI():void { mySegmented = new SegmentedControl(); mySegmented.setPosition(100, 200); mySegmented.width = 700; mySegmented.height = 50; stage.addChild(mySegmented);

7.

Create a LocaleResourceBundle instance and add an event listener. In the following code sample, an event listener is added to listen for resource bundle load complete events. Resource bundles are loaded asynchronously, so you can only reference a resource string after your application finishes loading a resource bundle. Your application must listen for bundle load completion events. The Event.COMPLETE event is dispatched only after a resource bundle has loaded.
var MyBundle:LocaleResourceBundle = new LocaleResourceBundle(); MyBundle.addEventListener( Event.COMPLETE, onResourceLoad );

8.

Load the resource bundle for the current locale. In the following code sample, the load() method is called by passing in a compound string that comprises the directory name, the current device locale, and the file name of the resource bundle. The getCurrentLocale() method returns the current locale.
MyBundle.load(LocaleManager.getLocalePath() + "/resource.properties" );

9.

Create the onResourceLoad() function. The BlackBerry Tablet OS calls onResourceLoad() when it finishes loading the resource bundle. In the following code sample, onResourceLoad() stores the event as a LocaleResourceBundle object named bundle.
private function onResourceLoad(event:Event):void { trace(LocaleManager.localeManager.getCurrentLocale()); var bundle:LocaleResourceBundle = event.target as LocaleResourceBundle;

10. Add items to your data provider by passing in resource strings from the current resource bundle. The strings are passed into the function by calling the getResource() method. Assign your data provider to the SegmentedControl.dataProvider property.
myDP.setItems([{label: bundle.getResource("day-sunday")}, {label: bundle.getResource("day-monday")}, {label: bundle.getResource("day-tuesday")}, {label: bundle.getResource("day-wednesday")}, {label: bundle.getResource("day-thursday")}, {label: bundle.getResource("day-friday")}, {label: bundle.getResource("day-saturday")}]); mySegmented.dataProvider = myDP;

121

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Code sample: Loading a resource bundle


package { import flash.display.Sprite; import flash.events.Event; import import import import qnx.locale.LocaleManager; qnx.locale.LocaleResourceBundle; qnx.ui.buttons.SegmentedControl; qnx.ui.data.DataProvider;

[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] public class MyLocaleSample extends Sprite { private var mySegmented:SegmentedControl; private var myDP:DataProvider; public function MyLocaleSample() { initializeUI(); myDP = new DataProvider(); } private function initializeUI():void { //Load the resource bundle var MyBundle:LocaleResourceBundle = new LocaleResourceBundle(); MyBundle.addEventListener( Event.COMPLETE, onResourceLoad ); MyBundle.load( "locale/" + LocaleManager.localeManager.getCurrentLocale() + "/resource.properties" ); //Create a segmented control mySegmented = new SegmentedControl(); mySegmented.setPosition(100, 200); mySegmented.width = 700; mySegmented.height = 50; stage.addChild(mySegmented);

//This function is called when the resource bundle is loaded. private function onResourceLoad(event:Event):void { trace(LocaleManager.localeManager.getCurrentLocale()); //Store the incoming event target as a bundle. var bundle:LocaleResourceBundle = event.target as LocaleResourceBundle; //Update the buttons in the segmented control with the bundle resources myDP.setItems([{label: bundle.getResource("day-sunday")}, {label: bundle.getResource("day-monday")}, {label: bundle.getResource("day-tuesday")}, {label: bundle.getResource("day-wednesday")}, {label: bundle.getResource("day-thursday")}, {label: bundle.getResource("day-friday")}, {label: bundle.getResource("day-saturday")}]);

122

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

mySegmented.dataProvider = myDP;

123

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

In App Payments

16

The BlackBerry Tablet OS SDK enables you to use the same Payment Service that processes all purchases that users make in the BlackBerry App World storefront. You can use the classes in the net.rim.blackberry.payment package to create a highly secure and consistent purchase experience that allows users to buy digital goods without leaving your application. The net.rim.blackberry.events package contains events that allow your application to listen for successful or unsuccessful purchases. To sell digital goods from your application you must be a registered vendor with BlackBerry App World and your application containing digital goods must be distributed exclusively through BlackBerry App World. Digital goods go through a vetting process along with your applications. To sign up as a vendor, visit appworld.blackberry.com/ isvportal. Users can purchase digital goods using any of the payment types supported by BlackBerry App World. Payment types can include billing to the wireless service provider (if available), credit card, or PayPal.

License models
You can distribute digital goods in your application by using a number of different license models (some of which are supported by the Payment Service). Depending on the license models that your application uses, you might want to customize the way you present purchase options to reflect that digital goods were purchased already.

Consumable
Digital goods that are registered as consumable must be purchased by a user for each use. For example, in a virtual world simulation, you could sell tickets to a virtual attraction or feed for a virtual animal. The Payment Service server does not set any controls on the number of times that a user can purchase these goods.

One-time payment
Digital goods that are registered as one-time payment are purchased only once by a user. The Payment Service server blocks subsequent purchases by the user. In this scenario, you might want to provide a way for users to see their purchase history. By invoking the PaymentSystem.getExistingPurchases function, you can retrieve a record of a user's past purchases. When you offer a single-instance digital good, you must ensure that the digital goods are available through your application for a specific period of time after the user downloads the application. To view the required minimum time period in the Research In Motion SDK License agreement, visit http://us.blackberry.com/developers/legal.jsp. You must also make sure that digital goods are still available if the user reinstalls the application or switches devices. Digital goods aren't automatically restored, so it's up to you to make sure that users can download these digital goods again.

Subscription

124

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Digital goods that are registered as a subscription are purchased initially by a user, and the user is charged at regular intervals for continued use of the goods. When you register subscription-based digital goods, you must specify an initial fee and usage period, as well as a renewal fee and usage period. Users are charged the initial fee when they purchase the digital goods and can use the digital goods for the initial period of time. Users are then charged the renewal fee each time the usage period elapses so that they can continue to use the digital goods. You can implement a trial period for your subscription-based digital goods by not specifying an initial fee. Users can download your digital goods and use them free of charge for the trial period and are charged after the trial period ends. To purchase subscription-based digital goods in your application, users must be running BlackBerry App World storefront 3.0.

Free
The Payment Service doesn't provide support for free digital goods. Your application can distribute free digital goods, but you cannot use the Payment Service to process transactions for goods with no monetary value.

Registering digital goods with BlackBerry App World


When you submit an application for review in the BlackBerry App World vendor portal, you must also add the details about the digital goods that your application offers. You must provide the name, the SKU (the unique identifier for the digital goods), the license model (consumable or one-time payment), the pricing tier, and a description of the digital goods in each language that your application is available. If it is impractical to create a separate name and SKU for each of your digital goods, you can use the same name and SKU for multiple digital goods. For example, if you sell streaming video through your application, you could use one name and SKU for the digital goods that you sell at a particular price tier. In this scenario, you might register digital goods with the name "Video $4.99" and use the same SKU for every streaming video that you sell at the $4.99 pricing tier. This way you can update the purchase options without submitting a new version of your application. When you invoke the PaymentSystem.purchase() function, you can pass a metadata argument that allows you to differentiate between digital goods that reference the same SKU. For more information about submitting applications and digital goods, see the BlackBerry App World vendor documentation at www.blackberry.com/go/appworld/vendordocs/.

Creating an application that sells digital goods


Creating an application that sells digtal goods involves the following tasks: 1. 2. 3. 4. 5. Set up a UI Create a class to store the properties for your digital goods Retrieve and display a list of digital goods Initiate a purchase Check for past purchases

125

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

For a complete sample application, see Code sample: Creating an application that sells digital goods. The sample application displays a list of goods, a Buy button, and a Refresh button. You initiate a purchase of one of the digital goods by clicking the Buy button. You can retrieve an array of past successful purchases by clicking the Refresh button.

Set up the UI
This task demonstrates how create a simple UI that allows users to purchase digital goods from your application. 1. Import the required classes.
import import import import import flash.display.Sprite; flash.events.MouseEvent; net.rim.blackberry.payment.PaymentSystem; qnx.ui.buttons.LabelButton; qnx.ui.listClasses.List;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class PaymentServiceDemo extends Sprite {

4.

Declare a variable for PaymentSystem, which is the class that is required for invoking purchases. Declare variables for the list and buttons that you need to use to build your UI.
private private private private var var var var paymentSystem:PaymentSystem; buyList:List; buyButton:LabelButton; refreshButton:LabelButton;

5.

Create a constructor for your class. In the constructor, instantiate PaymentSystem and set the connection mode to local. Setting the connection mode to local prevents your application from processing purchases with the Payment Service server. All purchases are simulated within the application. In the constructor, invoke initializeUI().
public function PaymentServiceDemo() { paymentSystem = new PaymentSystem(); paymentSystem.setConnectionMode(PaymentSystem.CONNECTION_MODE_LOCAL); } initializeUI();

6.

Create the initializeUI function to setup and initialize the UI controls.


private function initializeUI():void {

7.

In the initializeUI function, instantiate the UI components, set the appropriate properties, and add the components to the stage. Set the selection mode on the list to permit single selections. Set an event listener on each button to listen for click events.

126

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

buyList = new List(); buyList.setPosition(25,25); buyList.width = 400; buyList.height = 250; buyList.columnWidth = 400; buyList.scrollable = true; buyList.allowDeselect = false; buyList.selectionMode = ListSelectionMode.SINGLE; this.addChild(buyList); buyButton = new LabelButton(); buyButton.setPosition(25, 305); buyButton.width = 150; buyButton.label = "Buy"; buyButton.addEventListener(MouseEvent.CLICK, purchaseHandler); this.addChild(buyButton); refreshButton = new LabelButton(); refreshButton.setPosition(180, 305); refreshButton.width = 150; refreshButton.label = "Refresh"; refreshButton.addEventListener(MouseEvent.CLICK, refreshHandler); } this.addChild(refreshButton);

8.

Create the purchaseHandler function. This function runs whens the Buy button dispatches a click event.
private function purchaseHandler(event:MouseEvent):void { }

9.

Create the refreshHandler function. This function runs whens the Refresh button dispatches a click event.
private function refreshHandler(event:MouseEvent):void { }

10. Run the application. When you run the application, only the buttons appear on the screen. Before the list can appear, you must specify a data provider for the list and populate the list with data.

Create a class to store the properties for your digital goods


Creating a separate class to store the properties for your digital goods isn't a requirement, but when you're dealing with large numbers of digital goods that you want to update dynamically, it can help you manage the data more efficiently. In this task, you create a class that is designed to store the properties for the digital goods that your application offers. 1. Create a new ActionScript class named DigitalGoodsInfo.
127

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

package valueObjects { public class DigitalGoodsInfo {

2.

Create public variables for each of the properties for your digital goods.
public public public public public var var var var var name:String; sku:String; metadata:String; icon:String; appName:String;

3.

Create the constructor for DigitalGoodsInfo. The constructor accepts strings for the name, sku, and metadata of the digital goods as parameters.
public function DigitalGoodsInfo( name:String, sku:String, metadata:String ) {

4.

In the constructor, set the values for the properties of the class to the values of the parameters that the constructor receives. Set the values of the icon and appName properties to default values.
this.name = name; this.sku = sku; this.metadata = metadata; icon = "http://www.rim.com/products/appworld_3col.jpg"; appName = "PaymentServiceDemo";

Retrieve and display a list of digital goods


Depending on your application, you might want to dynamically update the list of digital goods that your application offers. By maintaining a list of digital goods outside of your application, you can make updates without having to release a new version of your application. In this task, you: Retrieve data from a remote server by using an HTTPService call. Create an ArrayCollection of DigitalGoodsInfo objects. Populate the List object that you previously created using the names of the digital goods. 1. In PaymentServiceDemo, import the required classes. Make sure that you import the DigitalGoodsInfo class that you created.
import import import import import import mx.collections.ArrayCollection; mx.rpc.events.FaultEvent; mx.rpc.events.ResultEvent; mx.rpc.http.HTTPService; qnx.ui.data.DataProvider; valueObjects.DigitalGoodInfo;

128

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

2.

In the body of the PaymentServiceDemo class, add declarations for ArrayCollection and HTTPService variables. The array collection is required for storing the value objects that contain data about the digital goods that your application offers.
private var digitalGoods:ArrayCollection; private var httpService:HTTPService;

3.

In the initializeUI function, create an instance of the HTTPService class. Specify the URL for the location of the .xml file, and set event listeners to listen for ResultEvent.RESULT and FaultEvent.FAULT. HTTPService broadcasts one of these two events depending on whether the HTTPService call is successful or not. Invoke send() to send the HTTPService call.
this.addChild(refreshButton); httpService = new HTTPService(); httpService.url = "http://docs.blackberry.com/digitalgoods.xml"; httpService.addEventListener(ResultEvent.RESULT, resultHandler); httpService.addEventListener(FaultEvent.FAULT, faultHandler); httpService.send();

4.

Create the function resultHandler. This function runs when HTTPService broadcasts a result event.
private function resultHandler(event:ResultEvent):void {

5.

The ResultEvent object that this function receives has a result property, which contains the .xml data retrieved during the HTTPService call. In the resultHandler function, declare variables for an ArrayCollection and a DataProvider. Declare a variable for DigitalGoodsInfo, the class that you created to store the properties of digital goods.
var remoteData:ArrayCollection; var data:DataProvider; var dgObject:DigitalGoodsInfo;

6.

In the resultHandler function, populate the remoteData variable that you declared with the .xml data that the event.result property contains. In the following code sample, digitalgoods.digitalgood represents the hierarchy of the elements in the .xml file. The parent element in the .xml file is named <digitalgoods>, and it contains a series of children named <digitalgood>. The <digitalgood> elements contain the individual properties for each of the digital goods. The result of the following code sample is that each index in the array collection is populated with an object that contains a digitalgood element and all of its children elements.
remoteData = event.result.digitalgoods.digitalgood;

7.

For the complete contents of the digitalgoods.xml file, visit http://docs.blackberry.com/digitalgoods.xml. In the resultHandler function, instantiate the data provider, and set the data provider on the list that you created when you set up the UI. Instantiate the array collection that you created to contain the DigitalGoodsInfo objects.

129

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

data = new DataProvider(); buyList.dataProvider = data; digitalGoods = new ArrayCollection();

8.

In the resultHandler function, create a for each loop that iterates over each object in the array collection.
for each(var obj:Object in remoteData) {

9.

In the for each loop, create a new instance of DigitalGoodsinfo. Pass in the name, sku, and metadata from the current index of the array collection to the constructor. Add the new instance of DigitalGoodsinfo to the digitalGoods array collection. Add the name of the digital goods to the data provider for the list that you previously created.
dgObject = new DigitalGoodsInfo(obj.name, obj.sku, obj.metadata); digitalGoods.addItem(dgObject); buyList.dataProvider.addItem({label: obj.name});

10. After the for each loop has executed, and the names of the digital goods are all added to the list, set the current selection in the list to the first item.
} buyList.selectedIndex = 0;

11. Create the function faultHandler. This function runs when HTTPService broadcasts a fault event. In the faultHandler function, create a trace statement that notifies you if the application is unable to retrieve the data from the .xml file.
private function faultHandler(event:FaultEvent):void { trace("Unable to retrieve digital goods from the server."); }

12. Run the application. The list that you created is now populated with the names of the digital goods.

Initiate a purchase
When you're ready to charge your user's account for a purchase, call the PaymentSystem.purchase function. PaymentSystem.purchase takes a variety of arguments that include things like authentication with the Payment Service server, informatino about the digitals goods being purchased, and so on. To see a description of all the arguments, see Arguments for purchases. In this task, you: Define the functionality for the purchaseHandler function, which runs when the user presses the Buy button. Set event listeners to listen for successful and unsuccessful purchases. Define the functionality for when the purchase routine completes. 1. In PaymentServiceDemo, import the required classes.

130

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

import net.rim.blackberry.events.PaymentErrorEvent; import net.rim.blackberry.events.PaymentSuccessEvent; import net.rim.blackberry.payment.Purchase;

2.

In the purchaseHandler function, declare a variable called index. Set the value of index to the index of the row in the list that is currently selected.
private function purchaseHandler(event:MouseEvent):void { var index:int; index = buyList.selectedIndex;

3.

In the purchaseHandler function, invoke PaymentSystem.purchase(). From the array collection of DigitalGoodsInfo objects, get the properties of the object that is at the position in the array collection equivalent to the position of the list item that is currently selected. Pass in the properties as arguments to purchase().
paymentSystem.purchase(null, digitalGoods.getItemAt(index).sku, digitalGoods.getItemAt(index).name, digitalGoods.getItemAt(index).metadata, digitalGoods.getItemAt(index).appName, digitalGoods.getItemAt(index).icon);

4.

In the constructor, add some event listeners to listen for successful and unsuccessful purchase attempts.
paymentSystem.setConnectionMode(PaymentSystem.CONNECTION_MODE_LOCAL); paymentSystem.addEventListener(PaymentSuccessEvent.PURCHASE_SUCCESS, purchaseSuccessHandler); paymentSystem.addEventListener(PaymentErrorEvent.PURCHASE_ERROR, purchaseErrorHandler); } initializeUI();

5.

Create the purchaseSuccessHandler function. This function runs when PaymentSystem dispatches PaymentSuccessEvent.PURCHASE_SUCCESS.
private function purchaseSuccessHandler(event:PaymentSuccessEvent):void {

The PaymentSuccessEvent object that this function receives has a purchase property, which contains details about the successful purchase. 6. In the purchaseSuccessHandler function, declare a variable for Purchase, and set the value to the event.purchase property. Create a trace statement to display all of the details of the successful purchase.
var purchase:Purchase = event.purchase; trace("Purchase Success - " + purchase.date + " : " + purchase.digitalGoodID + " : " + purchase.digitalGoodSKU +

131

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

" : " + purchase.licenseKey + " : " + purchase.metaData + " : " + purchase.transactionID);

7.

In production, you might want to display an alert to the user indicating that the purchase is a success. Create the purchaseErrorHandler function. This function runs when PaymentSystem dispatches PaymentErrorEvent.PURCHASE_ERROR.
private function purchaseErrorHandler(event:PaymentErrorEvent):void {

8.

The PaymentErrorEvent object that this function receives has an errorID property, which contains an integer representing the type of error, and a text property, which contains a human-readable error message. In the purchaseErrorHandler function, create a trace statement to display the error ID and the error message.
} trace("Purchase Error - " + event.errorID + " : " + event.text);

In production, you might want to handle some errors differently from others. For example, if the purchase fails because the user cancels the purchase, you might not want to do anything, while if the purchase fails because of an error with the server, you might want to display an alert that indicates that. 9. Run the application. 10. After the application starts, select one of the digital goods and press Buy. If the connection mode for the application is set to PaymentSystem.CONNECTION_MODE_LOCAL, the confirmation dialog that you see is different from the dialog that users see when the application is in production. If the application is configured for testing, the dialog displays a drop-down list that allows you specify the result that you want for the test purchase. This enables you test the responses you can expect from the Payment Service so that you can test whether your application handles the responses the way you intend.

Arguments for purchases


The following table describes the arguments that you can pass to PaymentEngine.purchase(). Argument
digitalGoodSKU

Description Required argument (can be substituted with the ID). An identifier that you assign to digital goods when you register the digital goods in the BlackBerry App World vendor portal. An alphanumeric string that can contain hyphens (-) and underscores (_), must not contain only numbers, and is 5 to 100 characters in length. If specified along with the ID, the SKU is ignored. Required argument (can be substituted with the SKU). An identifier that the vendor portal assigns to your digital goods after you register the digital goods in the vendor portal. If specified along with the SKU, the SKU is ignored.

digitalGoodID

132

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Argument
digitalGoodName

Description Optional argument. A name that overrides the name that you specified for the digital goods when you registered the digital goods in the vendor portal (the registered name might be a generic name that describes an entire batch of digital goods). Appears on the purchase confirmation dialogs in your application to provide users with context for what they are purchasing. Optional argument. A unique identifier that is required if you need to differentiate between the digital goods that reference the same SKU (for example, if your application sells eBooks, the identifier could be an ISBN number). Returned with each Purchase object when you make a getExistingPurchases() call. Optional argument. Overrides the application name retrieved from the application descriptor. Should always be specified if the name of the application, as it appears on the Home screen of the device, can change dynamically (for example, if the application name changes when the icon for the application receives focus). Appears on the purchase confirmation dialogs in your application to provide users with context for what they are purchasing. Optional argument Overrides the icon for the application that the purchase request originates from Should always be specified if the icon for the application, as it appears on the Home screen of the device, can change dynamically (for example, if the icon changes when new content is available in the application). Appears on the purchase confirmation dialogs in your application to provide users with context for what they are purchasing.

metadata

purchaseAppName

purchaseAppIcon

Check for existing purchases


Records of a user's past purchases are stored in a file on the device, and on the Payment Service server. Identifying a user's past purchases is necessary if you need to perform any of the following tasks: Modify the UI of your application to reflect past purchases. Implement a subscription model for your digital goods. Redistribute digital goods to users that switch devices. The PaymentSystem.getExistingPurchases function accepts a Boolean argument named allowRefresh. If you specify true for allowRefresh, the function tries to retrieve the purchase history from the Payment Service server.

133

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

The purchases history on the device could be out of date for a variety reasons, including a device switch. As a best practice, you should invoke getExistingPurchases(true) each time your application starts. If the user has switched devices, you can use the updated array of purchases to make sure that all of the user's past purchases are made available. In this task, you invoke getExistingPurchases(false) to retrieve the array of existing purchases from the device. 1. In the refreshHandler function, invoke getExistingPurchases(). Pass in false as an argument so that the application doesn't attempt to refresh the array of past purchases with the server.
private function purchaseHandler(event:MouseEvent):void { paymentSystem.getExistingPurchases(false); }

2.

If your application is configured for local testing, and you attempt to refresh the array of existing purchases with the server, getExistingPurchases throws an error. In the constructor, add event listeners to listen for successful and unsuccessful attempts at retrieving the array of existing purchases.
paymentSystem.addEventListener( PaymentSuccessEvent.GET_EXISTING_PURCHASES_SUCCESS, getPurchasesSuccessHandler); paymentSystem.addEventListener( PaymentErrorEvent.GET_EXISTING_PURCHASES_ERROR, getPurchasesErrorHandler); } initializeUI();

3.

Create the getPurchasesSuccessHandler function. This function runs when PaymentSystem dispatches PaymentSuccessEvent.GET_EXISTING_PURCHASES_SUCCESS. The PaymentSuccessEvent object has an existingPurchases property that contains an array of Purchase objects. Each of those objects represent a successful purchase.
private function getPurchasesSuccessHandler(event:PaymentSuccessEvent):void {

4.

In the getPurchasesSuccessHandler function, declare a variable for Purchase. Declare a variable for an array, and set the value to the event.existingPurchases property. Create a for loop that iterates through each position in the array of purchases.
var purchase:Purchase; var pastPurchases:Array = event.existingPurchases; for (var i:int = 0; i < pastPurchases.length; i++) {

5.

In the for loop, get the Purchase object from the current position in the array. Create a trace statement to display all of the details of the successful purchase.

134

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

purchase = pastPurchases[i]; trace("Get Existing Purchases Success - " + purchase.date + " : " + purchase.digitalGoodID + " : " + purchase.digitalGoodSKU + " : " + purchase.licenseKey + " : " + purchase.metaData + " : " + purchase.transactionID);

6.

Create the getPurchasesErrorHandler function. This function runs when PaymentSystem dispatches PaymentSuccessEvent.GET_EXISTING_PURCHASES_SUCCESS. Create a trace statement to display the error ID and error message associated with the event.
private function getPurchasesErrorHandler(event:PaymentErrorEvent):void { trace("Get Existing Purchases Error - " + event.errorID + " : " + event.text); }

7. 8. 9.

Debug the application. After the application starts, initiate a series of successful purchases. Press the Refresh button. The console displays information for each of the previous successful purchases.

Code sample: Creating an application that sells digital goods


PaymentServiceDemo.as
package { import flash.display.Sprite; import flash.events.MouseEvent; import import import import import import import import import import import import mx.collections.ArrayCollection; mx.rpc.events.FaultEvent; mx.rpc.events.ResultEvent; mx.rpc.http.HTTPService; net.rim.blackberry.events.PaymentErrorEvent; net.rim.blackberry.events.PaymentSuccessEvent; net.rim.blackberry.payment.PaymentSystem; net.rim.blackberry.payment.Purchase; qnx.ui.buttons.LabelButton; qnx.ui.data.DataProvider; qnx.ui.listClasses.List; qnx.ui.listClasses.ListSelectionMode;

import valueObjects.DigitalGoodsInfo; [SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] // A simple application that offers digital goods 135

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

public class PaymentServiceDemo extends Sprite { private var paymentSystem:PaymentSystem; private var buyList:List; private var buyButton:LabelButton; private var refreshButton:LabelButton; private var digitalGoods:ArrayCollection; private var httpService:HTTPService; public function PaymentServiceDemo() { // configures the application for testing paymentSystem = new PaymentSystem(); paymentSystem.setConnectionMode(PaymentSystem.CONNECTION_MODE_LOCAL); // listeners for successful and unsuccessful payment events paymentSystem.addEventListener(PaymentSuccessEvent.PURCHASE_SUCCESS, purchaseSuccessHandler); paymentSystem.addEventListener(PaymentErrorEvent.PURCHASE_ERROR, purchaseErrorHandler); paymentSystem.addEventListener( PaymentSuccessEvent.GET_EXISTING_PURCHASES_SUCCESS, getPurchasesSuccessHandler); paymentSystem.addEventListener( PaymentErrorEvent.GET_EXISTING_PURCHASES_ERROR, getPurchasesErrorHandler); } initializeUI();

private function initializeUI():void { // creates the list that displays purchase options buyList = new List(); buyList.setPosition(25,25); buyList.width = 400; buyList.height = 250; buyList.columnWidth = 400; buyList.scrollable = true; buyList.allowDeselect = false; buyList.selectionMode = ListSelectionMode.SINGLE; this.addChild(buyList); // creates the Buy button buyButton = new LabelButton(); buyButton.setPosition(25, 305); buyButton.width = 150; buyButton.label = "Buy"; buyButton.addEventListener(MouseEvent.CLICK, purchaseHandler); this.addChild(buyButton); // creates the Refresh button refreshButton = new LabelButton(); refreshButton.setPosition(180, 305); refreshButton.width = 150;

136

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

refreshButton.label = "Refresh"; refreshButton.addEventListener(MouseEvent.CLICK, refreshHandler); this.addChild(refreshButton); // sends an HTTPService request to retrieve a list of digital goods httpService = new HTTPService(); httpService.url = "http://docs.blackberry.com/digitalgoods.xml"; httpService.addEventListener(ResultEvent.RESULT, resultHandler); httpService.addEventListener(FaultEvent.FAULT, faultHandler); httpService.send(); function resultHandler(event:ResultEvent):void remoteData:ArrayCollection; data:DataProvider; dgObject:DigitalGoodsInfo;

private { var var var

// creates an array of raw xml data remoteData = event.result.digitalgoods.digitalgood; // sets a data provider for the list data = new DataProvider(); buyList.dataProvider = data; digitalGoods = new ArrayCollection(); // loops through each object in the array of xml data, creates // DigitalGoodsInfo objects, and displays the names of the // digital goods in the list for each(var obj:Object in remoteData) { dgObject = new DigitalGoodsInfo(obj.name, obj.sku, obj.metadata); digitalGoods.addItem(dgObject); buyList.dataProvider.addItem({label: obj.name}); } buyList.selectedIndex = 0;

private function faultHandler(event:FaultEvent):void { trace("Unable to retrieve digital goods from the server."); } private function purchaseHandler(event:MouseEvent):void { var index:int; index = buyList.selectedIndex; // initiates a purchase using the properties of the digital good // that is at the equivalent position in the array as the position // in the list that is currently selected paymentSystem.purchase(null, digitalGoods.getItemAt(index).sku, digitalGoods.getItemAt(index).name,

137

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

digitalGoods.getItemAt(index).metadata, digitalGoods.getItemAt(index).appName, digitalGoods.getItemAt(index).icon);

private function refreshHandler(event:MouseEvent):void { // initiates a local request for a list of existing purchases paymentSystem.getExistingPurchases(false); } private function purchaseSuccessHandler(event:PaymentSuccessEvent):void { var purchase:Purchase = event.purchase; trace("Purchase Success - " + purchase.date + " : " + purchase.digitalGoodID + " : " + purchase.digitalGoodSKU + " : " + purchase.licenseKey + " : " + purchase.metaData + " : " + purchase.transactionID);

private function purchaseErrorHandler(event:PaymentErrorEvent):void { trace("Purchase Error - " + event.errorID + " : " + event.text); } private function getPurchasesSuccessHandler(event:PaymentSuccessEvent):void { var purchase:Purchase; var pastPurchases:Array = event.existingPurchases; if (pastPurchases.length == 0) { trace("No existing purchases"); } else { // iterates through the list of existing purchases and prints the data for (var i:int = 0; i < pastPurchases.length; i++) { purchase = pastPurchases[i]; trace("Get Existing Purchases Success - " + purchase.date + " : " + purchase.digitalGoodID + " : " + purchase.digitalGoodSKU + " : " + purchase.licenseKey + " : " + purchase.metaData + " : " + purchase.transactionID);

private function getPurchasesErrorHandler(event:PaymentErrorEvent):void { trace("Get Existing Purchases Error - " + event.errorID + " : " + event.text);

138

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

DigitalGoodsInfo.as
package valueObjects { public class DigitalGoodsInfo { public var name:String; public var sku:String; public var metadata:String; public var icon:String; public var appName:String; public function DigitalGoodsInfo( name:String, sku:String, metadata:String ) { this.name = name; this.sku = sku; this.metadata = metadata; icon = "http://www.rim.com/products/appworld_3col.jpg"; appName = "PaymentServiceDemo";

digitalgoods.xml
<?xml version="1.0" encoding="utf-8"?> <digitalgoods> <digitalgood> <name>Developing for BlackBerry</name> <sku>123456abc123</sku> <metadata>1234-56-7890</metadata> </digitalgood> <digitalgood> <name>Intro to the BlackBerry Tablet OS</name> <sku>123456abc123</sku> <metadata>09-4567-1243</metadata> </digitalgood> <digitalgood> <name>Tutorial: Selling Digital Goods</name> <sku>123456abc123</sku> <metadata>654-34-29304</metadata> </digitalgood> <digitalgood> <name>Feature and Technical Overview</name> <sku>123456abc123</sku> <metadata>7399-29-0940</metadata> </digitalgood> <digitalgood> <name>Development Guide</name> <sku>123456abc123</sku>

139

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

<metadata>34-90390-124</metadata> </digitalgood> </digitalgoods>

Distributing digital goods


You can distribute digital goods either by sending data files over the wireless network from your own server, or by unlocking existing functionality from within the application's code. If the digital goods for your application don't require dynamic updates, include the functionality of those goods in the source code. For example, if you sell a game that has a predetermined selection of additional levels, those levels should be included in your application. Your game logic can control access to those levels based on the purchase logic. If you host your digital goods on a content server and deliver them to BlackBerry devices over the wireless network, you can update and add to your offering of digital goods without having to submit a new release of your application to the BlackBerry App World storefront.

Distributing digital goods from a content server


If you host your digital goods on a content server, you can notify your content server about successful purchases in two different ways. You can design your application to send notifications, or you can request a notification from the Payment Service. To request notifications from the Payment Service, you must set up a dynamic license model when you register the digital goods in the BlackBerry App World vendor portal. When you set up a dynamic license model for your digital goods, provide an HTTPS URL for your content server. After each successful purchase, the Payment Service server sends your content server a request for a license key, as well as the following parameters that describe the successful purchase:
pin: the device PIN email: the email address associated with the user's BlackBerry ID account product: the name of the application that the digital goods are purchased from version: the version of the application that the digital goods are purchased from transactionid: a unique identifier for the successful purchase sku: the SKU test: true or false depending on whether the purchase is initiated using a BlackBerry ID account that is

configured for testing

After your content server receives the notification, it's up to you to make sure that your users receive the digital goods that they purchase.

Testing your application


The Payment Service supports live testing with the Payment Service server. To test an application, you must have the BlackBerry App World storefront 1.0 or later installed on the BlackBerry PlayBook tablet.
140

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Live testing
Live testing permits you to test the purchase of digital goods against the live Payment Service server without being charged real money. To test your applications live, you must perform the following actions: Add your application to the vendor portal for the BlackBerry App World storefront (the application can remain in the Draft state). Add digital goods and a release bundle to your application in the vendor portal. Register for a BlackBerry ID account at na.blackberry.com/id/. Create a sandbox account by registering your BlackBerry ID in the vendor portal.

After you add your application and digital goods, you can download your application from BlackBerry App World and start testing the purchase process against the live Payment Service server. By registering the BlackBerry ID with the vendor portal, you can use the BlackBerry ID to perform test purchases of applications, as well as digital goods within your applications. When you initiate a purchase, and log in using the BlackBerry ID that you registered with the vendor portal, you can simulate a real purchase without any charges to your account. The BlackBerry ID that you register with the vendor portal can be used only to purchase digital goods from the applications associated with your BlackBerry App World vendor account. For more information about submitting applications and creating sandbox accounts, see the BlackBerry App World vendor documentation at www.blackberry.com/go/appworld/vendordocs/.

Creating a sandbox account


Before you make products available to BlackBerry device and BlackBerry PlayBook tablet users, you can test the purchase of your products and any digital goods that you sell within your products by creating a sandbox account. When you create a sandbox account, you specify the email address that is associated with a BlackBerry ID. You then use the BlackBerry ID to test the purchase of your products without being charged for the purchases.

Create a sandbox account


1. 2. 3. 4. 5. On the vendor portal for the BlackBerry App World storefront, click Sandbox. Click Add New User. In the Email field, type the email address associated with a BlackBerry ID. In the Description field, type a description for the sandbox account. Click Create.

Download an application before you make it available for distribution


If your application has any distribution restrictions (such as the BlackBerry device models or BlackBerry Device Software versions that it supports), make sure that the BlackBerry device that you download the application to is compatible with your application, otherwise you won't be able to locate your application in the BlackBerry App World storefront.

141

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

If you purchase another vendor's application or digital goods using your BlackBerry ID account that is configured for testing, the transaction is real, not simulated, and your account is charged. You can simulate only the purchases of your own applications and digital goods. Before you begin: Add your application, a release bundle, and digital goods in the vendor portal for the BlackBerry App World (the application status can remain as Draft). Create a sandbox account in the vendor portal using a BlackBerry ID. 1. 2. 3. 4. 5. 6. On the home screen of the BlackBerry PlayBook tablet, tap the BlackBerry App World icon. Swipe your finger from the bottom left corner of the screen toward the center of the screen to display the keyboard. Type tst. Tap Return. Open the browser on the tablet. In the address bar, type the location of the application that you want to test (for example, you can type http:// appworld.blackberry.com/webstore/content/xxxxx, where xxxxx is the ID of the application). Complete the instructions on the screen to download the application.

142

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

The blackberry-tablet.xml file

17

You can configure the appearance and behavior of your application in the BlackBerry Tablet OS by specifying XML elements and values in the blackberry-tablet.xml file. If you create an XML configuration file in your Adobe Flash Builder project, it is automatically included in your BAR file. If you package your application from the command line, be sure to specify the blackberry-tablet.xml file when you run the blackberry-airpackager tool. The following table describes the elements of the configuration file: XML element
action

Description Specifies the device capability to which your application requires access. For example, the user must grant your application permission to use the GPS or the microphone. The BlackBerry Tablet OS prompts the user to allow your application to use any device capability you specify in this element. You can specify one action element per capability. For a list of device capabilities, see Accessing restricted functionality. Specify a value for this element when you intend to run your application on a device using a debug token. This value should match the Author value from your debug token. For more information about how to use this element, see Using debug tokens. Specify a value for this element when you intend to run your application on a device using a debug token. This value should match the Author Id value from your debug token. For more information about how to use this element, see Using debug tokens. Specifies the fourth segment of the version number for an application. This must be a value from 0 to 65535. For more information about version numbers, see Assigning a version number to your application. Specifies the BlackBerry Tablet OS Home screen category in which your application should appear. The value must be one of: core.games core.media This element is optional. You can only specify one element of this type in your blackberry-tablet.xml configuration file. All applications appear in the All category by default. Your application appears in the category you specified using this element and the All category. Specifies the icon to display in the BlackBerry Tablet OS Home screen. Your icon should be 86-by-86 pixels. An icon that is larger than 86-by-86 pixels will not display on the screen.

author

authorId

buildId

category

icon

143

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

XML element

Description The icon must be included in your BAR file and can be a PNG file or JPG file. You specify the file name for the icon within an XML element named image.
<icon> <image>my_icon_image_file.png</image> </icon>

platformVersion qnx

splashscreen

For more information about designing application icons, see the BlackBerry PlayBook Tablet UI Guidelines. Specifies the minimum version of the BlackBerry Tablet OS required to run the application. The default is 1.0.0.0. Specifies a BlackBerry Tablet OS configuration file. This is the root XML element in blackberry-tablet.xml. Nest all other elements in this table within this element. Specifies the images to display while the BlackBerry Tablet OS loads your application. You can specify up to two files separated by a colon (":"). If you specify one file, the BlackBerry Tablet OS displays the file in a landscape orientation. If you specify two files, the first file is used when the tablet is in an landscape orientation, and the second file is used when the tablet is in a portrait orientation. The image for your splash screen must be included in your BAR file and can be a PNG file or JPG file. The screen resolution of the BlackBerry PlayBook tablet is 1024 by 600 pixels in default, landscape orientation. Your splash screen should be this size to fill the screen.

Sample blackberry-tablet.xml file


<qnx> <icon> <image>my_icon.png</image> </icon> <author>My Company</author> <authorId>gYAAgIqK0RLL5u4I9NanyxBUuCI</authorId> <category>core.games</category> <splashscreen>img/spalsh_landscape.jpg:img/splash_portrait.jpg</splashscreen> <action>use_camera</action> <action>read_geolocation</action> <action>play_audio</action> <buildId>349</buildId> <platformVersion>1.0.0.0</platformVersion> </qnx>

Localization
You can manage multiple regions and languages by localizing attributes in the blackberry-tablet.xml and <myApplication>-app.xml files. The following attributes can be localized.
144

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

In the <myApplication>-app.xml file: name description

In the blackberry-tablet.xml file: image splashscreen

For a list of available language codes, see <Link to Language Codes>. Sample localization syntax in <myApplication>-app.xml
<name> <text xml:lang="en-US">localization</text> <text xml:lang="fr-FR">localisation</text> <text xml:lang="de-DE">lokalisation</text> </name>

145

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Signing your application

18

Before you can distribute your application for use on a BlackBerry tablet, you must sign your application. The signing tool included with the BlackBerry Tablet OS SDK adds cryptographic hash values to your application package (.bar file) during the signing process. The hash files help verify the authorship of your application to users and the BlackBerry Tablet OS. If you want to test your application on a device without signing it, you can create and install a debug token on the device. For more information about debug tokens, see Using debug tokens. When you sign an application, you perform the following actions: 1. Request permission to sign BlackBerry Tablet OS applications by completing the web form at https:// www.blackberry.com/SignedKeys. After your request is accepted, you receive two .csj registration files by email. The RDK file allows you to configure your keystore to sign applications and the PBDT file allows you to create debug tokens. Each file arrives in a separate email with information about the purpose of the file attached. Complete the BlackBerry Tablet OS deployment setup wizard. This wizard runs when you create a new Adobe ActionScript Mobile Project and guides you through the configuration process to sign your applications or test them on a BlackBerry PlayBook tablet. If necessary, you can manually configure your environment for application signing. Sign your application by requesting a .bar file signature from the RIM Signing Authority. You must increment the version number of your application each time you sign it.

2.

3.

After you sign your application, you can publish it to the BlackBerry App World storefront.

Assigning a version number to your application


You must change the version number of your application before you package it for signing and installation on BlackBerry tablets. The version number for a BlackBerry Tablet OS application comprises a series of four numbers separated by decimals (for example 1.0.5.357).
(Major).(Minor).(Revision).(Build)

Each time you sign your application, you must change at least one segment of the version number. You can change the major, minor, and revision numbers by updating the versionNumber element in the your_project_nameapp.xml file. You can change the build number by updating the buildId element in your blackberry-tablet.xml file. Alternatively, you can specify the build ID using the buildId command line option when you package your application using the blackberry-airpackager tool. The buildId option accepts a number from 0 to 65535. If you specify a build number in both the blackberry-tablet.xml and using the blackberry-airpackager tool, the value given to the blackberryairpackager tool is used. If you do not specify a build number, the default build segment of your version number is 0.

146

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Configure application signing and create debug tokens using the setup wizard in Flash Builder
The following steps help you configure your computer to sign applications and create debug tokens using the setup wizard. You should only perform these steps once. Before you begin: Request permission to sign BlackBerry Tablet OS applications by completing the web form at https://www.blackberry.com/SignedKeys. After your application is accepted, you receive two CSJ registration files by email. 1. 2. 3. 4. 5. On the Window menu, click Preferences. On the Preferences screen, in the preferences list, expand Flash Builder > Target Platforms > BlackBerry Tablet OS. Click Signing. Click BlackBerry Tablet OS Deployment Setup Wizard. Follow the setup wizard to configure your computer to sign applications and create debug tokens.

Configure application signing manually in Flash Builder


The following steps help you manually configure your computer to sign applications. You should only perform these steps once. Before you begin: Request permission to sign BlackBerry Tablet OS applications by completing the web form at https://www.blackberry.com/SignedKeys. After your application is accepted, you receive two CSJ registration files by email. 1. 2. 3. 4. 5. On the Window menu, click Preferences. On the Preferences screen, in the preferences list, expand Flash Builder > Target Platforms > BlackBerry Tablet OS. Click Signing. On the Preferences screen, in the RIM Signing Authority section, click Register. On the Register with RIM Signing Authority screen, complete the following steps: a. In the RDK CSJ Path field, provide the location of the RDK CSJ registration file you received from the RIM Signing Authority. b. In the PBDT CSJ Path field, provide the location of the PBDT CSJ registration file you received from the RIM Signing Authority. c. In the CSJ Pin field, provide the PIN you entered on the web form to request permission to sign applications. d. In the CSK Password field. e. In the Confirm CSK Password field, repeat the password you provided in the previous step. f. Click OK.

147

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

6.

Create a developer certificate by completing the following steps: a. b. In the Developer Certificate section, click Create certificate. On the Create Developer Certificate screen, in the Certificate Path field, provide a location where you want to store your developer certificate. For more information about the default location for signing keys and developer certificates, see Default file location for code signing keys. In the Author field, type your company name. Ensure that this value matches the author element in your blackberry-tablet.xml file. For more information about the blackberry-tablet.xml file, see The blackberrytablet.xml file. In the Keystore Password field, provide a password. In the Confirm Keystore Password field, repeat the password you provided in the previous step. Click OK.

c.

d. e. f.

148

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

7.

Click OK.

Configure application signing through a proxy server in Flash Builder


During the signing process, your computer connects to the RIM Signing Authority. If your computer uses a proxy server to connect to the Internet, you must configure Adobe Flash Builder to use your proxy server. 1. 2. 3. On the Window menu, click Preferences. On the Preferences screen, in the preferences list, expand General. Click Network Connections. In the Active Provider drop-down list, click Manual.

149

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

4.

In the Proxy entries section, select the HTTP schema. Click Edit. a. In the Host field, specify the host address for your proxy server. b. In the Port field, specify the host port number for your proxy server. c. Click OK. Click OK.

5.

Sign your application in Flash Builder


Before you begin:
150

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

1. 2.

Make sure that you increment the version number of your application. For more information about version numbers, see Assigning a version number to your application. Make sure that your computer is connected to the Internet. Configure your computer to sign applications. For more information about configuring your computer to sign applications, see Configure application signing and create debug tokens using the setup wizard in Flash Builder. On the File menu, click Export. On the Export screen, in the export destination list, expand Flash Builder. Click Release Build. Click Next.

3. 4.

On the Export Release Build window, in the Target platforms section, select the BlackBerry Tablet OS check box. In the Export section, specify the export settings. a. Click Browse to specify an export location for your application. If you do not specify a path, the application is exported to the project directory. b. Select the Signed packages for each target platform option. c. Click Next.

151

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

5. 6.

On the Digital Signature tab, select the Enable digital signing check box. Click Finish.

152

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

The .bar file in the folder that you specified on the Export Release Build screen contains your signed application. You can publish the .bar file to BlackBerry App World storefront for distribution. For more information about distributing your applications through BlackBerry App World, see the Vendor Portal Administration Guide.

Configure application signing from the command line


The command below helps you configure your computer to sign applications. You should only perform this step once. You can find the blackberry-signer and blackberry-keytool tools in the bin subfolder where you installed the BlackBerry Tablet OS SDK. Before you begin: Request permission to sign BlackBerry Tablet OS applications by completing the web form at https:// www.blackberry.com/SignedKeys. If you connect to the Internet through a proxy server, you must specify additional command line options to contact the RIM Signing Authority. For more information about using a proxy server from the command line, see Using a proxy server from the command line. Use the blackberry-signer tool to register with the RIM Signing Authority using your CSJ registration file for application signing. In the -storepass parameter, you must specify the keystore password. In the -csjpin parameter, you must specify the registration PIN you enter in the PIN field on the web form when you requested permission to sign applications. You can also configure your computer to create debug tokens at the same time by including the debug token CSJ file in the blackberry-signer command.
153

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

blackberry-signer -register -csjpin <PIN> -storepass <KeystorePassword> <AppSigningCSJFile> <DebugTokenCSJFile>

After you finish: If you received your signing keys before August 9, 2011, you must create a developer certificate manually by using the blackberry-keytool tool. Make sure that the common name (company name) parameter matches the author element in your blackberry-tablet.xml file. For more information about the blackberry-tablet.xml file, see The blackberry-tablet.xml file. The command below creates a developer certificate, and the password that you specify in the -storepass parameter allows you to use the .p12 file to sign BAR files. You should protect the .p12 file and its password.
blackberry-keytool -genkeypair -storepass <storepass> -author <company_name>

Using a proxy server from the command line


During the signing process, your computer connects to the RIM Signing Authority. If your computer connects to the Internet through a proxy server, you should append the options in the table below to your blackberry-signer and blackberry-debugtokenrequest commands. Option
-proxyhost <host> -proxyport <port>

-proxyusername <user name> -proxypassword <password>

Description This option specifies the network host that provides the proxy service. The host parameter can be an IP address or a fully qualified domain name. This option specifies the port number on your proxy server through which blackberry-signer or blackberry-debugtokenrequest should communicate with the RIM Signing Authority. This option allows you to provide your user name if your proxy server requires authentication. This options allows you to provide your password if your proxy server requires authentication.

Example: blackberry-signer command line


blackberry-signer -proxyhost 192.168.1.1 -proxyport 80 -register -csjpin <PIN> -storepass <KeystorePassword> <AppSigningCSJFile> <DebugTokenCSJFile>

154

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Sign your application from the command line


You can sign your application during the packaging process using the blackberry-airpackager tool. Alternatively, you can package and sign your application using separate commands. The command below demonstrates how you can sign your application after you package it into a .bar file . You must sign your application before you can publish it. You can find the blackberry-signer tool in bin subfolder where you installed the BlackBerry Tablet OS SDK. Before you begin: Package your application into a .bar file. For more information about packaging your application, see Package your application from the command line. Make sure you increment the version number of your application. For more information about version numbers, see Assigning a version number to your application. Configure your computer to sign applications. For more information about configuring you computer to sign applications, see Configure application signing from the command line. If you connect to the Internet through a proxy server, you must specify additional command line options to contact the RIM Signing Authority. For more information about using a proxy server from the command line, see Using a proxy server from the command line. Sign your application by with the blackberry-signer tool. In the -storepass parameter, you must specify the keystore password that you created when you configured application signing in the -storepass parameter.
blackberry-signer -storepass <KeystorePassword> <BAR_file.bar>

Your .bar file contains your signed application. You can publish the .bar file to BlackBerry App World storefront for distribution. For more information about distributing your applications through BlackBerry App World, see the Vendor Portal Administration Guide.

Package your application from the command line


Before you begin: Add the path to the bin subfolder where you installed the BlackBerry Tablet OS SDK to the PATH environment variable for your operating system. 1. 2. 3. Open a command prompt. Navigate to the folder where your SWF application and XML configuration files are stored. Type the following command to package your application.
blackberry-airpackager -package output_filename project_name-app.xml project_name.swf any_other_project_files

For more information about command line options, run blackberry-airpackager from the command line with no options.

155

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Application Signing Errors


Attempt to rename [value1] to [value2] failed
Description
During the signing process, the signing tool makes a copy of the input .bar file. After the tool signs the copy of the .bar file successfully, the copy is renamed to the original input file name and the original file is deleted. This error indicates that one of these rename operations failed.

Possible solution
Make sure that you have permissions to modify files in the folder where your .bar file is stored.

Code signing request failed because Application-Development-Mode in Manifest is present and is not set to false
Description
This message appears when you try to sign a .bar file that was packaged in Development mode.

Possible solution
Repackage the .bar file. If you use blackberry-packager, or another command line tool, do not include the debug option in your command line.

Code signing request failed because Common Name in developer certificate is not [value]
Description
The Common Name (CN) property in your Developer Certificate does not match the value you provided in the Company field when you requested permission to sign applications by using the RIM Signing Authority.

Possible solution
Obtain a Developer Certificate that matches the name you provided when you requested permission to sign applications.

Possible solution
Create a self-signed Developer Certificate using the blackberry-keytool tool, that has a CN property that matches the name you provided when you requested permission to sign applications.

Possible solution
Reapply for permission to sign applications with the RIM Signing Authority at https://www.blackberry.com/ SignedKeys. On the web form, in the Company field, provide the name that appears in your Developer Certificate.

156

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Code signing request failed because this file has been previously signed
Description
You can sign an application only once per version number.

Possible solution
1. 2. In the your_project_name-app.xml file, increment the value in the versionNumber element. Repackage your application.

Code signing request failed because Package-Author in Manifest is not set to [value]
Description
The publisher element in your blackberry-tablet.xml file does not match the value you provided in the Company field when you requested permission to sign applications by using the RIM Signing Authority.

Possible solution
Change the value of the publisher element in your blackberry-tablet.xml file.\

Possible solution
Reapply for permission to sign applications with the RIM Signing Authority at https://www.blackberry.com/ SignedKeys. On the web form, in the Company field, provide the name that appears in your publisher element.

Code signing request failed because value of Package-Name in Manifest is not allowed
Description
Your application has a name that is restricted.

Possible solution
1. 2. 3. Change the name of your project. Recompile your project. Repackage your project.

-cskpass and -csjpin must be specified if -register is specified


Description
This message appears when you try to run the blackberry-signer tool with the register option, but you did not include both the cskpass and csjpin options.

157

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

The blackberry-signer tool tries to encrypt communication between your computer and the RIM Signing Authority. The tool stores the encryption keys an encrypted file that is designed to be unlocked by using the password your provide in the cskpass option. The CSJ Pin is a 6 to 10 digit number you selected when you requested permission to sign applications. The number is designed to verify that the CSJ registraion file is only used by the person who requested it.

Possible solution
Add the cskpass and csjpin options to your command line. Make sure you provide appropriate values for each option.

cskpass required
Description
You requested a signature from the RIM Signing Authority, but did not include the cskpass option. To contact the RIM Signing Authority, the blackberry-signer tool must decrypt the barsigner.csk file using the password you provide using the cskpass option.

Possible solution
Include the cskpass parameter and the password in your command line.

Developer certificate and private key not found in keystore or store password not supplied
Description
You attempted to sign an application using the blackberry-signer tool, but you did not provide a value for the storepass option, or your Developer Certificate has no private key named author.

Possible solution
Verify that your command line includes the storepass option, and specifies the correct password.

Possible solution
Recreate your Developer Certificate. You can use the blackberry-keytool tool. Make sure that you provide the literal value "author" (not your name) for the alias option.

Incomplete certificate chain


Description

158

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

The Developer Certificate that you provided to the blackberry-signer tool was issued by a Certificate Authority. However, the series of signatures (from a root authority to your certificate) that establish the authenticity of your certificate was not found in your keystore along with your Certificate.

Possible solution
Add the certificate chain to the keystore.

Key associated with [value] not a private key


Description
The blackberry-signer tool found a application signing key using the keyname parameter you specified on the command line. However, the key found is inappropriate for application signing.

Possible solution
To request a signature from the RIM Signing Authority, make sure you specify RDK for the keyname parameter. To sign your BAR file using your Developer Certificate, make sure you specify author for the keyname parameter.

Keystore load: store password incorrect


Description
The value you specified for the storepass option is incorrect. The blackberry-signer tool cannot decrypt the keystore for your Developer Certificate.

Possible solution
Provide the correct password for your keystore.

keytool error: java.io.FileNotFoundException: certificate.p12 <Access is denied>


Description
You tried to use the blackberry-keytool tool to create a self-signed Developer Certificate. The tool does not have permission to write to the location you provided for the output_file.p12 parameter.

Possible solution
Acquire read-write permissions for the folder to which you want to write the P12 file.

Possible solution
Choose another location for your P12 file.

Possible solution
Run blackberry-keytool with superuser permissions.

159

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

keytool error: java.io.IOException: Incorrect AVA Format


Description
You tried to use the blackberry-keytool tool to create a self-signed Developer Certificate. The cn value for the dname parameter contains a special character. The special character set includes: Commas (,) Additon symbol (+) Quotation mark (") Back-slash (\) Angled brackets(< and >) Semi-colon (;) Add a back-slash in front of the special character in your command line. The following shows an excerpt from an incorrect command line:
... -dname "cn="One, two, three" ...

Possible solution

The following corrects the excerpt above:


... -dname "cn=One\, two\, three" ...

keytool error: java.lang.Exception: Key pair not generated, alias <author> already exists
Description
You tried to use the blackberry-keytool tool to create a self-signed Developer Certificate. The file name you provided for the output_file.p12 parameter already exists.

Possible solution
Change the file name so that blackberry-keytool creates the output file using a different name or location.

Possible solution
Delete your existing P12 file. Then run blackberry-keytool again.

Missing parameter for [option_name] option


Description
You specified a command line option, option_name, that takes a parameter. However, you did not supply a value for the parameter.

Possible solution
Provide a value for the parameter.

160

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

No BAR file or CSJ file specified


Description
This error appears when you try to use the blackberry-signer tool to sign or verify a .bar file, but no .bar file was specified on the command line. This error can also appear when you try to use the blackberry-signer tool to register with the RIM Signing Authority, but no CSJ file was specified on the command line.

Possible solution
Specify the appropriate file.

No key name specified


Description
You cannot sign your .bar file because you did not specify a signing key. The final parameter of the blackberry-signer tool specifies the key with which to sign your .bar file. Your .bar file must be signed twice: first by the RIM Signing Authority, then by your Developer Certificate.

Possible solution
To request a signature from the RIM Signing Authority, type RDK to the end of your command line.

Possible solution
To sign your BAR file using your Developer Certificate, type author to the end of your command line.

No manifest
Description
The BAR file is corrupt.

Possible solution
Repackage your project using the blackberry-packager tool.

Only one of -setup, -register, or -verify can be specified


Description
You cannot execute any of the following functions concurrently: setup, register, and verify. They are mutually exclusive operations.

Possible solution
Perform these functions separately.

161

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Server is not responding


Description
The signing tool cannot contact the RIM Signing Authority. A problem with the network connection prevents the blackberry-signer tool from contacting the RIM Signing Authority. The signing tool cannot sign your BAR file until it contacts RIM Signing Authority.

Possible solution
Check your computer's network connection.

Unable to open BAR file


Description
The blackberry-signer tool cannot read the BAR file you specified on the command line. You may not have permission to access this file, or the file may be missing or corrupt.

Possible solution
Verify that you have permission to access the file and that it exists at the location you provided on the command line. If the file exists and you have access to it, then try repackaging your project using the blackberry-packager tool.

162

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Using debug tokens


When you run an unsigned application using a debug token, you can avoid: Changing the version number of your application Accessing the Internet Exporting a release build of your application

19

You can run an unsigned application on a BlackBerry PlayBook tablet by using a debug token. Debug tokens allow you to separate the process of application creation and publication. You can create and test an application using a debug token, then deliver the application to a supervisor or a client for signing and publication.

You can create a debug token if you have permission to sign BlackBerry Tablet OS applications. To request permission to sign applications, you must complete the web form at https://www.blackberry.com/SignedKeys. After your request is approved, you receive two CSJ registration files by email. The RDK file allows you to configure your keystore to sign applications and the PBDT file allows you to create debug tokens. Each file arrives in a separate email with information about the purpose of the file attached. After you receive your CSJ registration files, you can configure your computer to create debug tokens. When you create a new Adobe ActionScript Mobile Project, the BlackBerry Tablet OS deployment setup wizard guides you through the configuration process to test your applications on a BlackBerry PlayBook tablet. If necessary, you can create and configure debug tokens manually. When you create a debug token, you specify the PIN for each tablet on which the token can be used. You can distribute the debug tokens that you create to developers who can install them on the specified tablets, or you can install the debug tokens yourself. You are limited to 100 tablet PINs across all of your debug tokens that are currently active. If you create debug tokens that address 100 PINs, you must wait for some of your debug tokens to expire before you create more. Debug tokens are valid for 30 days. When a debug token expires, the BlackBerry Tablet OS no longer allows unsigned applications that rely on that token to run. When a developer is ready to load an unsigned application on a tablet, they must configure the application to use the same author and authorID values that are defined in the debug token.

Create a debug token manually using Flash Builder


If you have physical access to the BlackBerry tablet, you can create and install a debug token when you configure the tablet as a test device in Adobe Flash Builder . Otherwise, use the following steps to create a debug token. 1. 2. 3. 4. On the Windows menu, click Preferences. On the Preferences screen, in the preferences list, expand Flash Builder > Target Platforms > BlackBerry Tablet OS. Click Signing. In the Debug Tokens section, click Create.

163

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

5.

Choose one of the following options: If you did not configure your computer for signing applications, continue to step 7. If you configured your computer for signing applications, but did not configure your computer for creating debug tokens, continue to step 8. If you configured your computer for signing applications and creating debug tokens, continue to to step 9. If you did not configure your computer for signing applications, you must register both CSJ registration files that you received for signing applications and creating debug tokens. a. On the Register with RIM Signing Authority screen, specify or create a developer certificate. For more information about developer certificates, see Configure application signing manually in Flash Builder. b. In the RDK CSJ Path field, provide the location of the CSJ registration file that you received for signing applications. c. In the PBDT CSJ Path field, provide the location of the CSJ registration file that you received for creating debug tokens. d. In the CSJ Pin field, provide the PIN that you entered on the web form to request permission for signing applications. e. In the CSK Password field, provide the CSK password that you defined when you configured your computer for signing applications. f. Click OK.

6.

164

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

7.

Now that you configured your computer for signing applications and for creating debug tokens, continue to step 9. If you already configured your computer for signing, but this is the first debug token you are creating on your computer, you must register the CSJ registration file that you received for creating debug tokens. a. On the Register with RIM Signing Authority screen, create or specify a developer certificate. For more information about developer certificates, see Configure application signing manually in Flash Builder. b. In the PBDT CSJ Path field, enter the location of the CSJ registration file that you received for creating debug tokens. c. In the CSJ Pin field, enter the PIN that you entered on the web form to request permission to sign applications. d. In the CSK Password field, enter the CSK password you defined when you configured your computer to sign applications. e. Click OK.

165

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

8.

9.

Now that you configured your computer for creating debug tokens, go to step 9. On the Create Debug Token screen, in the Location field, enter the location and file name of the debug token you want to create. The debug token file must have a .bar extension. If you specify the name of an existing file, that file is deleted before your debug token is created. In the Device PINs section, click Add.

166

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

10. On the Add Devices screen, in the Device PINs field, provide a comma-delimited list that includes the PIN for each tablet that you want to load this debug token on. Click OK. For more information about finding the PIN of a tablet, see Retrieve the PIN of a BlackBerry tablet.

167

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

11. On the Create Debug Token screen, click OK. On the Preferences screen, in the Debug Tokens section, you should see the token you created. You can distribute or install the debug token you created.

Import a debug token using Flash Builder


If you receive a debug token that you want to install on a BlackBerry PlayBook tablet, you must import it into Adobe Flash Builder first. 1. 2. 3. 4. 5. On the Window menu, click Preferences. On the Preferences screen, in the preferences list, expand Flash Builder > Target Platforms > BlackBerry Tablet OS. Click Signing. In the Debug Tokens section, click Import. On the Import screen, in the File name field, enter the location of the debug token you were assigned (a .bar file). Click Open.

On the Preferences screen, in the Debug Tokens section, you should see the token you imported.

Install a debug token using Flash Builder


Before you begin: Create or import a debug token. Configure your BlackBerry tablet as a test device. 1. In the upper-right corner of the Home screen on your BlackBerry tablet, touch the gear icon to open the BlackBerry tablet options.

2. 3. 4. 5. 6. 7. 8. 9.

In the list of options, touch Security. In the list of security options, touch Development Mode. Touch Upload Debug Token. In Adobe Flash Builder, on the Window menu, click Preferences. On the Preferences window, in the preferences list, expand Flash Builder > Target Platforms > BlackBerry Tablet OS. Click Signing. In the Debug Tokens section, in the list of debug tokens, select the debug token that you want to install on the tablet. Click Upload.

168

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

10. On the Upload Debug Tokens to Devices screen, select the tablet on which you want to install the debug token. Click OK.

You can now run unsigned applications on your BlackBerry tablet.

Create a debug token from the command line


You can find the blackberry-debugtokenrequest tool in the bin subfolder where you installed the BlackBerry Tablet OS SDK. Before you begin: Request permission to sign BlackBerry Tablet OS applications by completing the web form at https:// www.blackberry.com/SignedKeys. If you connect to the Internet through a proxy server, you must specify additional command line options to contact the RIM Signing Authority. For more information about using a proxy server from the command line, see Using a proxy server from the command line. 1. If you already configured your computer for creating debug tokens when you configured application signing, go to step 2. Otherwise, use the blackberry-debugtokenrequest tool to register with the RIM Signing Authority using your PDBT .csj registration file for creating debug tokens. In the -storepass parameter, you must specify the keystore password. In the -csjpin parameter, you must specify the registration PIN you enter in the PIN field on the web form when you requested permission to sign applications. You should only perform this command once.
blackberry-debugtokenrequest -register -csjpin <PIN> -storepass <KeystorePassword> <DebugTokenCSJFile> blackberry-signer command.

Note: You can also configure your environment for signing by including the RDK .csj registration file in the

2.

Create a debug token for your tablet. Provide the following values for the command line options: Option
storepass

Value The keystore password that you specified when you registered with the RIM Signing Authority.

169

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Option
devicepin

Value The PIN of the BlackBerry tablet on which you want to install this debug token. For example,-devicepin12A34B56C . For more information about finding the PIN of a tablet, see Retrieve the PIN of a BlackBerry tablet. The file name of the debug token you want to create. The debug token file must end with .bar. If you specify the name of an existing file, the blackberry-debugtokenrequest tool deletes the file before the tool creates the debug token.

debug_token_file_name.bar

Example: blackberry-debugtokenrequest command line


blackberry-debugtokenrequest -storepass <KeystorePassword> -devicepin<PIN tablet 1> -devicepin <PIN tablet 2> -devicepin <PIN tablet n> <debug_token_file_name.bar>

Install a debug token from the command line


Before you begin: Retrieve the IP address of your BlackBerry tablet. For more information about retrieving the IP address of your tablet, see Retrieving the IP address of the BlackBerry tablet. 1. Open the BlackBerry tablet options. In the upper-right corner of the Home screen on your BlackBerry tablet, touch the gear icon.

2. 3. 4. 5.

In the list of options, touch Security. In the list of security options, touch Development Mode. Touch Upload Debug Token. At a command prompt, enter the following command:
blackberry-deploy -installDebugToken <path to debug token> -device <IP address of tablet> -password <tablet password>

The tablet is now ready to accept unsigned applications. For more information about configuring your application for use on a tablet with a debug token, see Configuring your application for use with a debug token from the command line.

170

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Configure your application for use with a debug token from the command line
You can use the BlackBerry Tablet OS to run an unsigned application on a BlackBerry tablet that has a debug token installed. To load an unsigned application, you must configure the application's author and authorId properties match those of specified by the debug token. You can find the blackberry-airpackager tool in bin subfolder where you installed the BlackBerry Tablet OS SDK. When you package your application, include -debugToken to extract author and authorId from <token> and apply it to your application.
blackberry-airpackager -devMode -debugToken <token> -package <MyApplication.bar> <MyApplication.xml> <blackberry-tablet.xml> <others files...>

Example: blackberry-airpackager command line


blackberry-airpackager -devMode -debugToken <token> -package <MyApplication.bar> <MyApplication.xml> <blackberry-tablet.xml> <others files...>

171

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Backup and restore your code signing keys

20

You should back up your code signing keys to protect your code signing credentials and developer certificate. Because you can only register your CSJ registration files with the RIM Signing Authority once, if you do not back up your code signing keys and you forget your password or lose your code signing keys, you must register with the RIM Signing Authority again to receive new code signing keys. If you sign your application with a new code signing key and deploy it to a BlackBerry PlayBook tablet, your application appears as a new application, not an upgrade, and cannot access shared data from the previous version. Using your backup files, you can: Restore the code signing keys to the original computer Install the code signing keys on another computer Share the code signing keys within an organization or between developers It is important that you protect your backup files, code signing keys and developer certificate. If someone obtains your backup files, they can use your code signing credentials to sign an application.

Back up code signing keys using Flash Builder


To back up your code signing keys and developer certificate as a ZIP file: 1. 2. 3. 4. 5. On the Window menu, click Preferences. On the Preferences screen, in the preferences list, expand Flash Builder > Target Platforms > BlackBerry Tablet OS. Click Signing. In the Backup and Restore section, click Backup. On the Save As screen, specify a name and location for your backup file. Click Save.

Restore code signing keys using Flash Builder


Before you begin: Before restoring your code signing keys and developer certificates, make sure you back up and remove any existing code signing keys and developer certificates. 1. 2. 3. 4. 5. 6. On the Window menu, click Preferences. On the Preferences screen, in the preferences list, expand Flash Builder > Target Platforms > BlackBerry Tablet OS. Click Signing. In the RIM Signing Authority section, click Unregister to remove any existing signing keys. In the Backup and Restore section, click Restore. On the Open screen, specify a name and location for your backup file. Click Open.

172

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Back up code signing keys manually


1. 2. Navigate to the directory that contains your code signing keys. For more information about the default location for code signing keys, see Default location for code signing keys. Copy the following files to a backup file location: barsigner.csk barsigner.db <yourkeyname>.p12 Note: The default file name for the developer certificate is author.p12

Restore code signing keys manually


Before you begin: Before restoring your code signing keys and developer certificates, make sure you back up and remove any existing code signing keys and developer certificates. 1. 2. Navigate to the current file location for your code signing keys and developer certificates. For more information about the default location for signing keys, see Default location for code signing keys. Copy the following files from your backup file location to the default file location: barsigner.csk barsigner.db <yourkeyname>.p12 Note: The default filename for the developer certificate is author.p12

Default location for code signing keys


By default, code signing keys are stored in a central location in your profile directory and are used by all BlackBerry Tablet OS development tools. The default locations of these files vary based on operating system and are outlined in the table below. Note: In a Windows XP environment, the default %HOMEPATH% is C:\Documents and Settings\<username>. In a Windows Vista and Windows 7 environment, the default %HOMEPATH% is C:\Users\<username>. Operating System Windows XP Windows Vista and Windows 7 Mac OS UNIX and Linux Default location %HOMEPATH%\Local Settings\Application Data\Research In Motion %HOMEPATH%\AppData\Local\Research In Motion ~/Library/Research In Motion ~/.rim

173

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Retrieve the PIN of a BlackBerry tablet


1.

21

In the upper-right corner of the Home screen on your BlackBerrytablet, press the gear icon to open the BlackBerry tablet options.

2. 3.

In the View information about your tablet field, select Hardware. Record the value from the PIN field.

174

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Retrieving the IP address of the BlackBerry PlayBook tablet


You can view the tablet's IP address by tapping the icon to the right of the clock on the status bar.

22

You must provide the IP address of the BlackBerry PlayBook tablet to the deployment tool of your choice to load your application on the tablet. To display the IP address, the tablet must be in development mode. Development mode is enabled by default. To learn how to enable development mode manually, see Enable development mode.

175

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Enable development mode


Development mode must be enabled before you can load and run your application on the BlackBerry Tablet Simulator, or if you want to view the IP address of the simulator. Development mode is enabled by default. 1.

23

In the virtual machine for the BlackBerry Tablet Simulator, in the upper-right corner of the simulator screen, click the icon.

2. 3.

On the Security screen, click Development mode. Next to the Use Development Mode label, set the Development Mode setting to ON.

4. 5.

In the Device password field, type the password for your device. Click Back.

176

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Provide feedback
To provide feedback on this deliverable, visit www.blackberry.com/docsfeedback.

24

177

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Document revision history


Date 13 September 2011 Description Added the following topics:

25

Responding to application window state Listen for a chance in application window state Configure updates for Flash Builder in a Windows environment Configure updates forFlash Builder in a Mac environment Check for updates to the BlackBerry Tablet OS plug-in Configure application signing and create debug tokens using the setup wizard in Flash Builder Configure application signing manually in Flash Builder Using debug tokens Create a debug token manually using Flash Builder Backup and restore your code signing keys Back up code signing keys using Flash Builder Restore code signing keys using Flash Builder Back up code signing keys manually Restore code signing keys manually Default location for code signing keys

Changed the following topics: Folders accessible by an application Understanding the application life cycle Saving the application state Signing your application Configure application signing through a proxy server in Flash Builder Sign your application in Flash Builder Configure application signing from the command line Using a proxy server from the command line Sign your application from the command line Create a debug token from the command line Configure your application for use with a debug token from the command line Changed the following topics:
178

23 March 2011

Configure application signing from Adobe Flash Builder 4.0.1 Configure application signing from Adobe Flash Builder 4.5 Configure application signing from the command line

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Date

Description Sign an application from Adobe Flash Builder 4.0.1 Sign an application from Adobe Flash Builder 4.5 Sign your application from the command line Added the following topics: Accessing restricted functionality Application signing errors Configuring your application Configure application signing from Adobe Flash Builder 4.0.1 Configure application signing from Adobe Flash Builder 4.5 Configure signing through a proxy server Creating a resource bundle Localizing your application using resource bundles Localizing an application Load a resource bundle Sign an application from Adobe Flash Builder 4.0.1 Sign an application from Adobe Flash Builder 4.5 Using a proxy server from the command line

10 March 2011

Changed the following topics: Configure application signing from the command line Signing your application Sign your application from the command line Configure application signing from the command line Signing your application Sign your application from the command line First draft released.

17 February 2011

13 January 2011

179

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Legal notice

26

2011 Research In Motion Limited. All rights reserved. BlackBerry, RIM, Research In Motion, and related trademarks, names, and logos are the property of Research In Motion Limited and are registered and/or used in the U.S. and countries around the world. Adobe,AIR, Flash, and ActionScript are trademarks of Adobe Systems Incorporated. SQLite is a trademark of Hipp, Wyrick & Company, Inc. QNX is a trademark of QNX Software Systems GmbH & Co. KG. All other trademarks are the property of their respective owners. This documentation including all documentation incorporated by reference herein such as documentation provided or made available at www.blackberry.com/go/docs is provided or made accessible "AS IS" and "AS AVAILABLE" and without condition, endorsement, guarantee, representation, or warranty of any kind by Research In Motion Limited and its affiliated companies ("RIM") and RIM assumes no responsibility for any typographical, technical, or other inaccuracies, errors, or omissions in this documentation. In order to protect RIM proprietary and confidential information and/or trade secrets, this documentation may describe some aspects of RIM technology in generalized terms. RIM reserves the right to periodically change information that is contained in this documentation; however, RIM makes no commitment to provide any such changes, updates, enhancements, or other additions to this documentation to you in a timely manner or at all. This documentation might contain references to third-party sources of information, hardware or software, products or services including components and content such as content protected by copyright and/or third-party web sites (collectively the "Third Party Products and Services"). RIM does not control, and is not responsible for, any Third Party Products and Services including, without limitation the content, accuracy, copyright compliance, compatibility, performance, trustworthiness, legality, decency, links, or any other aspect of Third Party Products and Services. The inclusion of a reference to Third Party Products and Services in this documentation does not imply endorsement by RIM of the Third Party Products and Services or the third party in any way. EXCEPT TO THE EXTENT SPECIFICALLY PROHIBITED BY APPLICABLE LAW IN YOUR JURISDICTION, ALL CONDITIONS, ENDORSEMENTS, GUARANTEES, REPRESENTATIONS, OR WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY CONDITIONS, ENDORSEMENTS, GUARANTEES, REPRESENTATIONS OR WARRANTIES OF DURABILITY, FITNESS FOR A PARTICULAR PURPOSE OR USE, MERCHANTABILITY, MERCHANTABLE QUALITY, NON-INFRINGEMENT, SATISFACTORY QUALITY, OR TITLE, OR ARISING FROM A STATUTE OR CUSTOM OR A COURSE OF DEALING OR USAGE OF TRADE, OR RELATED TO THE DOCUMENTATION OR ITS USE, OR PERFORMANCE OR NON-PERFORMANCE OF ANY SOFTWARE, HARDWARE, SERVICE, OR ANY THIRD PARTY PRODUCTS AND SERVICES REFERENCED HEREIN, ARE HEREBY EXCLUDED. YOU MAY ALSO HAVE OTHER RIGHTS THAT VARY BY STATE OR PROVINCE. SOME JURISDICTIONS MAY NOT ALLOW THE EXCLUSION OR LIMITATION OF IMPLIED WARRANTIES AND CONDITIONS. TO THE EXTENT PERMITTED BY LAW, ANY IMPLIED WARRANTIES OR CONDITIONS RELATING TO THE DOCUMENTATION TO THE EXTENT THEY CANNOT BE EXCLUDED AS SET OUT ABOVE, BUT CAN BE LIMITED, ARE HEREBY LIMITED TO NINETY (90) DAYS FROM THE DATE YOU FIRST ACQUIRED THE DOCUMENTATION OR THE ITEM THAT IS THE SUBJECT OF THE CLAIM. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW IN YOUR JURISDICTION, IN NO EVENT SHALL RIM BE LIABLE FOR ANY TYPE OF DAMAGES RELATED TO THIS DOCUMENTATION OR ITS USE, OR PERFORMANCE OR NONPERFORMANCE OF ANY SOFTWARE, HARDWARE, SERVICE, OR ANY THIRD PARTY PRODUCTS AND SERVICES

180

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

REFERENCED HEREIN INCLUDING WITHOUT LIMITATION ANY OF THE FOLLOWING DAMAGES: DIRECT, CONSEQUENTIAL, EXEMPLARY, INCIDENTAL, INDIRECT, SPECIAL, PUNITIVE, OR AGGRAVATED DAMAGES, DAMAGES FOR LOSS OF PROFITS OR REVENUES, FAILURE TO REALIZE ANY EXPECTED SAVINGS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, LOSS OF BUSINESS OPPORTUNITY, OR CORRUPTION OR LOSS OF DATA, FAILURES TO TRANSMIT OR RECEIVE ANY DATA, PROBLEMS ASSOCIATED WITH ANY APPLICATIONS USED IN CONJUNCTION WITH RIM PRODUCTS OR SERVICES, DOWNTIME COSTS, LOSS OF THE USE OF RIM PRODUCTS OR SERVICES OR ANY PORTION THEREOF OR OF ANY AIRTIME SERVICES, COST OF SUBSTITUTE GOODS, COSTS OF COVER, FACILITIES OR SERVICES, COST OF CAPITAL, OR OTHER SIMILAR PECUNIARY LOSSES, WHETHER OR NOT SUCH DAMAGES WERE FORESEEN OR UNFORESEEN, AND EVEN IF RIM HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW IN YOUR JURISDICTION, RIM SHALL HAVE NO OTHER OBLIGATION, DUTY, OR LIABILITY WHATSOEVER IN CONTRACT, TORT, OR OTHERWISE TO YOU INCLUDING ANY LIABILITY FOR NEGLIGENCE OR STRICT LIABILITY. THE LIMITATIONS, EXCLUSIONS, AND DISCLAIMERS HEREIN SHALL APPLY: (A) IRRESPECTIVE OF THE NATURE OF THE CAUSE OF ACTION, DEMAND, OR ACTION BY YOU INCLUDING BUT NOT LIMITED TO BREACH OF CONTRACT, NEGLIGENCE, TORT, STRICT LIABILITY OR ANY OTHER LEGAL THEORY AND SHALL SURVIVE A FUNDAMENTAL BREACH OR BREACHES OR THE FAILURE OF THE ESSENTIAL PURPOSE OF THIS AGREEMENT OR OF ANY REMEDY CONTAINED HEREIN; AND (B) TO RIM AND ITS AFFILIATED COMPANIES, THEIR SUCCESSORS, ASSIGNS, AGENTS, SUPPLIERS (INCLUDING AIRTIME SERVICE PROVIDERS), AUTHORIZED RIM DISTRIBUTORS (ALSO INCLUDING AIRTIME SERVICE PROVIDERS) AND THEIR RESPECTIVE DIRECTORS, EMPLOYEES, AND INDEPENDENT CONTRACTORS. IN ADDITION TO THE LIMITATIONS AND EXCLUSIONS SET OUT ABOVE, IN NO EVENT SHALL ANY DIRECTOR, EMPLOYEE, AGENT, DISTRIBUTOR, SUPPLIER, INDEPENDENT CONTRACTOR OF RIM OR ANY AFFILIATES OF RIM HAVE ANY LIABILITY ARISING FROM OR RELATED TO THE DOCUMENTATION. Prior to subscribing for, installing, or using any Third Party Products and Services, it is your responsibility to ensure that your airtime service provider has agreed to support all of their features. Some airtime service providers might not offer Internet browsing functionality with a subscription to the BlackBerry Internet Service. Check with your service provider for availability, roaming arrangements, service plans and features. Installation or use of Third Party Products and Services with RIM's products and services may require one or more patent, trademark, copyright, or other licenses in order to avoid infringement or violation of third party rights. You are solely responsible for determining whether to use Third Party Products and Services and if any third party licenses are required to do so. If required you are responsible for acquiring them. You should not install or use Third Party Products and Services until all necessary licenses have been acquired. Any Third Party Products and Services that are provided with RIM's products and services are provided as a convenience to you and are provided "AS IS" with no express or implied conditions, endorsements, guarantees, representations, or warranties of any kind by RIM and RIM assumes no liability whatsoever, in relation thereto. Your use of Third Party Products and Services shall be governed by and subject to you agreeing to the terms of separate licenses and other agreements applicable thereto with third parties, except to the extent expressly covered by a license or other agreement with RIM. Certain features outlined in this documentation require a minimum version of BlackBerry Enterprise Server, BlackBerry Desktop Software, and/or BlackBerry Device Software.

181

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

The terms of use of any RIM product or service are set out in a separate license or other agreement with RIM applicable thereto. NOTHING IN THIS DOCUMENTATION IS INTENDED TO SUPERSEDE ANY EXPRESS WRITTEN AGREEMENTS OR WARRANTIES PROVIDED BY RIM FOR PORTIONS OF ANY RIM PRODUCT OR SERVICE OTHER THAN THIS DOCUMENTATION. Research In Motion Limited 295 Phillip Street Waterloo, ON N2L 3W8 Canada Research In Motion UK Limited Centrum House 36 Station Road Egham, Surrey TW20 9LF United Kingdom Published in Canada

182

Você também pode gostar