Using NFC with Cordova Mobile Apps

Why NFC Tags?

NFC Tags are used extensively in agri-tech, warehouse, and logistics operations to track real-life objects.

With COVID-19, contactless technology has acquired importance in commercial and consumer applications. We see a need to scan NFC tags with mobile applications beyond the above well-known industrial applications.

Cordova

Cordova is a cross-platform mobile framework for apps in Android and iOS. Building a Cordova mobile app is easy for web developers as it uses the standard HTML, CSS, and JavaScript technologies. One use either plain JavaScript or one of the more expressive Single Page Application (SPA) frameworks, such as React, Vue, or Angular.

While Cordova may seem like a browser packaged in a mobile app, it is quite powerful in contactless technology in general and NFC in particular.

Cordova and NFC

The PhoneGap NFC Plugin provides a simple way to read and write NFC tags using the NDEF format for data.

In passing, we should mention that PhoneGap is a now-defunct version of Cordova, provided at some point by Adobe.

Reading NFC with Cordova

We used it in a Cordova mobile app, built using Vue.js with Vuetify for the user interface.

The UI with Vuetify

A UI component for reading NFC is activated with a button click,

  <v-card-actions>
  <v-btn flat color="orange" v-on:click="scanNFC()">Scan NFC</v-btn>
</v-card-actions>

Check Availability of NFC on Device

The function scanNFC first checks if NFC is enabled. If it is disabled and NFC is available on the device, it triggers the phone Settings app to allow its NFC sensor to interact with NFC tags.

  window.nfc.enabled(
    () => {
      // NFC enabled
      this.registerTagEvent()
    },
    (error) => {
      if (error === 'NFC_DISABLED') {
        // Trigger the phone settings to enable the NFC settings
        window.nfc.showSettings()
      } else if (error === 'NO_NFC') {
        navigator.notification.alert('Cannot scan NFC', () => {}, 'No NFC', 'OK')
      }
    }
  )

Read the NFC

If NFC is enabled, we register to listen to it:

registerTagEvent () {
     window.nfc.addNdefListener(
    this.displayNDEF,
    () => {
      console.log('succeess registering ndef listener')
    },
    (error) => {
      console.log('failure registering ndef listener', error)
    }
 )
}

The listener, displayNDEf decomposes the NDEF message:

displayNdef (nfcEvent) {
  // Decode tag data from the plugin
  let tag = nfcEvent.tag
  let tagId = window.nfc.bytesToHexString(tag.id)
  let message = window.nfc.bytesToString(tag.ndefMessage[0].payload)
}

Release the Listener on Exit

Generally, in Vue.js, one should clean listeners when leaving the component. But for NFC, there is an additional important reason to do it. We do not want to keep reading the nearby NFC tag once we leave the view. So we add a lifecycle hook,

    deactivated () {
    this.unregisterTagEvent()
  },

  unregisterTagEvent () {
  // Test if the plugin is defined
  if ((typeof nfc) !== 'undefined') {
    window.nfc.removeNdefListener(this.displayNdef)
  }
},