BlackBerry 10 - Sharing using NfcShareManager

by Retired on ‎12-04-2012 01:18 PM - edited on ‎12-04-2012 01:49 PM by Retired (5,220 Views)

Introduction

 

This article is part of a series intended to help developers wishing to exploit Near Field Communication (NFC) in their BlackBerry® 10 applications. Readers of this article should have some pre-existing knowledge of the fundamental architecture of NFC systems and be familiar with C++. It would be valuable to have read the earlier BlackBerry 10 articles in this series since they lay the foundations for the later ones such as this one.

 

This article will explain how to use the BlackBerry 10 C++ native APIs to develop software, which can transmit data from one NFC-enabled BlackBerry device to another using the NFC Sharing APIs.

 

The Authors

 

This article was co-authored by Martin Woolley and John Murray both of whom work in the RIM Developer Relations team. Both Martin and John specialize in NFC applications development (amongst other things).

 

Sharing Information

 

We got really excited when we discovered the APIs we’re going to describe in this article! Sharing information in a simple and intuitive way is one of the fundamental use-cases of NFC, and the BlackBerry 10 NFC Sharing APIs make that easy to integrate into your application.

 

The first thing to think about is what sort of information you might want to share easily between devices. We had a think about this and came up with three simple examples that should cover the most common cases:

 

  1. Information that could be identified by a URL. The URL itself would be shared and interpreted by the recipient device.
  2. Information that could be described by a MIME type. So, for example, a string of plain text described by the MIME type “text/plain”, or a string of HTML identified by the MIME type “text/html”.
  3. And, since Martin is a really good photographer as well as being an NFC guru, we decided to share images and photographs stored on one device with another device.

Now, this becomes interesting in that items (1) and (2) consist of objects that generally consist of small amounts of data whilst (3) generally consists of objects that are large. NFC is great when all you want to do is transfer small volumes of data between devices. However, when you want to transfer several megabytes of data then you run into a challenging user-experience; the nature of NFC is that the devices would have to be held in close proximity for an extended time, increasing the possibility of the devices misaligning and the transfer failing. Also, NFC is relatively slow compared to Wi-Fi® or Bluetooth®.

 

So, to have a seamless and pleasant user experience, item (3) would have to be done in two stages:

 

  1. Use NFC to initiate the negotiation of a Bluetooth connection between the two devices.
  2. And, transfer the bulk data of the images via that Bluetooth connection.

This would mean that the devices need only be in close proximity whilst negotiating the Bluetooth link and they could then be separated once the Bluetooth link has seen established.

 

This is where the NFC Forum standards come to our aid. One of the Peer to Peer (P2P) standards is called Connection Handover and does just what we wanted to do in this case. It’s also implemented on both BlackBerry 10 and BlackBerry 7.1 so that we could demonstrate this ability between BlackBerry 10 and BlackBerry 7.1 devices.

 

The Application

 

The application user interface is pretty simple. It consists of a “TabbedPane” Cascades™ object with three pages, one for each of the use cases. You can see the general layout in the three images in Figure 1.

 

Each page has a pair of buttons that switches data sharing on or off. In the case of sharing data and a URL, the actual data to be shared can be entered directly from the page itself. In the case of sharing image files, it was easier to allow the user to select, via checkboxes, one or more of three images that were placed into the “assets” folder of the application rather than having to supply a path to a file.

 

tabs.png

Figure 1 - The three use cases

 

The images shown in Figure 1 come from our Twitter® pages: John ( @jcmrim), Martin (@mdwrim), and our colleague in Canada, Rob (@robbieDubya). The others, which you can see by scrolling down, were taken by Martin.

 

As an interesting and instructive aside, Cascades does not have a built-in checkbox with an associated image, but one of the really nice things about Cascades is that it is easy to create one by aggregating “CheckBox” and “ImageView” as shown in Figure 2 below.

 

import bb.cascades 1.0

