Sending content using NFC Share Cards

The NFC Share Card is one of the many BlackBerry 10 cards that can be invoked by the invocation framework on behalf of an app. Your app can send an InvokeRequest to the invocation framework in order to share content with the help of the NFC Share Card. These requests and handlers can be created in QML using and InvokeActionItem, or they can be created in C++ using the InvokeManager class.

In either case, your app must set the action property of the InvokeRequest to a value of bb.action.SHARE. Then it must set the InvokeRequest object's uri, mimeType, or data properties. Once this is done, the InvokeRequest is sent by your app to the invocation framework.

The invocation framework will invoke the Share dialog as shown in the screenshot to the right. This Share dialog contains a list of all invocation targets that are registered to share the content provided by the invoking application. Users can select an application from the menu to help them share their content. As you can see in the image to the right, these invocation targets include the NFC Share Card.

Image showing a share card

If the user selects the NFC Share Card from the above Share dialog, then the NFC Share Card shown in the screenshot to the right is displayed with a preview of the shared content.

As you can see in the screen shot to the right, the NFC Share Card is ready to share an image file. In this case, Bluetooth Connection Handover is used to share the image file with the NFC target device.

For more information on the Connection Handover NFC specification, see NFC Forum: Reference Application Specifications.

Image showing a share card

Supported functionality of the NFC Share Card

The NFC Share Card supports the following:
  • Writing small amounts of data to an NFC tag.
  • Sending small amounts of data to another NFC-enabled device using SNEP.
  • Transferring files to another NFC-enabled device using NFC Connection Handover with Bluetooth transport.

The NFC Share Card uses the following criteria to select one of the above sharing approaches:

  • The combination of uri, mimeType and data property values defined within the InvokeRequest.
  • The type of content being shared and the NFC target detected. The NFC target is an NFC Tag or NFC-enabled device that is receiving the content. For example, content that is a Data type can either be written to NFC-tags, or sent using SNEP to NFC devices. Content that is a File type is typically sent using the Bluetooth Connection Handover approach.

The NFC Share Card is registered with the invocation framework by default. This is done to ensure that it will always get displayed in the list of invocation targets shown in the Share dialog when the action element of an InvokeRequest is set to bb.action.SHARE.

When your app shares content with the help of Share Cards, it doesn't have control over which card will be selected by a user who wants to share their content. Your app can control which Share Cards appear in the list of invocation targets by specifying the type of content that will be shared. This is done using the uri, mimeType and data property values defined within the InvokeRequest, as mentioned above.

For example, if an app decides to share text content, and packages it as a text/plain MIME-type, any share card that is registered to handle that MIME-type will appear in the Share dialog.

When your app wants to target the NFC Share Card specifically, the text content should be wrapped within an NDEF message, and the MIIME-type of the shared content should be set to application/vnd.rim.nfc.ndef. You can also specify the invocation target by setting the target property of the InvokeRequest to sys.NFCViewer, which will invoke the NFC Viewer app.

Most common use case for sharing content

The most common use case for sharing content with the help of Share Cards is the process described above using the invocation framework to select the content to share (uri, mimeType or data) and letting the invocation framework build a list of invocation targets to display to the user in the Share dialog. This use case is illustrated in the flow and sequence diagram shown below.

Flow diagram: Sharing content using the NFC Share Card

The following diagram illustrates the flow when sharing file content using the NFC Share Card.

Flow diagram showing how to write files with share cards

The following diagram illustrates the flow when sharing data content using the NFC Share Card.

Flow diagram showing how to write data content with share cards

Sequence diagram: Sharing content using the NFC Share Card

The following diagram illustrates the sequence of events that occur when sharing content using the NFC Share Card.

Sequence diagram showing how to share content using the invocation framework and share cards

The above diagrams depict the complete interaction between the device components involved in the process of sharing over NFC with the help of Share Cards. It's important to remember that your app's involvement is limited to interacting with the components of the invocation framework, which includes the InvokeActionItem or InvokeRequest.

Code sample: Sending content using NFC Share Cards

Sharing content with the help of Share Cards requires a trigger to initiate the process. Your app can trigger the share action when the user selects content to share, and chooses the Share action from the Share Menu. The share action can also be triggered when the user clicks on a UI element, such as a Button.

As you can see in the code sample below, the Share Menu is triggered when the user presses and holds (long presses) one of the Button controls on the application screen. Each Button defines an InvokeActionItem that is used by the Share Menu to find matching Cards (invocation targets) for the content that the app wants to share. These invocation Share actions are defined in your app's QML file.

