PlayBook sample ActionScript Application using QNX components

I recently participated in the BlackBerry Developer Day co-presenting the BlackBerry PlayBook Tablet Bootcamp: Adobe AIR sessions. We led developers through the process of installing all the tools (Flash Builder Burrito, VMWare, BlackBerry Tablet OS SDK and Simulator) and getting up and running to build their first application. As part of this presentation I wanted to build a more in depth application then the basic hello world app. Also wanted to show some of the optimizations with QNX components around Lists, image caching with ImageCache, QNXApplication SWIPE_DOWN, and object pooling. To that end here is a screen shot of the application called DataExampleApp:

MWC BlackBerry Developer Day AIR PlayBook example app

The full source code for this application is located on my github here.

Workaround for PPSChannel error when running QNX PlayBook specific APIs on the Desktop

First thing is to note this is a workaround and might not work in the future or might not cover all the errors you might see. Take the simple use case of creating an AIR application for PlayBook and with a qnx.ui.text.TextInput component in the display list. Because the qnx.ui.text.TextInput class allows you to define which PlayBook KeyboardType is shown on the device it must call out to a PlayBook specific AIR API. If you try and run this application on the desktop you will see this error:

qnx.pps.PPSChannel Error Message

This error is because the AIR runtime on the desktop does not have a qnx.pps.PPSChannel class, this class is specific to the PlayBook version of the AIR runtime that RIM has extended in their BlackBerry Tablet OS.

Ok, so what if you still want to run it on the desktop to work on UI layout an not necessarily full functionality?

View the whole post »

QMXML and as3viewnavigator for the PlayBook

I continue to play with different ideas around using QNX (ActionScript 3 only classes) with MXML (non-Flex MXML) in a project called QMXML. My co-worker, Piotr Walczyszyn, at Adobe posted some classes to that provide view based navigation in ActionScript 3. I decided to extend his classes and make them work with QMXML. The source code for the examples below is on https://github.com/renaun/QNXUIExamples/ViewNavigator.

View based navigation allows you to push new views on to a stack and then navigate the views by popping or pushing views on or off. Also allows for navigating directly back to the first view. Its a lot like breadcrumbs. In the case of QMXML I create 2 new classes, QView that extends QContainer but implements IView. I decided on another class so if you don’t want to do view based navigation you can just use QContainer as is. The IView interface provides QView with the navigator property that you can use inside that view to pop or push views. The QViewNavigator extends Piotr’s original ViewNavigator but provides some extra properties to easily set the application (DisplayObject that will have a reference to stage) and the firstView in MXML. Continue below to see it in action in the video and some of the code.

View the whole post »

PlayBook QNX AudioManager Example

I wanted to show how to use another QNX AIR API, specifically the class AudioManager. It provides a singleton instance of the AudioManager which gives access to the available inputs and outputs on the device. You can then set the levels and mute state of both input and output. In the example code project QNXAudioManager it plays a local mp3 that is bundled with the application. It also displays the different event messages that are fired while making changes to the input or output. And it provides a QNX VolumeSlider to set the output level while playing the mp3.

Here is the main chunk of code that setups and uses the singleton instance of AudioManager.

ACTIONSCRIPT:
audioManager = AudioManager.audioManager;
log("AvailableInputs: " + audioManager.availableInputs.length)
for (var i:int = 0; i <audioManager.availableInputs.length; i++)
{
    log(i + " - " + audioManager.availableInputs[i]);   
}
log("AvailableOutputs: " + audioManager.availableOutputs.length);   
for (var j:int = 0; j <audioManager.availableOutputs.length; j++)
{
    log(j + " - " + audioManager.availableOutputs[j])
}
audioManager.addEventListener(AudioManagerEvent.AVAILABLE_INPUTS_CHANGED, eventHandler);
audioManager.addEventListener(AudioManagerEvent.AVAILABLE_OUTPUTS_CHANGED, eventHandler);
audioManager.addEventListener(AudioManagerEvent.CONNECTED_INPUT_CHANGED, eventHandler);
audioManager.addEventListener(AudioManagerEvent.CONNECTED_OUTPUT_CHANGED, eventHandler);
audioManager.addEventListener(AudioManagerEvent.INPUT_LEVEL_CHANGED, eventHandler);
audioManager.addEventListener(AudioManagerEvent.INPUT_MUTE_CHANGED, eventHandler);
audioManager.addEventListener(AudioManagerEvent.OUTPUT_LEVEL_CHANGED, eventHandler);
audioManager.addEventListener(AudioManagerEvent.OUTPUT_MUTE_CHANGED, eventHandler);
log("connectedInput: " + audioManager.connectedInput);
log("connectedInput: " + audioManager.connectedOutput);
audioManager.setInputMute(true);
audioManager.setInputMute(false);

There is only seems to be one input for the PlayBook; found at qnx.system.AudioInput.INPUT. But there are four different audio output types: qnx.system.AudioOutput.BLUETOOTH, qnx.system.AudioOutput.HDMI, qnx.system.AudioOutput.HEADPHONES, and qnx.system.AudioOutput.SPEAKERS. You can check the audioManager.connectedInput and audioManager.connectedOutput values against the constants above.

Then the slider changes the output level on slider_move event:

ACTIONSCRIPT:
protected function slider_slider_moveHandler(event:SliderEvent):void
{
    audioManager.setOutputLevel(event.value);
}

Here is what the app looks like on the simulator, nothing fancy but a way to check out the event firing off the AudioManager instance.

QNX AudioManager Example App

All the source code for this example is on github here.

Exploring the PlayBook application’s blackberry-tablet.xml

UPDATE: RIM has provide documentation on the blackberry-tablet.xml located here.

With the release of the BlackBerry Tablet OS SDK for Adobe AIR Beta 3 (0.9.2) developers have access to a new PlayBook application descriptor file called "blackberry-tablet.xml". This file has to be named exactly "blackberry-tablet.xml" and be placed in the root of the application structure, basically along side the AIR typical Xxxx-app.xml descriptor file.

I created a simple example application (BlackBerryTabletXMLOptions) that displays a smiley face image to the screen to talk about a couple of the attributes in the blackberry-tablet.xml file.

Here is what the application looks like:

Smiley Face App

You might be wondering how I got an application to show up over the main interface of the PlayBook. Well lets take a look at the blackberry-tablet.xml:

XML:
<qnx>
  <initialWindow>
    <systemChrome>none</systemChrome>
    <transparent>true</transparent>
  </initialWindow>
  <publisher>Renaun Erickson</publisher>
  <category>core.media</category>
  <icon>
    <image>renaun-icon.png</image>
  </icon>
  <splashscreen>renaun_com_splash.png</splashscreen>
</qnx>

What makes this work is the "transparent" attribute set to true. This allows your application to render transparently over the main interface of the playbook. The other attributes in the xml file to call out are "category", "icon.image", and "splashscreen". First the category allows you to set the values: core.media, core.internet, core.games, and core.utils. This category value is used to place the application and its custom icon defined in the xml above in the application categories that show up on the main screen of the PlayBook. See below that the BBTabletXMLOptions application is installed in the Media category area.

Application in Media Category

The splashscreen is the last attribute that is in this application. It takes a 1024x600 image that is shown before the application is activated.

Using the PlayBook QNX TextInput KeyboardType and ReturnKeyType

The PlayBook has a few different Keyboard types depending on what type of input the user is asked to provide. The BlackBerry Tablet OS SDK for Adobe AIR allows the developer to assign what type of keyboard should be shown for a specific input box.

For the video and images below I used an example project called KeyboardTypes, all the source for this and other projects is located at here.

First lets take a look at a picture containing all the current (as of 2011.01.19) keyboard types together.

Different PlayBook KeyboardTypes

To see how this all works on the Simulator both in landscape and portrait modes check out the video below:

Using the PlayBook QNX TextInput KeyboardType and ReturnKeyType from Renaun Erickson on Vimeo.

PickQuick AIR Game across TV, Android and iOS

