Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Native Development Knowledge Base

NFC on BlackBerry 10 - peer to peer communication using SNEP

by Retired ‎06-13-2012 03:14 PM - edited ‎10-10-2012 10:23 AM (6,302 Views)

Introduction

 

This article is part of a series intended to help developers wishing to exploit 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++. You are expected to have read at least the first parts of the corresponding article from the BlackBerry® 7 series of articles entitled: "NFC – Peer to Peer Communication with SNEP" since this covers concepts which are as applicable to BlackBerry 10 as they are to BlackBerry 7. The BlackBerry 7 article can be found here.

 

This article will explain how to use the BlackBerry 10 C++ native API to develop software, which can transmit data from one NFC device to another using the Simple NDEF Exchange Protocol.

 

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).

 

About SNEP

“Peer to Peer” is one of the three modes of operation defined for NFC devices. It provides a mechanism by which data can be transferred from one device to another and, based on the ISO14443 type F variant, has more bandwidth available to it than other protocol variants such as A and B. Developers can use peer to peer mode by implementing either SNEP or LLCP (Logical Link Control Protocol). This article is about using SNEP on BlackBerry 10 from a C++ application.

 

SNEP allows all manner of data type to be transferred and uses the NDEF data format used with NFC tags. As such, the supported types include MIME types and therefore content such as vCards are well suited to being transferred in this way.

 

When a SNEP “responder” comes into proximity with another device, it automatically negotiates and establishes an LLCP connection with the other device, which it then uses to transfer an NDEF message across the contactless interface to the other device.

 

There’s a size limit of approximately 8K that applies to NDEF content transferred using SNEP from a BlackBerry device.

 

Developers faced with requirements to transfer large amounts of data should consider using NFC to initiate a connection handover to Bluetooth® and then use Bluetooth file transfer.

 

NFC Tool V2 - The Sample Application

 

IMG_00000042.png

Figure 1 - NFC Tool's home screen

 

In our article on reading and writing tags from a BlackBerry 10 application, we introduced the sample application “NFC Tool”. To accompany this article, we’ve created version 2 of NFC Tool and added a new option to the menu, “Send vCard (SNEP)” which you can see in Figure 1 above.

 

In the sections that follow, we’ll examine code fragments from this new aspect of NFC Tool to illustrate exactly how to proceed in your own code. We won’t be revisiting the overall design of NFC Tool or how we’ve used Cascades and the Qt framework since we’ve covered these issues in the previous article. We’ll just focus on the new aspects of NFC Tool version 2.1 and the specifics relating to the use of SNEP to transfer a vCard.

 

We’ve released version 2.1 of NFC Tool in full in our GitHub® repository, details of which can be found at the end of this article.

 

NFC Tool V2.1 – UI Design

 
Figure 3 gives an overview of the basic flow between pages involved in the "Send vCard (SNEP)" function.

 

UI Overview.png

Figure 2 - NFC Tool V2 – Send vCard (SNEP): user interface overview

 

The basic UI design is simple. The home screen provides a list of menu items that you can select by touching. When the “Send vCard (SNEP)” option is selected, we display a page that allows the user to enter details to encapsulate within a basic vCard structure. On selecting the “Send vCard” button at the foot of this page, we navigate to a live event log viewer page where details of the progression of the function are displayed for informative purposes. The user should bring another NFC device into proximity with their BlackBerry 10 device at this point and the SNEP transfer will take place.

 

Implementation Details

 

In this section, we’ll review the changes that were made to NFC Tool to incorporate the SNEP vCard capability. We won’t dwell on user interface issues but will focus immediately on those changes made to incorporate the required NFC operation.

 

The NfcManager class provides a simple, facade-like interface that other classes can use to initiate the various NFC operations. We added a new function “sendVcard” to NfcManager and this is shown in Figure 3 below.

 

void NfcManager::sendVcard(QString* first_name, QString* last_name,
                           QString* address, QString* email, QString* mobile) {

	_first_name = first_name;
	_last_name = last_name;
	_address = address;
	_email = email;
	_mobile = mobile;
	Logger::getInstance()->clearLog();
	_workerInstance = NfcWorker::getInstance();
	QObject::connect(
            this,
            SIGNAL(start_send_vcard(QVariant,QVariant,QVariant,QVariant,QVariant)),
            _workerInstance,
            SLOT(sendVcard(QVariant,QVariant,QVariant,QVariant,QVariant)),
            Qt::QueuedConnection);
	emit start_send_vcard(QVariant::fromValue(*first_name),
            QVariant::fromValue(*last_name), QVariant::fromValue(*address),
            QVariant::fromValue(*email), QVariant::fromValue(*mobile));
}

  Figure 3 – NfcManager’s sendVcard function

 

