How to Read NFC Tags and Write NDEF Data With NfcManager

Project Source Code

Get the project source code below, and follow along with the lesson material.

Download Project Source Code

To set up the project on your local machine, please follow the directions provided in the README.md file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.

This lesson preview is part of the The newline Guide to NFCs with React Native course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.

This video is available to students only
Unlock This Course

Get unlimited access to The newline Guide to NFCs with React Native, plus 70+ \newline books, guides and courses with the \newline Pro subscription.

Thumbnail for the \newline course The newline Guide to NFCs with React Native

Hello! In this lesson, we will focus on how to deal with n-death, covering, reading and parsing the n-death from NFC tags, building and writing n-death into NFC tags. Before handling n-death, let's first add some codes to check the NFC feature availability. First, open app.js from the previous Tech Countergame app. Paste the import NFC manager line back to our home screen. Then, migrate the use effect hook. So now we have the has NFC state to check if the NFC feature is available. And the enable state to check if the NFC is enabled. After that, we create a render NFC buttons function. And paste the original UI code into it. Then we go back to Tech Countergames app.js and copy the conditional rendering codes into our render NFC buttons function. Oh, it looks like we forgot to import touchable opacity. Save and refresh. We can see our simulator says, "Your device doesn't support NFC", which is expected. The next step is, of course, to scan our NFC tags. Remember, in our previous Tech Countergame app, we use register tag event and set event listener to scan our tags. Here, we will use a different approach. Let's call NFC manager.request_technology. As you can see from the type hint, the first parameter is called tag, which is the technology type we'd like to request. And n-depth itself is also an NFC technology type. In order to use the correct tag type, we should import NFC tag from our library . Once this API is resolved, it means the NFC tag with our expected technology has been discovered. So at this point, we can call NFC manager.get tag to retrieve the NFC tag object. If the NFC tag contains valid n-depth data, there will be a n-depth message property inside the tag object, as we saw before. After scanning, we will have to call NFC manager.cancel_technology request to clean up. Then what we'd like to do is to pass the tag object as parameters into the tag detail screen. And we can accomplish this by using the second parameter of the navigation.nav igate function. We also wrap our code in a tri-cache block to prevent unexpected errors. In this case, no critical exceptions will be thrown. So we can simply ignore them. We also move the cancel_technology API into the finally block, because it is the clean up operation and should always be called. Then call the read_end-depth function from our tag button. Let's quickly see our read_end-depth function again. This request_technology pattern will be our primary method for NFC tag scanning for the rest of the course. Here, this API is an async function and only resolves when the tag is discovered. Before testing, we still need to update our tag detail screen so that it can display the tag object we pass. First, destructor the route from props. And the data we are looking for will be in the route.parameters. For now, we simply wrap the stringified tag object inside a text element. This works pretty well. It's time to actually parse the end-depth. Import end-depth from React Native NFC Manager and declare a variable called ui . We first check if the tag object contains only valid end-depth record. Call from our previous lesson, end-depth message is a container which consists of multiple end-depth records. So the end-depth message property here will be an array and each element of this array is an end-depth record. To simplify things, we only handle the first end-depth record here. By the way, it's true for most cases. Then since we'd like to parse the ui, the tnf property should be well-known and the type property should be RTD ui. The tnf comparison is straightforward. But for the type property, we will have to perform array comparison since it's actually an array of bytes. Now we have confirmed this record is a RTD ui. We can decode the payload property via end-depth.uri.deco payload. We also need to update our render logic to display the parsed ui. Let's give it a try. Besides showing the parsed ui, we can use linking from RAN native to ask our operating system to perform corresponding actions according to our ui. We first wrap the text element inside a touchable opacity. For the unpressed handler, we simply call linking.open URL. Let's test it again. It's worked pretty well. Let's create a new screen called end-depth write screen. I will paste the ui code directly to save you some time. Here we have two states. One is selected link type and another is value. We iterate through web, tell, SMS and email. Set unpressed handler for each of them so that it can update the corresponding state into selected link type. We also have a text input to update the value state. Next, let's quickly hook up this new screen into our app navigator. And trigger the navigation from whole screen into end-depth write screen when the user clicks the link button. Let's give you a try. Now it's time to transform the user input data into a valid end-depth message. Again, import end-depth from native NFC manager. Add a skin to the correct value according to selected link type. Then create our ui record via end-depth.ui record. This function receives a ui stream and returns an end-depth record object. Next, we need to generate the end-depth message from the end-depth record. This can be accomplished by calling end-depth.encode message. The input is an array of end-depth record objects. And the output is an array of bytes, which represents the entire end-depth message. Let's observe the data now. Let's decode the first byte to see if it matches the end-depth record structure we just learned from the previous lesson. 2009 means D1 in Hacks and 1101, 0001 in binary. Once it is in the binary form, we can easily find the meaning for each bit by mapping it to the table here. So mb and me means it's the first and only end-depth record in current end- depth message. Then cf or chunk flag, we don't care about it. For the sr1 means it is a short record and tnf1 means it is a well-known record . Now I hope you get the feeling of what happened under the hood. The last part is to actually write end-depth into our tag. So import nfc-manager and nfc-tag from native NFC-manager. And we will use the same request-technology API and select end-depth as the expected NFC-technology as before. Then we use nfc-manager.end-depth-handler.write-end-depth-message to actually write end-depth into tags. This is the first time we have used an nfc-technology-handler. In our nfc-library, the technology-specific operations are grouped into their own handler. So the write-end-depth-message belongs to n-depth-handler. You might wonder why we don't need to use n-depth-handler when we read the nfc- tags. That is because the operating system will discover n-depth-message automatically, regardless of their underlying nfc-technology. So we can later retrieve it using get-tag API. Finally we call cancel-technology-request and wrap the code in a try-cache block like before. Let's test it. It's worked pretty well. Now we have both the read and write functionalities. Let's check if other URL type works. First write. Then read it back. Write. Read it back again. Write. Read it back again. Now it's time for our Android app. The only thing we need to do is integrate our previous Android prompt component into tap and go app. First make a src-components-directory and create a file name and write prompt inside it. Then copy our previous code into this file. Back to our home screen. Import the Android prompt component. Create a ref called Android prompt ref via react.use ref. Enter the component and pass ref and un-cancel-press into it. Inside un-cancel-press we simply call nfc-manager.cancel-technology-request. Finally in our read_m-death function we should set Android prompt to be visible in the beginning and set it back to invisible in the end. And of course we should only show this prompt on the Android platform. Okay, home screen is good to go. I will leave the end-death write screen to you as an exercise. (swish) (swish) [BLANK_AUDIO]