Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Version: 1.1.1
Development Guide
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
RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.
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/.
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.
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
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
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
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.
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.
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.
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.
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.
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 }
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.
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; } }
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.
2.
3.
Define the callback function called when a low memory event occurs.
public function onLowMemory(event:Event):void { // Save state // Release resources }
2.
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.
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.
2.
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.
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.
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.
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.
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.
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
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.
23
RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.
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.
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.
4.
26
RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.
5.
6.
Create the function initializeUI. The initializeUI function sets up the UI components that are used by the application.
private function initializeUI():void {
7.
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.
27
RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.
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)); }
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;
2.
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);
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;
2. 3.
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.
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);
36
RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.
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.
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. 5.
6.
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.
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);
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); } }
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.
5.
6.
39
RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.
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; }
[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.
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.
4.
5.
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.
43
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.
4.
5.
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.
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;
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
[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);
46
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.
4.
Create the variables for the myToggle toggle switch and the myButton label button.
private var myToggle:ToggleSwitch; private var myButton:LabelButton;
5.
6.
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);
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);
[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);
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.
4.
5.
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.
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);
[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)
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.
5.
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.
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"); }
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.
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
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.
4.
56
RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.
5.
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);
[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);
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)
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)
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.
5.
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.
7.
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);
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);
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.
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.
5.
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.
63
RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.
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 ); } } }
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.
5.
64
RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.
6.
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);
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.
66
RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.
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);
68
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 the MyCustomCellRenderer class. In your application signature, extend the AlternatingCellRenderer class.
public class MyCustomCellRenderer extends AlternatingCellRenderer {
4.
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.
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(); }
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.
5.
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.
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.
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.
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.
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.
5.
6.
74
RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.
7.
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"});
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.
4.
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.
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.
7.
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.
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"); }
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"});
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);
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=[];
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.
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"); }
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 { } }
84
RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.
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.
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.
5.
RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.
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, 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;
86
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.
4.
5.
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); }
RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.
private function onClick(e:MouseEvent):void { if (!myActivity.isAnimating()) { myAnimate.label = "Stop"; myActivity.animate(true) } else { myAnimate.label = "Animate"; myActivity.animate(false); } }
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.
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:
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. 5.
6.
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.
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 ); }
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.
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.
94
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.
4.
5.
6.
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.
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.
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);
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.
3.
4.
5.
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.
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); } }
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.
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.
1.
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.
102
RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.
5.
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.
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.
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.
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.
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.
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.
11. Create the ButtonClicked() method to respond to click events on your button.
public function ButtonClicked(event:Object):void { }
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);
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.
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.
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.
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.
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(), 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.
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";
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".
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.
[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]; } }
[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.
114
RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.
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.
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.
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.
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;
[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");
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.
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.
6.
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.
[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.
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.
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.
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.
RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.
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";
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.
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.
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.
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.
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
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.
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;
// 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.
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.
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.
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/.
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.
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.
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.
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.
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.
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.
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.
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.
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.
RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.
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>
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.
154
RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.
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.
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.
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.
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.
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.
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.
Possible solution
Provide the correct password for your keystore.
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.
Possible solution
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.
Possible solution
Provide a value for the parameter.
160
RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.
Possible solution
Specify the appropriate file.
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.
Possible solution
Perform these functions separately.
161
RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.
Possible solution
Check your computer's network connection.
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.
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.
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.
On the Preferences screen, in the Debug Tokens section, you should see the token you imported.
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.
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
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...>
171
RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.
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.
172
RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.
173
RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.
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.
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.
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.
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