It’s important to run NFC operations in a background thread since some of the function calls are blocking calls. As such, we use QtConcurrent to run code implemented in our NfcWorker class in a separate thread. The NfcManager::sendVcard function is exposed as a SLOT in the NfcWorker class and the above code invokes it in the background thread and passes the data entered by the user in the vCard details screen to it.

 

Let’s examine the code in NfcWorker next.

void NfcWorker::sendVcard(const QVariant &first_name, const QVariant &last_name,
        const QVariant &address, const QVariant &email, const QVariant &mobile) {
	prepareToSendVcard(first_name, last_name, address, email, mobile);
}

  Figure 4 – NfcWorker::sendVcard

 

The steps followed in NfcWorker::sendVcard follow exactly the same pattern as our other NFC functions supported by NFC Tool. In our call to prepareToSendVcard, which we’ll examine shortly, we start logging to the event log screen and set things up for executing the SNEP transfer. The NfcWorker thread is already in a loop in the listen() function, processing and responding to events from the BlackBerry Platform Services event queue. Figure 5 shows the prepareToSendVcard function.

 

void NfcWorker::prepareToSendVcard(const QVariant &the_first_name,
               const QVariant &the_last_name, const QVariant &the_address,
               const QVariant &the_email, const QVariant &the_mobile) {
	if (_failedToInitialize) {
            return;
	}
	QString first_name = the_first_name.toString();
        QString last_name = the_last_name.toString();
        QString address = the_address.toString();
        QString email = the_email.toString();
        QString mobile = the_mobile.toString();
	StateManager* state_mgr = StateManager::getInstance();
        state_mgr->setNdefPushState(true);
	emit message(QString("Preparing to send VCARD using SNEP"));
        emit message(QString("First Name: '%1'").arg(first_name));
        emit message(QString("Last Name: '%1'").arg(last_name));
        emit message(QString("Address: '%1'").arg(address));
        emit message(QString("Email: '%1'").arg(email));
        emit message(QString("Mobile: '%1'").arg(mobile));
	_first_name = first_name;
        _last_name = last_name;
        _address = address;
        _email = email;
        _mobile = mobile;
        _taskToPerform = SEND_VCARD;
	int rc = nfc_register_snep_client();
}

 

 Figure 5 – preparing to send the vCard over SNEP

 

Here’s what’s happening in the prepareToSendVcard function. First, we check that the initialization step completed successfully. We then write some messages to the event log screen by emitting the message signal that we connected to the event log elsewhere in our code. We save the parameters to be used in our vCard object and set a variable called _taskToPerform, which is used later on to control how we respond to NFC events. Critically, we invoke the nfc_register_snep_client() function, which establishes our application as a SNEP responder.

 