Button {
    text: "Text"
    contextActions: [
        ActionSet {
            InvokeActionItem {
                id: textActionItem
                onTriggered: {
                    data = _app.createTextRecordNdef("Shared Card via Invocation Framework");
                }
                query {
                    mimeType: "text/plain"
                    invokeActionId: "bb.action.SHARE"
                }
            }
        }
    ]
}
Button {
    text: "URI"
    contextActions: [
        ActionSet {
            InvokeActionItem {
                id: uriActionItem
                onTriggered: {
                    data = _app.createUriRecordNdef("www.rim.com");
                }
                query {
                    mimeType: "application/vnd.rim.nfc.ndef"
                    invokeActionId: "bb.action.SHARE"
                }
            }
        }
    ]
}
Button {
    text: "Smart Poster"
    contextActions: [
        ActionSet {
            InvokeActionItem {
                id: spActionItem
                onTriggered: {
                    data = _app.createSpRecordNdef("Shared Card via Invocation Framework", "www.rim.com");
                }
                query {
                    mimeType: "application/vnd.rim.nfc.ndef"
                    invokeActionId: "bb.action.SHARE"
                }
            }
        }
    ]
}
Button {
    text: "File"
    contextActions: [
        ActionSet {
            InvokeActionItem {
                id: fileActionItem
                query {
                    uri: _app.getFilePath("/accounts/1000/shared/downloads/IMG 00000001.jpg");
                    invokeActionId: "bb.action.SHARE"
                }
            }
        }
    ]
}
Button {
    text: "Contact"
    contextActions: [
        ActionSet {
            InvokeActionItem {
                id: contactActionItem
                onTriggered: {
                    data = _app.getContactData();
                }
                query {
                    mimeType: "text/vcard"
                    invokeActionId: "bb.action.SHARE"
                }
            }
        }
    ]
}
Button {
    text: "Calendar"
    contextActions: [
        ActionSet {
            InvokeActionItem {
                id: calActionItem
                onTriggered: {
                    data = _app.getCalData();
                }
                query {
                    mimeType: "text/calendar"
                    invokeActionId: "bb.action.SHARE"
                }
            }
        }
    ]
}

When a share action Button is clicked, the code within the onTriggered signal handler is executed. This calls the Qt code to create the data that's being sent. In this case, the sample can return the text entered in the text field, or it can create an NDEF message with a URI, or a SmartPoster record.

QByteArray ApplicationUI::getText(const QString& text) {
    return text.toUtf8();
}
 
QByteArray ApplicationUI::createUriRecordNdef(const QString& uri) {
    QNdefNfcUriRecord uriRecord;
    uriRecord.setUri(QUrl(uri));
 
    QNdefMessage message;
    message.append(uriRecord);
    return message.toByteArray();
}
 
QByteArray ApplicationUI::createSpRecordNdef(const QString& title, const QString& uri) {
    QNdefNfcSmartPosterRecord spRecord;
    // Not useful but here for completeness.
    spRecord.setAction(QNdefNfcSmartPosterRecord::Unset); 
    spRecord.addTitle(title, "en", QNdefNfcTextRecord::Utf8);
    spRecord.setUri(QUrl(uri));
 
    QNdefMessage message;
    message.append(spRecord);
    return message.toByteArray();
}
 
QByteArray ApplicationUI::getContactData() {
    QByteArray data("BEGIN:VCARD\nVERSION:3.0\nPRODID:-//Research In Motion//RIM App//
                     EN\nUID: 2\nFN:#AUTO\nN:;#AUTO;;;\nORG:;;\nTEL;TYPE=CELL:#2886\nEND:VCARD");
    return data;
}
 
QByteArray ApplicationUI::getCalData() {
    QByteArray data("BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:-//Research In Motion//RIM App//
                     EN\nUID:example@rim.com\nDTSTAMP:20140714T170000Z\nORGANIZER;CN=John 
                     Doe:MAILTO:john.doe@rim.com\nDTSTART:20150714T170000Z\nDTEND:20160715T035959Z\n
    SUMMARY:Birthday Party\nEND:VEVENT\nEND:VCALENDAR");
    return data;
}
 
QString ApplicationUI::getFilePath(const QString& path) {
    return "file://" + path;
}

Once the content that is being sent has been created, the app's sharing process ends. Now the app waits for the Menu Service to deliver the content as an Invoke request to the Share Card that was selected by the user in the Share dialog. It's important to note that the app does not stop executing, it's only the app's function call to create the content that ends. The app cannot be closed until the Share Card has completed its tasks and has been closed.

In the above sample, the content type is text/plain for the text sharing case. The NFC Share Card is one of the invocation target candidates shown in the Share dialog.

For the URI and SP sharing case, the content type is application/vnd.rim.nfc.ndef, which identifies it as NDEF content. In this case, the NFC Share Card will most likely be the only invocation target for that particular content type. Once NFC is selected for sharing, the NFC Share Card is launched to share the data with other NFC targets, such as an NFC tag or NFC-enabled device.

For sharing content in the form of a file, the NFC Share Card is one of the share card candidates. If the NFC Share Card is selected, it attempts to perform an NFC connection handover with the other NFC-enabled device, and send the file to the target device over Bluetooth.

Last modified: 2014-01-07

comments powered by Disqus