Container {

    id: myCheckBox

    property string message
    property string file
    property string thumb
    property alias checked: fileBox.checked 
    
    signal myCheckChanged(bool checked)

    layout: StackLayout {
        orientation: LayoutOrientation.LeftToRight
    }

    bottomMargin: 10

    CheckBox {
        verticalAlignment: VerticalAlignment.Center
        id: fileBox
	    onCheckedChanged: {
	        myCheckBox.myCheckChanged(checked);
	    }
    }

    ImageView {
        imageSource: "asset:///files/" + myCheckBox.thumb
        preferredWidth: 625

        onTouch: {
            if (event.isUp()) {
                checked = checked ? false : true;
            }
        }
    }
}

Figure 2 - Aggregating CheckBox with a clickable image

 

The way that the application works is that the act of entering information into any of the text fields, selecting one or more images, or clicking the enable or disable buttons, will result in one or more SIGNAL()s (see Figure 3) being emitted from the QML pages, which are connected to three key C/C++ functions in the application:

 

  • dataShareContentChanged(...)
  • urlShareContentChanged(...)
  • fileShareContentChanged(...)

  

    _nfcShareManager = new NfcShareManager();
...
    QObject::connect(  _shareDataPage, SIGNAL(updateMessage(QString, QString)),
    		                  this,   SLOT(dataShareContentChanged(QString, QString)));
...
    QObject::connect(  _shareFilePage, SIGNAL(updatedFileList(QString)),
    		                  this,   SLOT(fileShareContentChanged(QString)));
...
    QObject::connect(   _shareUrlPage, SIGNAL(updateUrl(QString)),
    		                  this,   SLOT(urlShareContentChanged(QString)));
...
    QObject::connect(            this, SIGNAL(setShareMode(bb::system::NfcShareMode::Type)),
    		      _nfcShareManager,   SLOT(setShareMode(bb::system::NfcShareMode::Type)));

Figure 3 - Connecting the QML events to the sharing actions in C/C++

 

Let’s look at each case in turn.

 

Sharing a Data Item

 

It’s really quite simple to share a data item with an associated MIME type. All you need to do is build a request to send to an instance of the NfcShareManager class, (which we obtained as shown in Figure 3), and pass this to the setShareContent() method of this class. That’s all there is to it. It’s all there in Figure 4.

 

void NfcSharing::dataShareContentChanged(QString message, QString dataType) {
    NfcShareDataContent request;
    QByteArray data(message.toUtf8());
    QUrl url;
    request.setUri(url);
    request.setMimeType(dataType);
    request.setData(data);
    NfcShareSetContentError::Type rc = _nfcShareManager->setShareContent(request);
}

 Figure 4 - Sharing a data Item

 

 

Sharing a URL is equally easy and is shown in Figure 5.

 

void NfcSharing::urlShareContentChanged(QString urlString) {
    NfcShareDataContent request;
    QUrl url(urlString);
    request.setUri(url);
    NfcShareSetContentError::Type rc = _nfcShareManager->setShareContent(request);
}

 Figure 5 - Sharing a URL item

 

 

You might think that sharing a list of image files and having a Bluetooth connection negotiated to have them transferred would be more complex. It isn’t! The whole process is shown in Figure 6.

 

void NfcSharing::fileShareContentChanged(QString paths) {
    NfcShareFilesContent request;
    QList<QUrl> urls;
    QDir dir;
    QStringList list = paths.split(",");
    QString publicPath(dir.currentPath().append("/app/public/"));

    for (int i = 0; i < list.size(); ++i) {
        QUrl url(QString("file://").append(publicPath).append(list.at(i)));
        urls.append(url);
    }

    request.setFileUrls(urls);
    NfcShareSetContentError::Type rc = _nfcShareManager->setShareContent(request);
}

 Figure 6 - Sharing a list of files

 

 

It’s easy isn’t it? There is one point where care needs to be taken though. The actual heavy lifting of using NFC to negotiate the Bluetooth connection and of the subsequent transfer of the files to the other device is performed by another system application called the NFC Share Adapter. The NFC Share Adapter needs to have read access to the files to be transferred and so care must be taken to ensure that they are accessible in terms of file access permissions.

 

