1# NFC Tag Read/Write Development 2 3## Introduction 4Near Field Communication (NFC) is a high-frequency radio technology that enables communication between devices over a distance less than 10 cm. NFC operates at 13.56 MHz. With NFC technologies, electronic devices can read and write NFC tags.<br> 5NFC tags support one or more communications technologies listed as follows: 6- NFC-A (also known as ISO 14443-3A) 7- NFC-B (also known as ISO 14443-3B) 8- NFC-F (also known as JIS 6319-4) 9- NFC-V (also known as ISO 15693) 10- ISO-DEP (also known as ISO 14443-4) 11- NDEF 12- MIFARE Classic 13- MIFARE Ultralight 14 15## When to Use 16An electronic device touches an NFC tag via the NFC antenna to read and write the NFC tag data. NFC tags can be read and written by a started application (foreground mode) on a device or without starting an application (background mode). 17- Reading or writing an NFC tag by a started application<br> 18An application started on a device reads or writes the NFC tag. That is, the user starts the application to read and write the NFC tag. The user starts the application, opens the application page, and taps the device on the NFC tag. In this case, the retrieved tag data can be distributed only to the foreground application. 19- Reading or writing an NFC tag without starting an application<br> 20The user taps the device on an NFC tag without starting any application. Then, the device selects an application based on the type of the NFC tag technology. If multiple applications are matched, an application selector will be displayed, listing all the available applications for the user to choose. After the user selects an application, the NFC tag read/write page of the application is automatically displayed. 21- Constraints<br> 22No matter whether the foreground mode or background mode is used, the NFC tag can be discovered by the device only when the device screen is unlocked and illuminated. 23 24## Available APIs 25 26For details about the JS APIs and sample code, see [Standard NFC Tags](../../reference/apis-connectivity-kit/js-apis-nfcTag.md). 27 28The following table describes the APIs for obtaining objects of the tags that use different NFC tag technologies. The objects obtained are used to read and write NFC tags. 29 30| API | Description | 31| ---------------------------------- | ------------------------------------------------------------------------------ | 32| getNfcA(tagInfo: TagInfo): NfcATag | Obtains an **NfcATag** object, which allows access to the tags that use the NFC-A technology. | 33| getNfcB(tagInfo: TagInfo): NfcBTag | Obtains an **NfcBTag** object, which allows access to the tags that use the NFC-B technology. | 34| getNfcF(tagInfo: TagInfo): NfcFTag | Obtains an **NfcFTag** object, which allows access to the tags that use the NFC-F technology. | 35| getNfcV(tagInfo: TagInfo): NfcVTag | Obtains an **NfcVTag** object, which allows access to the tags that use the NFC-V technology. | 36| getIsoDep(tagInfo: TagInfo): IsoDepTag | Obtains an **IsoDepTag** object, which allows access to the tags that use the ISO-DEP technology. | 37| getNdef(tagInfo: TagInfo): NdefTag | Obtains an **NdefTag** object, which allows access to the tags that use the NDEF technology. | 38| getMifareClassic(tagInfo: TagInfo): MifareClassicTag | Obtains a **MifareClassicTag** object, which allows access to the tags that use the MIFARE Classic technology. | 39| getMifareUltralight(tagInfo: TagInfo): MifareUltralightTag | Obtains a **MifareUltralightTag** object, which allows access to the tags that use the MIFARE Ultralight technology. | 40 41## Preparations 42 43### Reading/Writing NFC Tags in the Foreground or Background 44NFC tag application developers can choose to read/write NFC tags in the foreground or background based on service requirements. These two methods differ in their code implementations. 45- Reading or writing an NFC tag by a started application<br> 461. In the **module.json5** configuration file, you do not need to statically declare the technology type of the target NFC tag. Instead, dynamically register the technology type by using [tag.registerForegroundDispatch](../../reference/apis-connectivity-kit/js-apis-nfcTag.md#tagregisterforegrounddispatch10) or [tag.on](../../reference/apis-connectivity-kit/js-apis-nfcTag.md#tagon11). 472. During dynamic registration via **registerForegroundDispatch** or **tag.on**, specify the technology type of the target NFC tags in the input parameters. 483. If **registerForegroundDispatch** is used for registration: When the application runs in the foreground and enters the card swiping page, the NFC card emulation function is enabled, allowing card swiping to be performed simultaneously. If **tag.on** is used for registration: When the application runs in the foreground and enters the card swiping page, the NFC card emulation function is disabled, making simultaneous card swiping unavailable. 494. When the app page switches to the background, explicitly call [tag.unregisterForegroundDispatch](../../reference/apis-connectivity-kit/js-apis-nfcTag.md#tagunregisterforegrounddispatch10) or [tag.off](../../reference/apis-connectivity-kit/js-apis-nfcTag.md#tagoff11) to unregister technology type and exit the foreground dispatch mode. 50- Reading or writing an NFC tag without starting an application<br> 511. In the **module.json5** configuration file, statically declare the technology type of the target NFC tag. You must define at least one technology type based on service requirements. **tag-tech/** is the prefix, followed by the technology type description. 522. The technology type description is case-sensitive and must exactly match the actual technology type. 53 54> **NOTE** 55> - Starting from API version 9, application development supports the Stage model, which is recommended for long-term evolution. 56> - All the sample code in this document is based on the Stage model. 57 58## How to Develop 59 60### Accessing an NFC Tag by a Started Application 611. Declare the permission required for NFC tag operations and the action for filtering the application in the **module.json5** file. 622. Import related modules. 633. Check whether the device supports the NFC feature. 644. Register a listener for the NFC tag read event so that the tag can be preferentially dispatched to a foreground application. 655. Obtain an NFC tag object of the specific technology type. 666. Read and write the tag data. 677. Exit the foreground dispatch mode when the application exits the NFC tag page. 68 69```ts 70 "abilities": [ 71 { 72 "name": "EntryAbility", 73 "srcEntry": "./ets/entryability/EntryAbility.ts", 74 "description": "$string:EntryAbility_desc", 75 "icon": "$media:icon", 76 "label": "$string:EntryAbility_label", 77 "startWindowIcon": "$media:icon", 78 "startWindowBackground": "$color:start_window_background", 79 "exported": true, 80 "skills": [ 81 { 82 "entities": [ 83 "entity.system.home" 84 ], 85 "actions": [ 86 "ohos.want.action.home", 87 88 // The actions field must contain ohos.nfc.tag.action.TAG_FOUND. 89 "ohos.nfc.tag.action.TAG_FOUND" 90 ] 91 } 92 ] 93 } 94 ], 95 "requestPermissions": [ 96 { 97 // Add the NFC tag operation permission. 98 "name": "ohos.permission.NFC_TAG", 99 "reason": "$string:app_name", 100 } 101 ] 102``` 103 104```ts 105import { tag } from '@kit.ConnectivityKit'; 106import { BusinessError } from '@kit.BasicServicesKit'; 107import { hilog } from '@kit.PerformanceAnalysisKit'; 108import { AbilityConstant, UIAbility, Want, bundleManager } from '@kit.AbilityKit'; 109 110let nfcTagElementName: bundleManager.ElementName; 111let foregroundRegister: boolean; 112 113async function readerModeCb(error : BusinessError, tagInfo : tag.TagInfo) { 114 if (!error) { 115 // Obtain an NFC tag object of the specific technology type. 116 if (tagInfo == null || tagInfo == undefined) { 117 hilog.error(0x0000, 'testTag', 'readerModeCb tagInfo is invalid'); 118 return; 119 } 120 if (tagInfo.uid == null || tagInfo.uid == undefined) { 121 hilog.error(0x0000, 'testTag', 'readerModeCb uid is invalid'); 122 return; 123 } 124 if (tagInfo.technology == null || tagInfo.technology == undefined || tagInfo.technology.length == 0) { 125 hilog.error(0x0000, 'testTag', 'readerModeCb technology is invalid'); 126 return; 127 } 128 129 // The NFC tag may support multiple technology types. Select a specific technology type to read or write tag data. 130 // The following sample code is based on the IsoDep technology. 131 let isoDep : tag.IsoDepTag | null = null; 132 for (let i = 0; i < tagInfo.technology.length; i++) { 133 if (tagInfo.technology[i] == tag.ISO_DEP) { 134 try { 135 isoDep = tag.getIsoDep(tagInfo); 136 } catch (error) { 137 hilog.error(0x0000, 'testTag', 'readerModeCb getIsoDep error = %{public}s', JSON.stringify(error)); 138 return; 139 } 140 } 141 // You can also use other technology types as required. 142 } 143 if (isoDep == undefined) { 144 hilog.error(0x0000, 'testTag', 'readerModeCb getIsoDep is invalid'); 145 return; 146 } 147 148 // Connect to the NFC tag via IsoDep. 149 try { 150 isoDep.connect(); 151 } catch (error) { 152 hilog.error(0x0000, 'testTag', 'readerModeCb isoDep.connect() error = %{public}s', JSON.stringify(error)); 153 return; 154 } 155 if (!isoDep.isConnected()) { 156 hilog.error(0x0000, 'testTag', 'readerModeCb isoDep.isConnected() false.'); 157 return; 158 } 159 160 // Send a command to the connected NFC tag to obtain the response data. 161 let cmdData = [0x01, 0x02, 0x03, 0x04]; // Modify the command data as required. 162 try { 163 isoDep.transmit(cmdData).then((response : number[]) => { 164 hilog.info(0x0000, 'testTag', 'readerModeCb isoDep.transmit() response = %{public}s.', JSON.stringify(response)); 165 }).catch((err : BusinessError)=> { 166 hilog.error(0x0000, 'testTag', 'readerModeCb isoDep.transmit() err = %{public}s.', JSON.stringify(err)); 167 return; 168 }); 169 } catch (businessError) { 170 hilog.error(0x0000, 'testTag', 'readerModeCb isoDep.transmit() businessError = %{public}s.', JSON.stringify(businessError)); 171 return; 172 } 173 } else { 174 hilog.info(0x0000, 'testTag', 'readerModeCb readerModeCb error %{public}s', JSON.stringify(error)); 175 } 176} 177 178export default class EntryAbility extends UIAbility { 179 onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) { 180 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); 181 182 // Check whether the device supports the NFC feature. 183 if (!canIUse("SystemCapability.Communication.NFC.Core")) { 184 hilog.error(0x0000, 'testTag', 'nfc unavailable.'); 185 return; 186 } 187 188 // Initialize element names of the NFC tag based on the application information. 189 nfcTagElementName = { 190 bundleName: want.bundleName ?? '', 191 abilityName: want.abilityName ?? '', 192 moduleName: want.moduleName, 193 } 194 } 195 196 onForeground() { 197 // Switch the application to the foreground and call the foreground dispatch API to enable the foreground application to preferentially process the discovered NFC tag. 198 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); 199 if (nfcTagElementName != undefined) { 200 // Select an appropriate technology type based on service requirements. 201 let techList : number[] = [tag.NFC_A, tag.NFC_B, tag.NFC_F, tag.NFC_V]; 202 try { 203 tag.on('readerMode', nfcTagElementName, techList, readerModeCb); 204 foregroundRegister = true; 205 } catch (error) { 206 hilog.error(0x0000, 'testTag', 'on readerMode error = %{public}s', JSON.stringify(error)); 207 } 208 } 209 } 210 211 onBackground() { 212 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); 213 // When exiting the NFC tag page, call the tag.off API to exit the foreground dispatch mode. 214 if (foregroundRegister) { 215 foregroundRegister = false; 216 try { 217 tag.off('readerMode', nfcTagElementName); 218 } catch (error) { 219 hilog.error(0x0000, 'testTag', 'off readerMode error = %{public}s', JSON.stringify(error)); 220 } 221 } 222 } 223} 224``` 225 226### Accessing an NFC Tag Without Starting an Application 2271. In the **module.json5** configuration file, declare the NFC tag operation permission, the NFC tag action, and the technology type. 2282. Import related modules. 2293. Obtain an NFC tag object of the specific technology type. 2304. Read and write the tag data. 231 232```ts 233 "abilities": [ 234 { 235 "name": "EntryAbility", 236 "srcEntry": "./ets/entryability/EntryAbility.ts", 237 "description": "$string:EntryAbility_desc", 238 "icon": "$media:icon", 239 "label": "$string:EntryAbility_label", 240 "startWindowIcon": "$media:icon", 241 "startWindowBackground": "$color:start_window_background", 242 "exported": true, 243 "skills": [ 244 { 245 "entities": [ 246 "entity.system.home" 247 ], 248 "actions": [ 249 "ohos.want.action.home", 250 251 // The actions field must contain ohos.nfc.tag.action.TAG_FOUND. 252 "ohos.nfc.tag.action.TAG_FOUND" 253 ], 254 255 // You must define at least one technology type based on service requirements. **tag-tech/** is the prefix, followed by the technology type description. 256 "uris": [ 257 { 258 "type":"tag-tech/NfcA" 259 }, 260 { 261 "type":"tag-tech/IsoDep" 262 } 263 // Add other technology types if necessary. 264 // Example: NfcB/NfcF/NfcV/Ndef/MifareClassic/MifareUL/NdefFormatable 265 ] 266 } 267 ] 268 } 269 ], 270 "requestPermissions": [ 271 { 272 // Add the NFC tag operation permission. 273 "name": "ohos.permission.NFC_TAG", 274 "reason": "$string:app_name", 275 } 276 ] 277``` 278 279```ts 280import { tag } from '@kit.ConnectivityKit'; 281import { BusinessError } from '@kit.BasicServicesKit'; 282import { hilog } from '@kit.PerformanceAnalysisKit'; 283import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit'; 284 285export default class EntryAbility extends UIAbility { 286 onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) { 287 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); 288 289 // Obtain an NFC tag object of the specific technology type. 290 let tagInfo : tag.TagInfo; 291 try { 292 tagInfo = tag.getTagInfo(want); 293 } catch (error) { 294 hilog.error(0x0000, 'testTag', 'getTagInfo error = %{public}s', JSON.stringify(error)); 295 return; 296 } 297 298 if (tagInfo == null || tagInfo == undefined) { 299 hilog.error(0x0000, 'testTag', 'tagInfo is invalid'); 300 return; 301 } 302 if (tagInfo.uid == null || tagInfo.uid == undefined) { 303 hilog.error(0x0000, 'testTag', 'uid is invalid'); 304 return; 305 } 306 if (tagInfo.technology == null || tagInfo.technology == undefined || tagInfo.technology.length == 0) { 307 hilog.error(0x0000, 'testTag', 'technology is invalid'); 308 return; 309 } 310 311 // The NFC tag may support multiple technology types. Select a specific technology type to read or write tag data. 312 // The following sample code is based on the IsoDep technology. 313 let isoDep : tag.IsoDepTag | null = null; 314 for (let i = 0; i < tagInfo.technology.length; i++) { 315 if (tagInfo.technology[i] == tag.ISO_DEP) { 316 try { 317 isoDep = tag.getIsoDep(tagInfo); 318 } catch (error) { 319 hilog.error(0x0000, 'testTag', 'getIsoDep error = %{public}s', JSON.stringify(error)); 320 return; 321 } 322 } 323 // You can also use other technology types as required. 324 } 325 if (isoDep == undefined) { 326 hilog.error(0x0000, 'testTag', 'getIsoDep is invalid'); 327 return; 328 } 329 330 // Connect to the NFC tag via IsoDep. 331 try { 332 isoDep.connect(); 333 } catch (error) { 334 hilog.error(0x0000, 'testTag', 'isoDep.connect() error = %{public}s', JSON.stringify(error)); 335 return; 336 } 337 if (!isoDep.isConnected()) { 338 hilog.error(0x0000, 'testTag', 'isoDep.isConnected() false.'); 339 return; 340 } 341 342 // Send a command to the connected NFC tag to obtain the response data. 343 let cmdData = [0x01, 0x02, 0x03, 0x04]; // Modify the command data as required. 344 try { 345 isoDep.transmit(cmdData).then((response : number[]) => { 346 hilog.info(0x0000, 'testTag', 'isoDep.transmit() response = %{public}s.', JSON.stringify(response)); 347 }).catch((err : BusinessError)=> { 348 hilog.error(0x0000, 'testTag', 'isoDep.transmit() err = %{public}s.', JSON.stringify(err)); 349 return; 350 }); 351 } catch (businessError) { 352 hilog.error(0x0000, 'testTag', 'isoDep.transmit() businessError = %{public}s.', JSON.stringify(businessError)); 353 return; 354 } 355 } 356} 357``` 358