Guest post by Johan Larsby.
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.
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.