// part of the listen() function
void NfcWorker::listen() {
[......]
	while (!_timeToDie) {
[......]
		rc = bps_get_event(&event, BPS_EVENT_TIMEOUT);
[......]
		handleNfcEvent(event);

 Figure 6 – Listening for events and dispatching them for handling

 

The listen() function is involved in all NFC operations that our NFC Tool application supports and is running in a background thread that was started when the application itself started.  A small fragment of this function is shown in Figure 6. All it does is sit in a loop, reading event objects from the BlackBerry Platform Services queue and then calling handleNfcEvent where the event will be handled according to its type and the value of the _taskToPerform variable.

 

Figure 7 shows the relevant parts of the handleNfcEvent function.

 

void NfcWorker::handleNfcEvent(bps_event_t *event) {
	emit message("Handling an NFC event");
	switch (_taskToPerform) {
       [....]
	case SEND_VCARD:
		handleSendVcardEvent(event);
		break;
	}
        [....]
}

 Figure 7 - handleNfcEvent

 

The handleSendVcardEvent function drives the logic that formulates a vCard string and then writes it out over the NFC interface. Figure 8 shows this.

void NfcWorker::handleSendVcardEvent(bps_event_t *event) {
	uint16_t code = bps_event_get_code(event);
        nfc_event_t *nfcEvent;
	nfc_target_t* target;
        nfc_ndef_record_t* myNdefRecord;
        nfc_ndef_message_t* myNdefMessage;
	if (NFC_NDEF_PUSH_EVENT == code) {
		QString mimeType = QString("text/x-vCard");
		QString vCard = QString("BEGIN:VCARD\n")
				        .append("VERSION:3.0\n")
				        .append("FN:").append(_name).append("\n")
				        .append("ADR;TYPE=WORK:").append(_address).append("\n")
				        .append("TEL;TYPE=CELL:").append(_mobile).append("\n")
				        .append("EMAIL;TYPE=INTERNET:").append(_email).append("\n")
				        .append("END:VCARD");
                CHECK(nfc_get_nfc_event(event, &nfcEvent));
                CHECK(nfc_get_target(nfcEvent, &target));
		myNdefRecord = makeMediaRecord(mimeType, vCard);
		CHECK(nfc_create_ndef_message(&myNdefMessage));
		CHECK(nfc_add_ndef_record(myNdefMessage, myNdefRecord));
		CHECK(nfc_push_ndef_message(target, myNdefMessage));
		CHECK(nfc_delete_ndef_message(myNdefMessage, true));
		emit message(QString("vCard sent OK"));
	} else {
		qDebug()
				<< "XXX NfcWorker::handleSendVcardEvent - NFC BPS event that we didn't register for< "
				<< code;
	}
}

 

 Figure 8 – using SNEP to transfer a vCard message

 

The important aspects of Figure 8 are as follows. We commence by creating a string that contains the MIME type “text/x-vCard” and another string which contains our vCard in the standard format and which includes the values entered by the user. We then call a function we wrote called makeMediaRecord and which is depicted in Figure 9, passing these two strings as parameters. This returns an NDEF record which has TNF=2 meaning “TNF_MEDIA”. Details of this function are shown below. We then create an NDEF message and add our record to it.

 

Now that we have an NDEF message containing our vCard record, we can actually send the data across the NFC contactless interface. We accomplish this by calling the API function nfc_push_ndef_message. We finish off by deleting resources associated with the NDEF message by calling API function nfc_delete_ndef_message.

 

nfc_ndef_record_t* NfcWorker::makeMediaRecord(QString type, QString text) {
	nfc_ndef_record_t* record = 0;
	int textLen = text.length();
	int totalLen = textLen;
	uchar_t payload[totalLen];
	int offset = 0;
	memcpy(&payload[offset], text.toUtf8().constData(), textLen);
	CHECK(nfc_create_ndef_record(NDEF_TNF_MEDIA, type.toUtf8().constData(), payload, totalLen, 0, &record));
	return record;
}

 Figure 9 – Making an NDEF record of type NDEF_TNF_MEDIA

 

Testing

 

To test the SNEP function of NFC Tool V2.1, you'll need two devices. One must be a device on which NFC Tool can be installed, such as a BlackBerry 10 Dev Alpha. The other can be any device which supports SNEP such as a BlackBerry Bold 9900 running the BlackBerry OS version 7.1. Note that NFC peer-to-peer mode is supported from version 7.1 of the BlackBerry OS onwards.

 

To test, simply select the Send vCard function from the main menu of NFC Tool, edit the vCard details on the next screen, select the "Send vCard" button at the foot of that screen and then at the Event Log screen, bring the other device into proximity with the device running NFC Tool. The transfer should be automatically initiated and the NFC Tool event log screen will be updated with messages indicating the processing that is taking place as shown in Figure 10.

  

IMG_00000044.png

Figure 10 - NFC Tool's event log showing sending the vCard to the other device

 

How the receiving device behaves exactly will depend on what that device is. A BlackBerry 7 device like the BlackBerry® Bold™ 9900 will display a dialogue indicating that a contact has been received and giving you the option either to save it into the Contacts database or to cancel the operation. If you opt to save the vCard, you will next be presented with the new record in the Contacts application. Figures 11 and 12 show these two steps.

 

save_contact.png

Figure 11 - the receiving device prompting the user to save the vCard or cancel the operation

  

 

new_contact.png

Figure 12 - The vCard as new entry in the Contacts database

 

Summary

 

Using SNEP to serve NDEF messages using peer-to-peer mode from a BlackBerry 10 C++ application is very straightforward and follows a similar pattern to that which we saw in the previous article on Reading and Writing Tags with BlackBerry 10.

 

You can download NFC Tool V2, including its full source code from:

 

https://github.com/blackberry/Cascades-Community-Samples

 

 

The NFC Tool as 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.6
  • BlackBerry Dev Alpha Device Software 10.0.6

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

 

Users Online
Currently online: 4 members 5,078 guests
Please welcome our newest community members: