Flutter实现NFC读写功能详解
Flutter实现NFC读写功能详解
了解NFC
近距离无线通信 (NFC) 是一组近距离无线技术,通常只有在距离不超过 4 厘米时才能启动连接。大部分NFC标签读写的都是NDEF数据。
根据上图举例NfcA: NFC-A是一种NFC协议,根据ISO 14443-3A标准定义,ISO 14443-3A定义了NFC-A协议的物理特征、数据传输方式和命令集等。NFC-A协议支持操作14A型NFC标签和卡片。
属性: NFC标签和卡片的属性包括标签容量、读写权限、标签类型、支持的数据格式等信息。通过NFC-A协议,你可以访问和获取这些属性信息。
I/O操作: NFC-A协议支持通过读取和写入操作来对NFC标签和卡片进行数据交互。你可以发送特定的命令和数据给NFC标签,以读取标签上存储的数据或向标签写入数据。
也就是说NfcA、NfcB、NfcF、IsoDep都是通过特殊指令与NFC标签互动进行NDEF数据的读写,具体特殊指令就需要参考具体NFC标签的功能和支持的命令集,每个厂商的NFC指令集可能各不同
Ndef则是可以通过方法可以直接获取到NdefMessage对象然后获取NdefRecord。这些记录可能包含URI、文本、电话号码等各种类型的数据。
身份证、地铁卡、银行卡、大部分的工卡都不是Ndef格式,因此无法直接使用Ndef进行读写,需要使用特定的协议和指令集。
提示
因为本人不知道当前使用的NFC指令集所以采用的是Ndef进行读写的,如果你知道你们NFC标签或厂商提供的指令集也可使用互动的方式进行读写。当然看你们的标签支持什么技术,因为不同的标签支持的技术也不同。
一、引入nfc_manager
获取并引入nfc_manager
import 'dart:typed_data';
import 'package:nfc_manager/nfc_manager.dart';
二、NFC读写
1.nfc_read读取数据
void _tagRead() {
// 开始扫描标签
NfcManager.instance.startSession(onDiscovered: (NfcTag tag) async {
print(tag.data); // 当能打印到tag.data说明已经扫描到标签了
Ndef? ndef = Ndef.from(tag);
// 如果标签支持Ndef技术
if(ndef != null){
NdefMessage? message = ndef?.cachedMessage;
// 打印读取到的message,message包含一条或多条record
print(message);
// 循环解析并打印记录中包含的信息
message?.records.forEach((record) {
// 转换ASCII获取数据,record.payload中就是write写入的数据
String uriPayload = String.fromCharCodes(record.payload);
print('Record payload: $uriPayload');
print('Record typeNameFormat: ${record.typeNameFormat}');
print('Record Type: ${String.fromCharCodes(record.type)}');
print('Record identifier: ${record.identifier}');
});
}
// 停止扫描标签
NfcManager.instance.stopSession();
});
}
2.写入数据
void _ndefWrite() {
// 开始扫描标签
NfcManager.instance.startSession(onDiscovered: (NfcTag tag) async {
Ndef? ndef = Ndef.from(tag);
// 如果该标签支持ndef,并且该标签支持写入,注意有的标签是只读的
if (ndef == null || !ndef.isWritable) {
print('Tag is not ndef writable');
NfcManager.instance.stopSession(errorMessage: result.value);
return;
}
// 每个message中可以写入多个record,写入之后会覆盖之前的record
// 注意nfc_manager读写的源数据都是ASCII码,所以如果写入中文,读取后中文可能会变成空
String payload = '{"type","user","id": "66","no": "A1001"}';
NdefMessage message = NdefMessage([
// 把要写入的数据转换为ASCII码数据
NdefRecord.createMime('application/json', Uint8List.fromList(payload.codeUnits)),
// NdefRecord.createText('Hello World!'),
// NdefRecord.createUri(Uri.parse('https://flutter.dev')),
// NdefRecord.createMime('text/plain', Uint8List.fromList('Hello'.codeUnits)),
// NdefRecord.createExternal('com.example', 'mytype', Uint8List.fromList('mydata'.codeUnits)),
]);
try {
await ndef.write(message);
print('Success to "Ndef Write"');
// 此时已经写入成功了,并停止扫描标签
NfcManager.instance.stopSession();
} catch (e) {
print(e);
// 写入失败了.....
NfcManager.instance.stopSession(errorMessage: result.value.toString());
return;
}
});
}
3.总结
再次声明:我使用的是ndef进行读写的,如果你知道你们所使用的nfc指令集或者不支持ndef可以使用NfcA、NfcB、IsoDep...进行互动式读写请参阅nfc_manager文档https://pub.dev/packages/nfc_manager
NfcA、NfcB、IsoDep…这些互动式的读写,nfc_manager内置了transceive方法。
以NfcA举例
// 需要引入 import 'package:nfc_manager/platform_tags.dart';
// 开始扫描标签
NfcManager.instance.startSession(onDiscovered: (NfcTag tag) async {
print(tag.data); // 当能打印到tag.data说明已经扫描到标签了
NfcA? nfca= NfcA.from(tag);
// 如果标签支持NfcA技术
if(nfca!= null){
// 此时code也要求是Uint8List数据,同上ndef方式
// 但是具体指令就只能参考具体的NFC指令集了,每个厂商的NFC标签所支持的指令可能也不同
var data = nfca.transceive(data: code);
print(data);
}
// 停止扫描标签
NfcManager.instance.stopSession();
});