Since the image files we’re using are located in the Assets folder in the project, they need to be flagged as “public” as shown in Figure 7, otherwise they will not be accessible.

 

assets.png

Figure 7 - Ensure that image files are shared as public

 

So, we’ve set up the mechanics for sharing these three types of data. However, how do we know whether a particular object has been shared successfully? There is still one set of SIGNAL()s to connect and these are with the NfcShareManager instance itself as shown in Figure 8.

 

...    
QObject::connect(_nfcShareManager,SIGNAL(shareModeChanged(bb::system::NfcShareMode::Type)),
    		              this,  SLOT(shareModeChanged(bb::system::NfcShareMode::Type)));
QObject::connect(_nfcShareManager,SIGNAL(finished(bb::system::NfcShareSuccess::Type)),
    		              this,  SLOT(finished(bb::system::NfcShareSuccess::Type)));
QObject::connect(_nfcShareManager,SIGNAL(error(bb::system::NfcShareError::Type)),
    		              this,  SLOT(error(bb::system::NfcShareError::Type)));
...

QObject::connect(            this,SIGNAL(setShareMode(bb::system::NfcShareMode::Type)),
    		  _nfcShareManager,  SLOT(setShareMode(bb::system::NfcShareMode::Type)));

 Figure 8 - Connections to the NfcShareManager

 

Two of the connections are used to notify our application as to the success or failure of a sharing operation (“finished” and “error” respectively).  “shareModeChanged” is used to notify our application of a change in the sharing mode type (Data or File). “setShareMode” is used by our application to establish the sharing mode type that the NfcShareManager is to use on our behalf (Data or File).

 

Sharing in Action

 

So, let’s see the application in action. Since working with images is more interesting, let’s look at the steps that take place for this case. Figure 9 shows a data transfer request, with the selection made on a BlackBerry 10 device on the left, and the notification on a BlackBerry 7.1 device on the right. The BlackBerry 7.1 device is configured to ensure that approval must be given to allow the transfer to take place.

 

Notice that there doesn’t need to be an application running on the target device. The NFC software on the target device, whether it’s a BlackBerry 10 or BlackBerry 7.1 device, is smart enough to recognise the MIME type of the data being transferred and to launch the most appropriate application to handle it.

 

select_send.png

Figure 9 - Initiate sharing and accept the transfer

 

Once approval has been given, the transfer starts to take place over a Bluetooth connection that has been established. Figure 10 shows the transfer of an image in progress on a BlackBerry 7.1 device.

 

receiving_bb7.png

Figure 10 - Receiving the data

 

Once the BlackBerry 7.1 device has successfully received the file, a confirmation dialogue is displayed as shown in Figure 11, and just for completeness, the image that we transferred is also shown.

 

received_and_preview.png

Figure 11 - Completion and transferred image at the BlackBerry 7.1 device end

 

Summary

 

Wasn’t that easy? What we’ve learned is that it’s simple to integrate data and file transfer operations into your BlackBerry 10 application. I’m sure you can think of many other applications for this ability.

 

Where can I find the code?

 

The full source code of this application is available from our GitHub repositories here:

https://github.com/blackberry/Cascades-Community-Samples/tree/master/NfcSharing

 

The NfcSharing application was written for the BlackBerry 10 “Dev Alpha” device and requires the following versions of the NDK and device software to build and run:

 

  • BlackBerry® 10 Native SDK 10.0.9
  • BlackBerry Dev Alpha Device Software 10.0.9 (Beta 4)

You can find details of other NFC related articles and sample applications written by Martin and John at:

http://supportforums.blackberry.com/t5/Java-Development/NFC-Article-and-Code-Index/ta-p/1538775

 

You can contact Martin or John either through the BlackBerry support forums or through Twitter:

 

  Support Forum ID Twitter
Martin mwoolley @mdwrim
John jomurray @jcmrim

 

If you like this article and code sample and have found it useful then drop us a Tweet (hash tag: #nfcguys).