Skip to content

Exploring the Capacitor NFC API

Near Field Communication (NFC) has become an essential technology for modern mobile applications, enabling seamless interactions between devices and smart objects. With the Capacitor NFC plugin from Capawesome, developers can integrate powerful NFC capabilities into their Ionic and Capacitor applications, bridging the gap between web technologies and native device features through a unified NFC API that works seamlessly across multiple platforms, including Android, iOS, and Web.

Terms and Concepts

Before diving into the details of the Capacitor NFC API, let's clarify some key terms and concepts related to NFC technology:

  • NFC Tag: A small, passive device that can store data and communicate with NFC-enabled devices when they are in close proximity (typically within a few centimeters).
  • NFC Reader: A device that can read data from NFC tags and interact with them. This can be a smartphone, tablet, or any other NFC-enabled device.
  • Host Card Emulation (HCE): A feature that allows an application to emulate an NFC tag, enabling it to interact with NFC readers as if it were a physical NFC tag. This is particularly useful for applications that need to provide NFC functionality without requiring a physical tag.
  • NDEF (NFC Data Exchange Format): A standardized format for storing data on NFC tags, allowing different devices to read and write data in a consistent manner.

Installation

To install the Capacitor NFC plugin, please refer to the Installation section in the plugin documentation.

Usage

Let's explore the key features of the Capacitor NFC API and how to use them effectively in your Ionic applications.

Checking Availability

Before using any NFC functionality, it's essential to check if NFC is available on the device. The Capacitor NFC API provides the isAvailable(...) method for this purpose:

import { NFC } from '@capawesome-team/capacitor-nfc';

const isAvailable = async () => {
  const { hce, nfc } = await NFC.isAvailable();
  if (!nfc) {
    alert('NFC is not available on this device. Please check your device settings.');
  } else if (!hce) {
    alert('Host Card Emulation (HCE) is not available on this device. Some features may be limited.');
  }
};

This method checks whether both NFC and Host Card Emulation (HCE) are available on the device. In most cases, you will want to ensure that NFC is available before proceeding with any NFC operations. HCE is an advanced feature that allows your application to emulate an NFC tag, enabling more complex interactions with NFC readers.

If a feature is not available that you need, you should inform the user about the limitation and should not attempt to use that feature in your application.

Checking Status

To ensure that NFC is enabled on the device, you can use the isEnabled(...) method:

const isEnabled = async () => {
  const enabled = await NFC.isEnabled();
  if (!enabled) {    
    alert('NFC is disabled. Please enable it in your device settings.');
  }
};

This method checks if NFC is enabled. If NFC is disabled, you can prompt the user to enable it in their device settings. For this, you can use the openSettings(...) method to direct users to the NFC settings page:

import { NFC } from '@capawesome-team/capacitor-nfc';

const openSettings = async () => {
  await NFC.openSettings();
};

Handling Permissions

To ensure your application has the necessary permissions to use NFC, you can check and request permissions using the checkPermissions(...) and requestPermissions(...) methods:

const checkPermissions = async () => {
  const permissions = await NFC.checkPermissions();
  if (!permissions.nfc) {
    alert('NFC permission is required to use this feature.');
  }
};

const requestPermissions = async () => {
  const permissions = await NFC.requestPermissions();
  if (!permissions.nfc) {
    alert('NFC permission was denied. Please enable it in your device settings.');
  }
};

Make sure to call these methods before performing any NFC operations to ensure your application has the necessary permissions.

Reading NFC Tags

To finally read your first NFC tag (including NDEF messages), you need to start a scan session using the startScanSession(...) method. This method allows you to listen for NFC tags using the nfcTagScanned event. Here's a simple example of how to read an NFC tag:

import { Nfc } from "@capawesome-team/capacitor-nfc";

const read = async () => {
  return new Promise((resolve) => {
    Nfc.addListener("nfcTagScanned", async (event) => {
      await Nfc.stopScanSession();
      resolve(event.nfcTag);
    });

    Nfc.startScanSession();
  });
};

