Creating your own cards

You just learned how you can integrate the functionality of other applications with yours by using cards. However, a great way to get your application noticed is to export your application's cards, so other applications can import them. Creating cards is similar to creating a small, focused application. One of the key differences, however, is that unlike an application, a card can have multiple instances running at the same time. The BlackBerry 10 OS creates a new instance for each client application. In many cases, the BlackBerry 10 OS will pool your card (pooling is discussed a bit later). This section can help you understand how you can use cards to expose your application's functionality to other applications.

A card shares an execution context across multiple instances of itself. For example, all instances of a card run in the same workspace directory and permissions. This feature of cards is important when you consider how you use your resources. If you read and write files, make sure you coordinate and access across different instances of your card. Any cards your application exports are packaged in the same .bar file as the application.

Register a card target

Since a card is used through an invocation request, the first step in exporting a card is to register an invocation target for it. Registering card targets is exactly the same as registering application targets except for a minor difference. The <invoke-target-type> tag must specify one of the card styles supported by the BlackBerry 10 OS. The valid values for <invoke-target-type> are card.previewer, card.composer, and card.picker. Registering in this way informs the BlackBerry 10 OS that you are exporting a card and describes the style of the card, so the BlackBerry 10 OS can handle it appropriately.

Just like applications, cards are packaged and identified as invocation targets in the bar-descriptor.xml file. Here's an example that shows you how to declare cards:

<invoke-target id="com.acme.myapp">
  <invoke-target-type>card.previewer</invoke-target-type>
  <filter>
    <action>bb.action.VIEW</action>
    <action>bb.action.SHARE</action>
    <mime-type>image/png</mime-type>
    <mime-type>image/jpeg</mime-type>
    <property var="uris" value="file://"/>
  </filter>
</invoke-target>

Invocation requests for cards

Since your cards are bundled in the same executable file as your application, when you start your app, you should check whether the executable file needs to be the application or one of the exported cards. Inspecting the application start-up mode will reveal whether the process started when an application starts (for example, a user tapping on the application icon to start it) or as an invocation, and whether the invocation is for the full application or one of the exported cards. Here's how you can perform a check up during the start-up mode:

public function Main()
{
	// You must define the following in the constructor of your 
    // main class for the event to fire properly
 	InvokeManager.invokeManager.addEventListener(InvokeEvent.INVOKE, onInvoke );
}
//Card recieves invocation requests
private function onInvoke( event:InvokeEvent ):void
{
	if( InvokeManager.invokeManager.startupMode == InvokeStartupMode.INVOKE )
	{
		var request:InvokeRequest =  InvokeManager.invokeManager.startupRequest;

		switch( request.target )
		{
			case "com.acme.message.previewer":
				//init the card ui.
				break;
			case "com.acme.message.composer":
				//init the card ui.
				break;
			case "com.acme.message.previewer":
				//init the card ui.
				break;
		} 
	}
	else if(  InvokeManager.invokeManager.startupMode == InvokeStartupMode.VIEWER )
	{
		//launched as viewer.
	}
	else
	{
		//We were launched from the homescreen. Display the default UI.
	}
}

Card targets receive invocation requests in the same way as application targets do. For more information, see Receiving invocation.

Requesting your card to be closed

After a card finishes its task, it can request to be closed. When this request is processed, the card is transitioned off the screen and its parent application is notified. While the card closes itself, it can also send a response message to the parent application. The qnx.fuse.ui.display.CardBase class provides the basic functionality for all the different types of cards. The closeCard() method found in the CardBase class can be used to request the card to be closed. Here's how a card requests to be closed:

Prepare your card for pooling

You can create your cards in such a way that they can be pooled when a user closes the card. Pooling helps to keep frequently used cards ready for reuse, which reduces loading and transition time when cards are stacked. For example, if the user is viewing one email message after another, instead of exporting a new card for every email, the BlackBerry 10 OS may pool the existing email previewer card and use it again.

When you're creating a card, you must consider several things before you handle pooling events, such as which resources your cards should clean up or keep when they're pooled. First, consider adding support for purging the state of the card. While pooled cards are not terminated, they may be suspended to keep them from processing while pooled. Once your card is pooled it should release resources such as files or database connections until it is resumed again. When a card receives a cardPooled notification it should clear its current state and listen for future invocations. In addition, cards must be written to support multiple instances which run simultaneously within the same sandbox.

Second, if an application with cards defines several card targets, then when it's retrieved from the pool, the card may be invoked to service any of the declared targets. In other words, if a .bar file bundles a composer, previewer, and picker under a single entry point, then when it's retrieved from the pool, the application or card may be invoked as any of these targets.

Thirdly, cards generally occupy the full screen of the BlackBerry device. However, some applications may show the status bar and require the card to be resized if it covers the status bar. Therefore, applications with cards should always listen for the Event.RESIZE event on the main stage of the running app and resize the cards according to the size of the main stage.

BlackBerry 10 OS manages the pooling of cards. The pooling is also dependent on varying factors of the device state. This means that in certain situations, a card may not be pooled. In such cases, the card receives the exit message that indicates to the card that it should terminate.

Prepare your cards for resizing and rotation

Cards can be rotated and resized. Rotation occurs when a user rotates the BlackBerry device. When the device is rotated, the main screen is automatically resized to the new dimensions of the card. Your application's card must listen for the Event.RESIZE event on the main stage of your application and resize the UI according to the size of the main stage. Here's how a card handles the resizing request:

stage.addEventListener( Event.RESIZE, onStageResize );
private function onStageResize( event:Event ):void
{
      trace( "new stage size", stage.stageWidth, stage.stageHeight );
      //resize your UI to the new dimensions.
 }

A card’s orientation is aligned with the orientation of the parent application. If the parent application's orientation is fixed, any child cards in the stack also have a fixed orientation.

When you create cards, you must add support for both landscape and portrait orientation so that the card follows the orientation of your application.

Card security

Cards have their own identity and sandbox environment that is shared with all instances of the card. Like applications, cards are processed in their own context and with their own permissions. It is important to pay attention to the capabilities and the data that you want to expose using your card.

comments powered by Disqus