DEVELOPERS BLOG

Porting BlackBerry Java NFC Applications to BlackBerry 10 Part 4: Reading a Contactless Card

NFC contactless

Today’s post is the fourth part of a si- part series on porting BlackBerry Java applications that use NFC to BlackBerry 10. So far, we’ve looked at Tag Reading, Tag Writing and Peer to Peer mode. This time, we’ll review the porting of code that deals with reading contactless NFC cards such as transportation tickets.

Here’s where we are in the series as a whole:

  1. Reading NFC Tags
  2. Writing NFC Tags
  3. Peer to Peer Mode
  4. Reading NFC Contactless Cards
  5. NFC Virtual Tag and Card Emulation
  6. NFC Card Emulation

Reading NFC Contactless Cards – Issues for Java Developers:

  1. Detecting the card: The application must implement the DetectionListener interface and register it with ReaderWriterManager.addDetectionListener(…). When a card comes into proximity with the device, there will be a callback to the DetectionListener.
  1. Exchange ISO7816-4 APDUs with the card: We then obtain an ISO14443Part4Connection object associated with the Target provided in the callback to the DetectionListener and use the connection object’s transceive method to exchange ISO7816-4 APDUs in byte array format.

The BlackBerry 10 Native approach:

We use BPS (BlackBerry Platform Services) to detect and then exchange ISO7816-4 APDUs with the card.

Detecting the card (“target”) is the same as for writing a tag and is explained elsewhere in this guide.  Exchanging APDUs with the card is shown in the following code fragment which formulates and exchanges a SELECT command with the card:

int NfcWorker::selectByAID(uchar_t* the_aid, int aid_size, nfc_target_t* target) {       int apdu_size = 5 + aid_size;       uchar_t select_command[apdu_size];       select_command[0] = 0x00; // CLA       select_command[1] = 0xA4; // INS       select_command[2] = 0x04; // P1       select_command[3] = 0x00; // P2       select_command[4] = aid_size; // Lc       int j = 5;       for (int i = 0; i < aid_size; i++) {             select_command[j] = the_aid[i];             j++;       }       return exchangeApdu(select_command, apdu_size, target); }  int NfcWorker::exchangeApdu(uchar_t* the_apdu, int apdu_size, nfc_target_t* target) {       QByteArray requestData = QByteArray::fromRawData(reinterpret_cast<const char *>(the_apdu), apdu_size);       QString requestAsHex = QString::fromAscii(requestData.toHex());       qDebug() << "XXXX request:" << requestAsHex;        int MAX_RESPONSE_SIZE = 256;       size_t rlength;       // Allocate response buffer       // (max size determined by application)       uchar_t response[MAX_RESPONSE_SIZE];       int rc = nfc_tag_transceive(target, TAG_TYPE_ISO_14443_4, the_apdu, apdu_size, response, MAX_RESPONSE_SIZE, &rlength);       if (rc == NFC_RESULT_SUCCESS) {             QByteArray responseData = QByteArray::fromRawData(reinterpret_cast<const char *>(response), rlength);             QString responseAsHex = QString::fromAscii(responseData.toHex());             qDebug() << "XXXX response:" << responseAsHex;       } else {             qDebug() << "XXXX " << QString("ERROR transmitting APDU:%1:%2").arg(rc).arg(Utilities::getOperationResultName(rc));       }       return rc; }

Hopefully this was helpful and will make your porting work nice and easy!

Resources

Sample Code:

Contacts:

About mdwrim