As soon as an NFC tag is hold near the device, the nfcTagScanned event will be triggered, and you can access the scanned tag data. After reading the tag, it's important to stop the scan session using the stopScanSession(...) method to free up system resources.

Writing NDEF Messages

To write NDEF messages to an NFC tag, you need to use the write(...) method. But before writing, you need to create an NDEF record. The Capacitor NFC API provides a Utils class that helps you create various types of NDEF records, such as text, URI, and MIME records. Here's an example of how to create a text record:

import { NfcUtils } from "@capawesome-team/capacitor-nfc";

const createNdefTextRecord = () => {
  const utils = new NfcUtils();
  const { record } = utils.createNdefTextRecord({
    text: "Capacitor NFC Plugin",
  });
  return record;
};

You can then use the write(...) method to write this record as part of an NDEF message to an NFC tag:

import { Nfc } from "@capawesome-team/capacitor-nfc";

const write = async () => {
  return new Promise((resolve) => {
    const record = createNdefTextRecord();

    Nfc.addListener("nfcTagScanned", async (event) => {
      await Nfc.write({ message: { records: [record] } });
      await Nfc.stopScanSession();
      resolve();
    });

    Nfc.startScanSession();
  });
};

As with reading, you have to start a scan session first to listen for NFC tags. When a tag is scanned, the nfcTagScanned event will be triggered, and you can write the NDEF message to the tag using the write(...) method.

Making NFC Tags Read-Only

To make an NFC tag read-only, you can use the makeReadOnly(...) method. This method allows you to set the tag to read-only mode, preventing any further modifications to its data:

import { Nfc } from "@capawesome-team/capacitor-nfc";

const makeReadOnly = async () => {
  return new Promise((resolve) => {
    Nfc.addListener("nfcTagScanned", async (event) => {
      await Nfc.makeReadOnly();
      await Nfc.stopScanSession();
      resolve();
    });

    Nfc.startScanSession();
  });
};

This method is useful when you want to ensure that the data on an NFC tag cannot be modified after it has been written, providing a level of data integrity and security.

Warning

This is a one-way operation and cannot be undone. Once an NFC tag has been made read-only, it can no longer be written to.

Erasing NFC Tags

To remove all data from an NFC tag, you can use the erase(...) method. This method allows you to erase all NDEF records from the tag:

import { Nfc } from "@capawesome-team/capacitor-nfc";

const erase = async () => {
  return new Promise((resolve) => {
    Nfc.addListener("nfcTagScanned", async (event) => {
      await Nfc.erase();
      await Nfc.stopScanSession();
      resolve();
    });

    Nfc.startScanSession();
  });
};

This method is useful when you want to clear the data on an NFC tag, allowing it to be reused for new data at a later time.

Warning

This operation will remove all data from the NFC tag, including any NDEF records. Use it with caution, as it cannot be undone.

Advanced

The Capacitor NFC API also provides advanced features for more complex NFC operations. Let's explore some of these features.

Executing Raw Commands

Executing raw commands is a common requirement for advanced NFC applications, especially when dealing with specific NFC tag types or protocols. The Capacitor NFC API allows you to execute raw commands using the transceive(...) method. You can find a list of supported commands in the technical documentation of the NFC tag you are working with.

Here's an example of how to execute a raw command to read a signature from an NFC tag:

const readSignature = async () => {
  return new Promise((resolve) => {
    Nfc.addListener('nfcTagScanned', async (event) => {
      if (Capacitor.getPlatform() === 'android') {
        // 1. Connect to the tag.
        await Nfc.connect({ techType: NfcTagTechType.NfcA }); 
        // 2. Send one or more commands to the tag and receive the response.
        const result = await Nfc.transceive({ data: [60, 0] });
        // 3. Close the connection to the tag.
        await Nfc.close();
        await Nfc.stopScanSession();
        resolve(response);
      } else {
        // 1. Send one or more commands to the tag and receive the response.
        const result = await Nfc.transceive({ techType: NfcTagTechType.NfcA, data: [60, 0] });
        await Nfc.stopScanSession();
        resolve(response);
      }
    });

    Nfc.startScanSession();
  });
};

