Using NFC With iOS in React Native

A look at react-native-nfc-manager

Tamas Szikszai
Nov 10 · 6 min read

With iOS 13, Apple finally opened the SDK to write data on some of the most popular NFC chips.

Thankfully one of the most popular (and to my knowledge, only) NFC React Native libraries, react-native-nfc-manager, also added (some) support to do this. Let’s see how it works in practice!

TL;DR 1: Too lazy to read? Watch the video:

TL;DR 2: Just want the code? Here is the code!


Installing the Library

Installation is actually super simple. First, we need to add the module via npm.

npm i --save react-native-nfc-manager

For Android, that’s it. For iOS, you have to do a couple of extra steps. First of all, run a pod install:

cd ios && pod install && cd ..

Then, you have to add the following lines to your info.plist (in ios/YourProject):

<key>NFCReaderUsageDescription</key>
<string>YOUR_PRIVACY_DESCRIPTION</string>

You also need to add the “Near Field Communication Tag Reading” capability to your app:


Scaffolding

First, let’s make some buttons and scaffolding code:

import React, { Component } from 'react';
import {
SafeAreaView,
StyleSheet,
View,
Text,
TextInput,
Alert,
Platform,
TouchableOpacity
} from 'react-native';
import NfcManager, { NfcTech } from 'react-native-nfc-manager';

There is not much to explain here.

We’ve set up an input field that will contain the text we want to write to our tag. Also two buttons, one for writing and one for reading. Finally, a text field for logging stuff. Pretty basic…


Writing Data

With all honesty, before writing this article, I didn’t know that there are different NFC chips. I simply ordered the cheapest one from Amazon, which happened to be a Mifare Ultralight chipset one.

Unluckily, the library’s support for this chipset on iOS is pretty basic: all you can do is send commands to the chip.

My first instinct was to order a new set of tags with better support. But then I started Googling things and found the documentation for Mifare Ultralight.

On page 41, the documentation describes the commands you need to send to write data. Here is how it looks in React Native:

writeData = async () => {
if (!this.state.text){
Alert.alert("Enter some text");
return;
}

OK, don’t get scared, it’s actually pretty simple. Let’s break it down.

let resp = await NfcManager.requestTechnology(tech, {
alertMessage: "Ready for magic"
});

These three lines tell the engine that you are trying to communicate with a Mifare Ultralight chip. iOS will automatically render the standard UI and the execution will wait until such a device gets in close proximity of the NFC reader.

At this point, the chip is ready to accept commands. On iOS, you can send commands with NfcManager.sendMifareCommandIOS, which accepts a list of bytes.

Based on the documentation, all write commands should start with 0xA2 followed by the address of the page you are writing. On my chip, all pages can contain four bytes and their addresses are between 0x02 and 0x2C.

0x02 and 0x03 are actually reserved, so the first page you want to write is 0x04.

We are going to write a text-type record, which should follow a certain pattern:

  1. The first byte is 0x03.
  2. The second byte should be the length of the full payload (it will be your text’s length + 7).
  3. The third byte is 0xD1.
  4. The fourth byte is 0x01.
  5. The fifth byte is the length of the record (in case of a text record, it will be the text’s length + 3).
  6. 0x54 -> the character “T”.
  7. 0x02
  8. 0x65 -> the character “e”.
  9. 0x6E-> the character “n”.
  10. Your text.
  11. 0xFE to close the record.

This part of the code takes care of the above:

let text = this.state.text;
let fullLength = text.length + 7;
let payloadLength = text.length + 3;

Reading Data

Reading data is actually a bit simpler. Here is the implemented function:

readData = async () => {
try {
let tech = Platform.OS === 'ios' ? NfcTech.MifareIOS : NfcTech.NfcA;
let resp = await NfcManager.requestTechnology(tech, {
alertMessage: "Ready for magic"
});

After requesting the technology, we can start sending commands. Page 39 of the documentation explains the FAST_READ command, which has a very simple interface:

  1. The first byte of the request is 0x3A.
  2. The second byte is the first page you want to read.
  3. The third byte is the last page you want to read.

In our implementation, we first read the third page, which contains the full payload’s length. Based on the payload’s length, we can calculate how many pages we need to request.

From this point, we will just ignore the text record’s header (i<5) and keep reading characters until the 0xFE terminator.


Conclusion

And that’s all. This is, of course, just a proof of concept. You can do a ton of stuff with NFC technology.

The library for iOS is in pretty early stages right now but the repository is very active, so I’m sure a much better API will be released soon.

Better Programming

Advice for programmers.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade