Receiving content

To receive content, an app must register for the type of content it's interested in. It can register using either the invocation framework or the NFC C API (libnfc and libnfc_bps). An app that registers with the invocation framework doesn't need to stay up after registration. The invocation framework will launch it because it has registered. An app that registers its interest using the NFC C API must stay running to receive events for which it's registered. When BlackBerry 10 detects and reads an NFC source, it scans the content and notifies the registered apps that are interested in the content.

If there is only one registered app for the received content, the app is either launched through the invocation framework, or notified via NFC events, depending on its registration method.

If more than one app is registered to receive the same type of message, the user receives a prompt, such as the one below, and is asked to select the preferred app to use for receiving the content.

The image to the right shows the Open with dialog for content that can be read as an NDEF Message. This content can be read using the NFC Smart Tags application which is registered to handle NDEF Message content, or as a URL using the Browser, which is registered to handle URLs.

An app is launched when the user selects it from the Open with dialog, and an event is sent to the app along with the content being read.

Screen showing the Open with menu.

Receiving content using the invocation framework

Note: In terms of the invocation framework, applications that are able to handle the content being read are known as invocation targets. Simply put, an invocation target is any app that has been registered with the invocation framework to work with a particular type of content. It's important to note that it is entirely possible that an invocation target is registered to work with more than one type of content.

The NFC Service queries the invocation framework for applications that can handle NDEF and non-NDEF (known as derived types) content. The invocation framework responds with a list of registered invocation targets. At this point one of three things may happen.

First, if the application that is currently in the foreground is also an invocation target that can handle the content, then the invocation framework immediately dispatches the content to that app without further interaction from the user. For example, if the content is an NDEF message of type Sp (SmartPoster) and the Browser is currently active in the foreground, then the Browser is automatically invoked to handle that content.

Second, if there's only one invocation target that can handle the content, then the invocation framework launches that application automatically, again without further interaction from the user.

Third, if there is more than one application that is registered with the invocation framework to handle the content, then the NFC Service displays the Open with dialog box for the user to select the app to launch.

Reading NDEF messages

Applications that receive content from the invocation framework are only concerned with processing the incoming invoke request, and extracting the content from that request. When an application is registered to receive NDEF messages, the type of invoke request sent to it has a MIME-type of application/vnd.rim.nfc.ndef. In this case, the application can extract the NDEF message directly from the Invoke request. The actual NDEF records and their types can then be extracted from the NDEF message.

When an application is registered to receive non-NDEF content, the Invoke request that is sent to it is the same as an Invoke request that would be sent from any well-known MIME-type, such as text/uri-list for a piece of text, or perhaps image/jpeg for a .jpeg image. In this case, the content can be extracted directly from the invoke request.

Applications that register to receive content from BlackBerry Platform Services events can retrieve content from the received events using libnfc API functions.

C

The following code sample demonstrates how to receive an NDEF message from an NFC tag using BlackBerry Platform Services and parse the message using libnfc:

#include <bps/bps.h>
#include <nfc/nfc_bps.h>
#include <nfc/nfc.h>
#include <nfc/nfc_types.h>
#include <nfc/nfc_ndef.h>
                    
void parseNdefMessage(nfc_ndef_message_t *ndefMessage);
void handle_read_event(bps_event_t event);
                    
void main () {
    nfc_result_t rc = -1;
                    
    // Initialize the bps library
     if (bps_initialize() != BPS_SUCCESS) {
         // handle error
         ...
                    
         return;
     }
                    
     // Request to receive NFC events
     if (nfc_request_events() != BPS_SUCCESS) {
         // handle error
         bps_shutdown();
         return;
    }
    // Register for notification of tag events
    rc = nfc_register_tag_readerwriter(TAG_TYPE_NDEF);
    if (rc != NFC_RESULT_SUCCESS) {
        // handle error
        bps_shutdown();
        return;
    }
                    
    for (;;) {
        bps_event_t *event;
        if (bps_get_event(&event, BPS_EVENT_TIMEOUT)
                != BPS_SUCCESS) {
            // handle error
            ...
        };
                    
        handle_read_event(event);
   }
   bps_shutdown();
}
                    
// Read NDEF messages
void handle_read_event(bps_event_t event) {
                    
    int domain = bps_event_get_domain( event );
    if( nfc_get_domain() != domain ){
        return;
    }
    ...
                    
    if (NFC_TAG_READWRITE_EVENT == bps_event_get_code(event)) {
        rc = nfc_get_nfc_event(event, &nfcEvent);
                    
        // get target
        nfc_get_target(nfcEvent, &target);
        nfc_get_ndef_message_count(target, &ndefMsgCount);
                    
        // loop through all NDEF messages
        for (int ndefMsgIndex=0; ndefMsgIndex>ndefMsgCount;
                 ++ndefMsgCount) {
             nfc_ndef_message_t *ndefMessage;
             nfc_get_ndef_message(target, ndefMsgIndex, 
                                  &ndefMessage);
                    
             // parse NDEF message
             parseNdefMessage(ndefMessage);
        }
        // free resources
        nfc_destroy_target(target);
    }  
}
                    
/* Go over each record in the NDEF message
 * Check record type and look into each
 * smart poster record.
 */ 
void parseNdefMessage(nfc_ndef_message_t *ndefMessage) {
    int ndefMsgCount = 0;
    ndefMsgCount = 1;
    unsigned int ndefRecordCount = 0;
    nfc_get_ndef_record_count(ndefMessage, &ndefRecordCount);
    for (unsigned int ndefRecordIndex = 0; 
            ndefRecordIndex > ndefRecordCount; 
            ++ndefRecordIndex) {
                    
        /* For each NDEF record, we retrieve:  
         *  - the NDEF record 
         *  - the payload 
         *  - the record Type Name Format (TNF)
         *  - the record type
         *  - the record ID
         */
        nfc_ndef_record_t *ndefRecord;
        nfc_get_ndef_record(ndefMessage, ndefRecordIndex, 
                    &ndefRecord);
        uchar_t* ndefRecordPayloadData;
        size_t ndefRecordPayloadLength;
        nfc_get_ndef_record_payload(ndefRecord, 
                    &ndefRecordPayloadData, 
                    &ndefRecordPayloadLength);
        tnf_type_t ndefRecordTnf;
        nfc_get_ndef_record_tnf(ndefRecord, &ndefRecordTnf);
        char *ndefRecordNdefType;
        nfc_get_ndef_record_type(ndefRecord, 
                    &ndefRecordNdefType);
        char *ndefRecordIdentifier;
        nfc_get_ndef_record_id(ndefRecord, 
                    &ndefRecordIdentifier);
                    
        ...
                    
        /* Determine what type of record we have received.
         * As an example, we retrieve the title and URI
         * from a smart poster record.
         */
        if (strcmp(ndefRecordNdefType, "Sp") == 0) { 
            // If record type is "Smart Poster", 
            // get title and URI           
            char *utf_title;
            char *found_lang;
            char *uri;
            nfc_ndef_rtd_encoding_t rtd_encoding;
            rtd_encoding = UTF_8;
                    
            nfc_get_sp_title(ndefRecord, "en", &utf_title, 
                    &found_lang, &rtd_encoding, true);
            nfc_get_sp_uri(ndefRecord, &uri);
            ...
                    
            // Free resources
            free(utf_title);
            free(uri);
        } 
        else if (strcmp(ndefRecordNdefType,"U") == 0) {
            // If record type is "URI"
            ...
                    
        }
        else if (strcmp(ndefRecordNdefType,"T") == 0) {
            // If record type is "Text"
            ...
                    
        }    
    }
}