Build a BlackBerry Express Plugin

Cascades

Guest post by Johan Larsby.

BlackBerry Express

Following the recent success of BlackBerry Express, we received several questions from developers about how to write plug-ins that serve images for presentations created within the app. Today’s post will address some of those questions.

Similar to other apps, BlackBerry Express can invoke cards.  To familiarize yourself with the process, we created an app that allows you to search through DeviantArt and select an image to use in your presentation. We also created a ”Hello World” project and made a few changes so that it could be launched as a card as well as a standalone app.

First, we modify the bar-descriptor to tell the system that it can be invoked. We also need to change the main function so that it could respond to invocations.

ApplicationUI::ApplicationUI(bb::cascades::Application *app) : QObject(app), m_InvokeManager(new InvokeManager(this))

Additionally, this is the signal that we needed to listen to for invocation:

void ApplicationUI::onInvoked(const bb::system::InvokeRequest &req)

With these steps, we can create an image and send it back. To do this, we fetch the media RSS provided by DeviantArt supplies into a data model we use to populate a list. When an image is chosen, we download and send it to the invoker.

The project is available on GitHub for more information on the steps involved. You can also get more information on invocation on the BlackBerry Developer site.

BlackBerry Express Screen Shot

Invocation documentation

Also provided below pieces of code to help you with the development process:

main.qml

Page {
     ...
     property variant appScene: Application.scene
     id: root
     signal cancel()
     signal select(string filePath) 
...

We use “select signal” and “cancel” to communicate to the C++ code when the user has either clicked on an item or pressed cancel:

applicationui.cpp

ApplicationUI::ApplicationUI(bb::cascades::Application *app) : QObject(app), m_InvokeManager(new InvokeManager(this)) 
{
     connect(m_InvokeManager, SIGNAL(invoked(const bb::system::InvokeRequest &)), this, SLOT(onInvoked(const bb::system::InvokeRequest &))); 
...
 QmlDocument *qml = QmlDocument::create("asset:///main.qml").parent(this);
           qml->setContextProperty("application", this);
           // Create root object for the UI
           AbstractPane *root = qml->createRootObject<AbstractPane>();

           // Set created root object as the application scene
           app->setScene(root);

           connect(root, SIGNAL(cancel()), this, SLOT(onCancel()));
           connect(root, SIGNAL(select(const QString&)), this, SLOT(onSelect(const QString&)));
 ...

To get the XML from DeviantArt, we use the built-in DataSource component. Here we listen to the signal on DataLoaded to populate our GroupData model with the relevant information:

RSSDataSource.qml

    onDataLoaded: {
        ...
         for (var i = 0; i < data.length; i ++) {
              tempdata[i] = data[i]

             // An invokable function in the C++ app code is used to parse the
             // data and look for an image that can be presented together with the text.
             tempdata[i].imageSource = application.findImage(data[i]);
             tempdata[i].description = data[i].description;
         }
 ....
         // Finally insert the data in the dataModel and it will be presented in the list.
         dataModel.insertList(tempdata)

We created a class that downloads images from the Internet for our ListItem:

ImageSearchListItem.qml

Container {
     property alias src: httpImage.url
     ...
       ImageView {
             id: imageView
             ....
       }
        ...
 attachedObjects: [
         HTTPImage {
             id: httpImage
             objectName: "httpImage"
             onImageDownloadComplete: {
                 imageView.image = image;
             }
      ...

And finally, when the user clicks on an item we download the image and save it:

main.qml:

   ListView {

                 dataModel: dataModel
                 onTriggered: {
                      if (indexPath.length > 1) {
                         var chosenItem = dataModel.data(indexPath);
                         httpDownloader.url = chosenItem.imageSource;
                        }}
                        ...
                        HTTPImage {
                 id: httpDownloader
                 onImageDownloadComplete: {

                                          var fullPath = httpDownloader.saveImage("imagesearch");
                     //this will trigger our select signal and the C++ code will be able to send the Card Done message
                     root.select(fullPath);
                 }
             }

If you have any questions about this or on how to develop other BlackBerry Express plug-ins, let us know in the comments below.

Join the conversation

Show comments Hide comments
+ -
blog comments powered by Disqus