Again, you need to start a scan session to listen for NFC tags. When a tag is scanned, the nfcTagScanned event will be triggered, and you can execute the raw command using the transceive(...) method. The method takes an array of bytes as input and returns the response from the NFC tag.

Emulating NFC Tags

Emulating NFC tags allows your application to act as an NFC tag, enabling interactions with NFC readers. The Capacitor NFC API provides two event listener and one method for this purpose:

Here's an example of how to set up NFC tag emulation:

import { Nfc } from '@capawesome-team/capacitor-nfc';

const addListener = async () => {
  Nfc.addListener('commandReceived', async (event) => {
    console.log(event.data);
    await respond({ data: [...] });
  });
};

This time you don't need to start a scan session, as the NFC reader will initiate the communication. The commandReceived event will be triggered whenever a NFC reader sends an Application Protocol Data Unit (APDU) command to your application. You can respond to these commands using the respond(...) method, which allows you to send data back to the NFC reader.

??? + info

The NDEF format is not supported for tag emulation. Only raw commands can be sent to NFC readers during emulation.

Retrieve NFC Antenna Information

On Android, you can retrieve information about the NFC antenna using the getAntennaInfo(...) method. This method provides details about the NFC antenna, such as the device height and width, and the antenna's position on the device:

import { Nfc } from "@capawesome-team/capacitor-nfc";

const getAntennaInfo = async () => {
  const antennaInfo = await Nfc.getAntennaInfo();
  console.log("Device Height:", antennaInfo.deviceHeight);
  console.log("Device Width:", antennaInfo.deviceWidth);
  console.log("Is Devive Foldable:", antennaInfo.isDeviceFoldable);
  console.log("X Position of first antenna:", antennaInfo.availableAntennas[0].locationX);
  console.log("Y Position of first antenna:", antennaInfo.availableAntennas[0].locationY);
};

This method is particularly useful for applications that want to provide visual feedback to users about where to place their NFC tags for optimal scanning performance. By understanding the antenna's position, you can guide users to hold their NFC tags in the right spot for successful interactions.

Best Practices

When working with the Capacitor NFC API, consider these best practices:

  1. Always check NFC availability and status: Use the isAvailable(...) and isEnabled(...) methods to ensure that NFC is available and enabled on the device before attempting any NFC operations. This helps prevent errors and provides a better user experience.

  2. Handle permissions properly: Check and request permissions using the checkPermissions(...) and requestPermissions(...) methods before performing any NFC operations. This ensures that your application has the necessary permissions to access NFC features and prevents unexpected behavior.

  3. Manage scan sessions carefully: Always stop scan sessions when done to free up system resources using the stopScanSession(...) method. This is especially important in mobile applications where resource management is crucial for performance and battery life.

  4. Implement error handling: Use the scanSessionError event to handle errors that may occur during NFC operations. This allows you to provide feedback to users and handle unexpected situations gracefully.

  5. Optimize for user experience: Provide clear instructions to users on how to use NFC features in your application. For example, guide them on how to hold their device and NFC tags for optimal scanning performance. Use visual cues or animations to enhance the user experience.

Conclusion

The Capacitor NFC Plugin from Capawesome provides a powerful and flexible solution for integrating NFC capabilities into Ionic applications. By offering a unified API across multiple platforms, it enables developers to create sophisticated NFC-enabled applications without the complexity of platform-specific implementations.

To stay updated with the latest updates, features, and news about the Capawesome, Capacitor, and Ionic ecosystem, subscribe to the Capawesome newsletter and follow us on X (formerly Twitter).

If you have any questions or need assistance with the Capacitor NFC Plugin, feel free to reach out to the Capawesome team. We're here to help you make the most of NFC technology in your Ionic applications.