# NFC标签读写

#### 场景介绍

NFC标签读写是实用工具类应用的高频使用场景之一，如用户记录网址、文本或应用信息等，以便NFC标签再次贴近手机时自动读取存储的信息并执行相应操作。

本示例基于[标准NFC-Tag](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-nfctag)实现了NFC标签读取与写入。  

#### 效果预览

![](https://media:201786506722879816 "点击放大")  
![](https://media:201786506723550817)  
* 导入tag模块编辑器报错：在某些具体的设备型号上，能力可能超出工程默认设备定义的能力集范围，如需使用该部分能力，需额外配置自定义syscap，具体请参考[SysCap开发指导](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/syscap)。
* 本示例的读取"是否可写"和"可为只读"功能，以及写入功能仅支持包含NDEF技术类型的NFC卡。  

#### 实现思路

1. 通过给[tag.on()](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-nfctag#tagonreadermode11)传入不同的注册方法，实现读卡和写卡模式的切换。

   ```
   // NfcUtil.ets
   public nfcTagOn(callback: AsyncCallback<tag.TagInfo, void>) {
     if (this.nfcTagElementName !== undefined) {
       // 调用tag模块中前台优先的接口，使能前台应用程序优先处理所发现的NFC标签功能
       tag.on('readerMode', this.nfcTagElementName, TECH_LIST, callback);
       this.foregroundRegister = true;
     }
     // ...
   }

   // 读卡方法
   public async readerModeCb(error: BusinessError, tagInfo: tag.TagInfo) {}

   // 写卡方法
   public async writeModeCb(error: BusinessError, tagInfo: tag.TagInfo) {}
   ```

2. 读卡模式时，通过[tag.TnfType](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-nfctag#tnftype9)区分不同类型记录，采取不同的方法进行内容解析。

   ```
   // NdefTagModel.ets
   getTagRecords(ndefTag: tag.NdefTag) {
     let ndefMessage: tag.NdefMessage = ndefTag.getNdefMessage();
     let ndefRecords: tag.NdefRecord[] = ndefMessage.getNdefRecords();
     return ndefRecords;
   }

   // uri解析，通过标识符，匹配协议头
   static getUriContent(payload: number[]) {
     let res: string = '';

     // 解析前缀协议
     let prefix = UriPrefixUtil.URI_PREFIX_MAP.get(payload[0]); // 通过标识符，匹配协议头
     res = prefix;

     // 解析内容
     let content = payload.slice(1, payload.length + 1);
     res = res + buffer.from(content).toString('utf-8'); // 解析uri主体部分
     return res;
   }

   // 解析文本记录
   static getTextContent(payload: number[]) {}

   // 解析External记录
   static getExternalContent(payload: number[]) {}
   ```

3. 写卡模式时，通过传入不同的getRecord方法，将输入的内容根据类型，构建不同的NDEF标签的Record。

   ```
   // WriteCardPage.ets
   Button($r('app.string.write_input_button_add_record'), { stateEffect: false })  // 添加记录
     .onClick(() => {
       if (getRecord !== undefined) {
         let record = getRecord(this.inputContent);
         if (record) {
           this.records.push(record);
           this.recordsInfo.push(NdefTagModel.getRecordContent(record));
           // ...
           this.showSheetNum = -1;
         }
       }
     })

   // NdefTagModel.ets
   // 创建uri类型的record
   static getWriteUriRecord(uri: string): tag.NdefRecord | undefined {}

   // 创建文本类型的record
   static getWriteTextRecord(text: string) {}

   // 创建external的record
   static getWriteExternalRecord(bundleName: string) {}

   // 写入记录
   async writeNdefToTag(ndefRecords: tag.NdefRecord[]): Promise<boolean> {
     ndefMessage = tag.ndef.createNdefMessage(records);
     // ...
     if (this.ndefTag.isConnected() && ndefMessage) {
       await this.ndefTag.writeNdef(ndefMessage);
       return true;
     }
     // ...
   }
   ```

#### 约束与限制

* 本示例支持API Version 20 Release及以上版本。
* 本示例支持HarmonyOS 6.0.0 Release SDK及以上版本。
* 本示例需要使用DevEco Studio 6.0.0 Release及以上版本进行编译运行。  

#### 权限说明

* 需要NFC标签读取权限：[ohos.permission.NFC_TAG](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/permissions-for-all#ohospermissionnfc_tag)。
* 需要声明NFC标签特定的action：[ohos.nfc.tag.action.TAG_FOUND](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/module-configuration-file#skills标签)。  

#### 工程目录

```
├──entry/src/main/ets                 // 代码区
│  ├──constants
│  │  ├──CommonConstant.ets           // 通用常量
│  │  └──Constant.ets                 // 常量
│  ├──entryability
│  │  └──EntryAbility.ets  
│  ├──model
│  │  ├──NdefTagModel.ets             // NdefTag模型
│  │  └──NfcATagModel.ets             // NfcATag模型
│  ├──pages
│  │  ├──HomePage.ets                 // 主页
│  │  ├──ReadCardPage.ets             // 读卡界面
│  │  └──WriteCardPage.ets            // 写卡界面
│  └──utils
│     ├──NfcUtil.ets                  // Nfc工具类
│     └──UriPrefixUtil.ets            // uri前缀解析类
└──entry/src/main/resources           // 应用资源目录
```

#### 参考文档

[@ohos.nfc.tag（标准NFC-Tag）](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-nfctag)

[nfctech（标准NFC-Tag Nfc 技术）](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-nfctech)

[NFC标签读写开发指南](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/nfc-tag-access-guide)  

#### 代码下载

[NFC标签读写示例代码](https://media:201786506723615818)  
