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

Native SDK Development

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

My name’s Martin Woolley and I work in BlackBerry's Developer Relations team as a Senior Application Development Consultant. I’ve been with BlackBerry since 2009 but have worked in software development in various capacities for 30 years in a whole range of industry sectors and on numerous computing platforms small and large. These days I specialise in areas such as Bluetooth Low Energy, NFC, Internet of Things (Iot) and wearable technologies amongst other things.

Join the conversation

Show comments Hide comments
+ -
blog comments powered by Disqus