# react-native-nfc-manager
[](https://www.npmjs.com/package/react-native-nfc-manager)
[](https://travis-ci.org/whitedogg13/react-native-nfc-manager)
[](https://github.com/whitedogg13/react-native-nfc-manager/issues)
Bring NFC feature to React Native. Inspired by [phonegap-nfc](https://github.com/chariotsolutions/phonegap-nfc) and [react-native-ble-manager](https://github.com/innoveit/react-native-ble-manager)
Contributions are welcome!
Made with ❤️ by [whitedogg13](https://github.com/whitedogg13) and [revteltech](https://github.com/revtel)
## Install
### javascript part
```shell
npm i --save react-native-nfc-manager
```
### native part
This library use native-modules, so you will need to do `pod install` for iOS:
```shell
cd ios && pod install && cd ..
```
For Android, it should be properly auto-linked, so you don't need to do anything.
## Setup
Please see [here](setup.md)
### **Android 12**
We start to support Android 12 from `v3.11.1`, and you will need to update `compileSdkVersion` to `31`, otherwise the build will fail:
```
buildscript {
ext {
...
compileSdkVersion = 31
...
}
...
}
```
The reason for this is because Android puts new limitation on [PendingIntent](https://developer.android.com/reference/android/app/PendingIntent#FLAG_MUTABLE) which says `Starting with Build.VERSION_CODES.S, it will be required to explicitly specify the mutability of PendingIntents`
> The original issue is [here](https://github.com/revtel/react-native-nfc-manager/issues/469)
BTW, if you don't care about **Android 12** for now, you can use **`v3.11.0`** as a short term solution.
### **[Demo App] NfcOpenReWriter**
We have a full featured NFC utility app using this library available for download.
It also open sourced in this repo: [React Native NFC ReWriter App](https://github.com/revtel/react-native-nfc-rewriter)
## Learn
We have published a React Native NFC course with [newline.co](https://www.newline.co/), check it out!
- Free course (1 hour) about basic NFC setup and concept [here](https://www.youtube.com/watch?v=rAS-DvNUFck)
- Full course (3 hours) for more (NDEF, Deep Linking, NTAG password protection, signature with UID) [here](https://www.newline.co/courses/newline-guide-to-nfcs-with-react-native)
## Usage
The simplest (and most common) use case for this library is to read `NFC` tags containing `NDEF`, which can be achieved via the following codes:
```javascript
import React from 'react';
import {View, Text, TouchableOpacity, StyleSheet} from 'react-native';
import NfcManager, {NfcTech} from 'react-native-nfc-manager';
// Pre-step, call this before any NFC operations
NfcManager.start();
function App() {
async function readNdef() {
try {
// register for the NFC tag with NDEF in it
await NfcManager.requestTechnology(NfcTech.Ndef);
// the resolved tag object will contain `ndefMessage` property
const tag = await NfcManager.getTag();
console.warn('Tag found', tag);
} catch (ex) {
console.warn('Oops!', ex);
} finally {
// stop the nfc scanning
NfcManager.cancelTechnologyRequest();
}
}
return (
Scan a Tag
);
}
const styles = StyleSheet.create({
wrapper: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
});
export default App;
```
Pleaes notice when running above codes, iOS and Android has different behaviors:
- iOS will pop up a system scanning UI
- Android provides **NO** system scanning UI
Regarding the system scannning UI, both platforms should be able to scan your NFC tags succesfully and print out its content.
### Old Style (registerTagEvent) To Scan NFC Tags
There's an alterntaive style to scan NFC tags through `NfcManager.registerTagEvent`, like this:
```javascript
import NfcManager, {NfcTech} from 'react-native-nfc-manager';
// The following function resolves to a NFC Tag object using old event listener approach.
// You can call it like this:
// `const nfcTag = await listenToNfcEventOnce()`
function listenToNfcEventOnce() {
const cleanUp = () => {
NfcManager.setEventListener(NfcEvents.DiscoverTag, null);
NfcManager.setEventListener(NfcEvents.SessionClosed, null);
};
return new Promise((resolve) => {
let tagFound = null;
NfcManager.setEventListener(NfcEvents.DiscoverTag, (tag) => {
tagFound = tag;
resolve(tagFound);
NfcManager.unregisterTagEvent();
});
NfcManager.setEventListener(NfcEvents.SessionClosed, () => {
cleanUp();
if (!tagFound) {
resolve();
}
});
NfcManager.registerTagEvent();
});
}
```
As you can see, the above approach is more verbose and hard-to-read, so we recommend using `NfcManager.requestTechnology` instead of `NfcManager.registerTagEvent` in your application.
## Advanced Usage Concept
In higher level, there're 4 steps to use this library:
1. request your particular NFC technologies through `NfcManager.requestTechnology`, for example:
- `Ndef`
- `NfcA`
- `NfcB` (Android-only)
- `NfcF` (Android-only)
- `NfcV` (Android-only)
- `IsoDep`
- `MifareClassic` (Android-only)
- `MifareUltralight` (Android-only)
- `MifareIOS` (ios-only)
- `Iso15693IOS` (ios-only)
- `FelicaIOS` (ios-only)
2. select the proper NFC technology handler, which is implemented as getter in main `NfcManager` object, for example:
- `ndefHandler` (for `Ndef` tech)
- `nfcAHandler` (for `NfcA` tech)
- `isoDepHandler` (for `IsoDep` tech)
- `iso15693HandlerIOS` (for `Iso15693IOS` tech)
- `mifareClassicHandlerAndroid` (for `mifareClassic` tech)
- `mifareUltralightHandlerAndroid` (for `mifareUltralight` tech)
- ... and so on
3. call specific methods on the NFC technology handler (for example `NfcManager.ndefHandler.writeNdefMessage`). To view all available methods for some tech handler, check out the [API List](index.d.ts)
4. clean up your tech registration through `NfcManager.cancelTechnology`
## Advanced Usage Example: NDEF-Writing
For example, here's an example to write NDEF:
```javascript
import NfcManager, {NfcTech, Ndef} from 'react-native-nfc-manager';
async function writeNdef({type, value}) {
let result = false;
try {
// STEP 1
await NfcManager.requestTechnology(NfcTech.Ndef);
const bytes = Ndef.encodeMessage([Ndef.textRecord('Hello NFC')]);
if (bytes) {
await NfcManager.ndefHandler // STEP 2
.writeNdefMessage(bytes); // STEP 3
result = true;
}
} catch (ex) {
console.warn(ex);
} finally {
// STEP 4
NfcManager.cancelTechnologyRequest();
}
return result;
}
```
## Advanced Usage Example: Mifare Ultralight
Here's another example to read a Mifare Ultralight tag:
```javascript
async function readMifare() {
let mifarePages = [];
try {
// STEP 1
let reqMifare = await NfcManager.requestTechnology(
NfcTech.MifareUltralight,
);
const readLength = 60;
const mifarePagesRead = await Promise.all(
[...Array(readLength).keys()].map(async (_, i) => {
const pages = await NfcManager.mifareUltralightHandlerAndroid // STEP 2
.mifareUltralightReadPages(i * 4); // STEP 3
mifarePages.push(pages);
}),
);
} catch (ex) {
console.warn(ex);
} finally {
// STEP 4
NfcManager.cancelTechnologyRequest();
}
return mifarePages;
}
```
To see more examples, please see [React Native NFC ReWriter App](https://github.com/revtel/react-native-nfc-rewriter)
## API
Please see [here](index.d.ts)
## FAQ
Please see [here](FAQ.md)
## Expo
> This package cannot be used in the "Expo Go" app because [it requires custom native code](https://docs.expo.io/workflow/customizing/).
After installing this npm package, add the [config plugin](https://docs.expo.io/guides/config-plugins/) to the [`plugins`](https://docs.expo.io/versions/latest/config/app/#plugins) array of your `app.json` or `app.config.js`:
```json
{
"expo": {
"plugins": ["react-native-nfc-manager"]
}
}
```
Next, rebuild your app as described in the ["Adding custom native code"](https://docs.expo.io/workflow/customizing/) guide.
> Notice: This Config Plugin will ensure the minimum Android SDK version is 31.
#### Props
The plugin provides props for extra customization. Every time you change the props or plugins, you'll need to rebuild (and `prebuild`) the native app. If no extra properties are added, defaults will be used.
- `nfcPermission` (_string | false_): Sets the iOS `NFCReaderUsageDescription` permission message to the `Info.plist`. Setting `false` will skip adding the permission. Defaults to `Allow $(PRODUCT_NAME) to interact with nearby NFC devices` (Info.plist).
- `selectIdentifiers` (_string[]_): Sets the iOS [`com.apple.developer.nfc.readersession.iso7816.select-identifiers`](https://developer.apple.com/documentation/bundleresources/information_property_list/select-identifiers) to a list of supported application IDs (Info.plist).
- `systemCodes` (_string[]_): Sets the iOS [`com.apple.developer.nfc.readersession.felica.systemcodes`](https://developer.apple.com/documentation/bundleresources/information_property_list/systemcodes) to a user provided list of FeliCa™ system codes that the app supports (Info.plist). Each system code must be a discrete value. The wild card value (`0xFF`) isn't allowed.
#### Example
```json
{
"expo": {
"plugins": [
[
"react-native-nfc-manager",
{
"nfcPermission": "Custom permission message",
"selectIdentifiers": ["A0000002471001"],
"systemCodes": ["8008"]
}
]
]
}
}
```