Capacitor NFC Plugin (@exxili/capacitor-nfc)
A Capacitor plugin for reading and writing NFC tags on iOS and Android devices. This plugin allows you to:
- Read NDEF messages from NFC tags.
- Write NDEF messages to NFC tags.
Note: NFC functionality is only available on compatible iOS devices running iOS 13.0 or later.
Table of Contents
Installation
Install the plugin using npm:
npm install @exxili/capacitor-nfc
npx cap sync
iOS Setup
To use NFC functionality on iOS, you need to perform some additional setup steps.
1. Enable NFC Capability
In Xcode:
- Open your project (
.xcworkspace
file) in Xcode.
- Select your project in the Project Navigator.
- Select your app target.
- Go to the Signing & Capabilities tab.
- Click the
+ Capability
button.
- Add Near Field Communication Tag Reading.
2. Add Usage Description
Add the NFCReaderUsageDescription
key to your Info.plist
file to explain why your app needs access to NFC.
In your Info.plist
file (usually located at ios/App/App/Info.plist
), add:
<key>NFCReaderUsageDescription</key>
<string>This app requires access to NFC to read and write NFC tags.</string>
Replace the description with a message that explains why your app needs NFC access.
Android Setup
Add the following to your AndroidManifest.xml
file:
<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc" android:required="true" />
Usage
Import the plugin into your code:
import { NFC } from '@exxili/capacitor-nfc';
Reading NFC Tags
To read NFC tags, you need to listen for nfcTag
events. On iOS, you must also start the NFC scanning session using startScan()
.
import {NFC, NDEFMessagesTransformable, NFCError} from '@exxili/capacitor-nfc';
NFC.startScan().catch((error) => {
console.error('Error starting NFC scan:', error);
});
NFC.onRead((data: NDEFMessagesTransformable) => {
console.log('Received NFC tag:', data.string());
});
NFC.onError('nfcError', (error: NFCError) => {
console.error('NFC Error:', error);
});
Writing NFC Tags
To write NDEF messages to NFC tags, use the writeNDEF
method and listen for onWrite
events.
import { NFC, NDEFWriteOptions, NFCError } from '@exxili/capacitor-nfc';
const message: NDEFWriteOptions = {
records: [
{
type: 'T',
payload: 'Hello, NFC!',
},
],
};
NFC.writeNDEF(message)
.then(() => {
console.log('Write initiated');
})
.catch((error) => {
console.error('Error writing to NFC tag:', error);
});
NFC.onWrite(() => {
console.log('NDEF message written successfully.');
});
NFC.onError((error: NFCError) => {
console.error('NFC Error:', error);
});
API
Methods
isSupported()
Returns if NFC is supported on the scanning device.
Returns: Promise<{ supported: boolean }>
startScan()
Starts the NFC scanning session on iOS only. Android devices are always in reading mode, so setting up the nfcTag
listener is sufficient to handle tag reads on Android.
Returns: Promise<void>
NFC.startScan()
.then(() => {
})
.catch((error) => {
console.error('Error starting NFC scan:', error);
});
writeNDEF(options: NDEFWriteOptions<T extends string | number[] | Uint8Array = string)
Writes an NDEF message to an NFC tag.
Payload may be provided as a string, Uint8Array
, or an array of numbers. The plugin will automatically convert the payload to a byte array for storage on the NFC tag.
Android use: since Android has no default UI for reading and writing NFC tags, it is recommended that you add a UI indicator to your application when calling writeNDEF
and remove it in the nfcWriteSuccess
listener callback and the nfcError
listener callback. This will prevent accidental writes to tags that your users intended to read from.
Parameters:
options: NDEFWriteOptions<T extends string | number[] | Uint8Array = string>
- The NDEF message to write.
Returns: Promise<void>
NFC.writeNDEF(options)
.then(() => {
})
.catch((error) => {
console.error('Error writing NDEF message:', error);
});
cancelWriteAndroid()
Cancels an Android NFC write operation. Android does not have a native UI for NFC tag writing, so this method allows developers to hook up a custom UI to cancel an in-progress scan.
Listeners
onRead(listener: (data: NDEFMessagesTransformable) => void)
Adds a listener for NFC tag detection events. Returns type NDEFMessagesTransformable
, which returns the following methods to provide the payload:
string()
: Returns NDEFMessages<string>
, where all payloads are strings.
base64()
: Returns NDEFMessages<string>
, where all payloads are the base64-encoded payloads read from the NFC tag.
uint8Array()
: Returns NDEFMessages<Uint8Array>
, where all payloads are the Uint8Array
bytes from the NFC tag.
numberArray()
: Returns NDEFMessages<number[]>
, where all payloads bytes from the NFC tag represented as a number[]
.
Parameters:
listener: (data: NDEFMessagesTransformable) => void
- The function to call when an NFC tag is detected.
Returns: void
NFC.onRead((data: NDEFMessages) => {
console.log('Received NFC tag:', data);
});
onError(listener: (error: NFCError) => void)
Adds a listener for NFC error events.
Parameters:
listener: (error: NFCError) => void
- The function to call when an NFC error occurs.
Returns: PluginListenerHandle
NFC.onError((error: NFCError) => {
console.error('NFC Error:', error);
});
onWrite(listener: () => void)
Adds a listener for NFC write success events.
Parameters:
listener: () => void
- The function to call when an NDEF message has been written successfully.
Returns: PluginListenerHandle
NFC.onWrite('nfcWriteSuccess', () => {
console.log('NDEF message written successfully.');
});
Interfaces
NDEFWriteOptions
Options for writing an NDEF message.
interface NDEFWriteOptions<T extends string | number[] | Uint8Array = string> {
records: NDEFRecord<T>[];
}
NDEFMessagesTransformable
Returned by onRead
and includes the following methods to provide the payload:
string()
: Returns NDEFMessages<string>
, where all payloads are strings.
base64()
: Returns NDEFMessages<string>
, where all payloads are the base64-encoded payloads read from the NFC tag.
uint8Array()
: Returns NDEFMessages<Uint8Array>
, where all payloads are the Uint8Array
bytes from the NFC tag.
numberArray()
: Returns NDEFMessages<number[]>
, where all payloads bytes from the NFC tag represented as a number[]
.
interface NDEFMessagesTransformable {
base64: ()=> NDEFMessages;
uint8Array: ()=> NDEFMessages<Uint8Array>;
string: ()=> NDEFMessages;
numberArray: ()=> NDEFMessages<number[]>;
}
NDEFMessages
Data received from an NFC tag.
interface NDEFMessages {
messages: NDEFMessage[];
}
NDEFMessage
An NDEF message consisting of one or more records.
interface NDEFMessage {
records: NDEFRecord[];
}
NDEFRecord
An NDEF record. payload
is, by default, an array of bytes representing the data; this is how an NDEFRecord
is read from an NFC tag. You can choose to provide an NDEFRecord
as a string a Uint8Array
also.
interface NDEFRecord<T = number[]> {
type: string;
payload: T;
}
NFCError
An NFC error.
interface NFCError {
error: string;
}
Integration into a Capacitor App
To integrate this plugin into your Capacitor app:
-
Install the plugin:
npm install @exxili/capacitor-nfc
npx cap sync
-
Import the plugin in your code:
import { NFC } from '@exxili/capacitor-nfc';
-
Use the plugin methods as described in the Usage section.
Example
Here's a complete example of how to read and write NFC tags in your app:
import { NFC, NDEFMessages, NDEFWriteOptions, NFCError } from '@exxili/capacitor-nfc';
const { supported } = await NFC.isSupported();
NFC.startScan().catch((error) => {
console.error('Error starting NFC scan:', error);
});
NFC.onRead((data: NDEFMessages) => {
const stringMessages: NDEFMessage<string> = data.string();
const uint8ArrayMessages: NDEFMessage<Uint8Array> = data.uint8Array();
console.log('Received NFC tag:', stringMessages.messages?.at(0)?.records?.at(0).payload);
console.log('Received NFC tag:', uint8ArrayPayloads.messages?.at(0)?.records?.at(0).payload);
});
NFC.onError((error: NFCError) => {
console.error('NFC Error:', error);
});
const message: NDEFWriteOptions = {
records: [
{
type: 'T',
payload: 'Hello, NFC!',
},
],
};
NFC.writeNDEF(message)
.then(() => {
console.log('Write initiated');
})
.catch((error) => {
console.error('Error writing to NFC tag:', error);
});
NFC.onWrite('nfcWriteSuccess', () => {
console.log('NDEF message written successfully.');
});
License
MIT License
Support: If you encounter any issues or have questions, feel free to open an issue.