I created this game called PickQuick for demoing and testing applications across screens. I have previously demo'd this working across various devices, but recently at the #jivhack (hackathon in Chicago this last weekend) I decided to code in the support for TV remotes and get it running on the TV with AIR for TV. Here is a video of the outcome:

PickQuick running on AIR for TV, Android, and iOS from Renaun Erickson on Vimeo.

The full source code of PickQuick is available on my github site.

Using BlackBerry PaymentService with Adobe AIR for the PlayBook

Part of BlackBerry's AppWorld services is the ability to have your users purchase goods inside your application. This service provides an API to use inside your AIR for PlayBook applications. Read on to check out the basics of using this new API, new as of Beta 3 or Tablet OS SDK for Adobe AIR 0.9.2.

I will show you how to use the API in local mode to test the different responses your application can get during a purchase sequence. To test the API for real you will have to register your goods with BlackBerry as a vendor. I am not familiar with that process at the moment, I'll leave that for another blog post. Here is a link for more information on the Payment Services.

View the whole post »

Using QNX Image and ImageCache in List Custom CellRenderer

In this blog I'll show how to create a custom cell renderer skin for the QNX UI component List class. The custom cell renderer will display an image, text, and box beneath the text for affect. The List class implements virtualization of the cell renderers and reuses instances of the objects that are displayed as you scroll up and down. This allows for memory optimization and speed gains by not creating and destroying a bunch of cell renderer instances. In the process of displaying images in virtualizated instances you end up changing the source each time the data is assigned to the cell renderer instance.

This causes a problem of performance and visual quirks. For example if updating the image url takes longer then the time it takes to have the data value changed with a new value (try flicking a long list really fast, the instances of the cell renderer will be set a bunch of times before it slows down). This situation might cause a flicker of the old image before the new image loads. Luckily QNX classes probably a mechanism to help with this situation.

View the whole post »

Run Through of PlayBook Beta3 AIR SDK Updates

Check out the latest development beta bits for developing applications for the PlayBook. Video covering the new Beta3 or BlackBerry Tablet OS SDK/Simulator 0.9.2 for Adobe AIR:

Run Through of PlayBook Beta3 AIR SDK Updates from Renaun Erickson on Vimeo.

Highlights:

  • Differences of old simulator and new simulator
  • New simulator portrait mode simulation
  • Sample HelloWorld application showing off blackberry-tablet.xml for custom splash screen and icon.

Here is the source Flex Hero application code for the application I used in the video:

XML:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
               xmlns:s="library://ns.adobe.com/flex/spark"
               width="100%" height="100%"
               resize="application1_resizeHandler(event)"
               applicationComplete="application1_applicationCompleteHandler(event)">

    <s:layout>
        <s:VerticalLayout />
    </s:layout>

    <fx:Script>
        <![CDATA[
            import mx.events.FlexEvent;
            import mx.events.ResizeEvent;

            protected function application1_applicationCompleteHandler(event:FlexEvent):void
            {
                stage.scaleMode = StageScaleMode.NO_SCALE;
                stage.align = StageAlign.TOP_LEFT;
                lblOrientation.text += "init: " + stage.orientation + " w/h: " + stage.stageWidth + "/" + stage.stageHeight + " s: " + stage.scaleX + "\n";
                stage.addEventListener(StageOrientationEvent.ORIENTATION_CHANGE, stageOrientationChange);
            }
            private function stageOrientationChange(event:StageOrientationEvent):void
            {
                lblOrientation.text += "stageOrientationChange: " + stage.orientation + " w/h: " + stage.stageWidth + "/" + stage.stageHeight + " s: " + stage.scaleX +
                    "\n>>event.beforeOrientation: " + event.beforeOrientation +
                    "\n>>event.afterOrientation: " + event.afterOrientation;
               
            }

            protected function application1_resizeHandler(event:ResizeEvent):void
            {
                if (stage)
                    lblOrientation.text += "resize: " + stage.orientation + " w/h: " + stage.stageWidth + "/" + stage.stageHeight + " s: " + stage.scaleX + "\n";
            }
        ]]>
    </fx:Script>
    <s:Button label="Some Button" />
    <s:TextArea id="lblOrientation" width="100%" height="100%" />
</s:Application>