Flutter NFC主机卡模拟插件flutter_nfc_hce的使用
Flutter NFC主机卡模拟插件flutter_nfc_hce的使用
1. 介绍
flutter_nfc_hce
插件项目是在探索跨平台之间使用NFC交换数据的方法过程中发起的。该插件旨在利用Flutter的功能,基于Qifan Yang的NFCAndroid
项目中的com.qifan.nfcbank.cardEmulation.KHostApduService
实现(参考:NFCAndroid)。关于Android 13版本中与NFC HCE操作相关的问题,参考了MichaelsPlayground/NfcHceNdefEmulator进行了修改。
// KHostApduService.kt
private val READ_CAPABILITY_CONTAINER_RESPONSE = byteArrayOf(
0x00.toByte(), 0x0F.toByte(), // CCLEN 长度为15字节
0x20.toByte(), // 映射版本2.0
0x00.toByte(), 0x3B.toByte(), // MLe 最大值60
0x00.toByte(), 0x34.toByte(), // MLc 最大值52
0x04.toByte(), // NDEF文件控制TLV的T字段
0x06.toByte(), // NDEF文件控制TLV的L字段
0xE1.toByte(), 0x04.toByte(), // NDEF文件标识符
0x00.toByte(), 0xFF.toByte(), // 最大NDEF文件大小为65534字节
0x00.toByte(), // 无需任何安全措施即可读取
0xFF.toByte(), // 无需任何安全措施即可写入
0x90.toByte(), 0x00.toByte(), // A_OKAY
)
NFC HCE操作支持从Android 11到13版本,在当前初始项目中,支持的AID固定为D2760000850101
。对于NFC HCE读取器,可以参考使用flutter_manager
创建的示例(flutter_nfc_hce_reader)。
2. 截图
主界面 | Android NFC HCE |
---|---|
3. 设置
Android设置
-
在
AndroidManifest.xml
中添加权限:<uses-permission android:name="android.permission.NFC" /> <uses-feature android:name="android.hardware.nfc" android:required="true" /> <uses-feature android:name="android.hardware.nfc.hce" android:required="true" /> <uses-permission android:name="android.permission.VIBRATE" />
-
在
AndroidManifest.xml
中注册服务:<service android:name="com.novice.flutter_nfc_hce.KHostApduService" android:exported="true" android:enabled="true" android:permission="android.permission.BIND_NFC_SERVICE"> <intent-filter> <action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> <meta-data android:name="android.nfc.cardemulation.host_apdu_service" android:resource="@xml/apduservice"/> </service>
-
在
res/xml
目录下添加apduservice.xml
:<?xml version="1.0" encoding="utf-8"?> <host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android" android:description="@string/servicedesc" android:requireDeviceScreenOn="false" android:requireDeviceUnlock="false"> <aid-group android:description="@string/aiddescription" android:category="other" > <aid-filter android:name="D2760000850101"/> </aid-group> </host-apdu-service>
-
在
res/values
目录下添加strings.xml
:<resources> <string name="servicedesc">服务描述</string> <string name="aiddescription">AID描述</string> </resources>
4. 使用示例
以下是一个完整的示例代码,展示了如何使用flutter_nfc_hce
插件:
import 'package:flutter/material.dart';
import 'package:flutter_nfc_hce/flutter_nfc_hce.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
[@override](/user/override)
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final _flutterNfcHcePlugin = FlutterNfcHce();
bool _showNFCScanDialog = false;
var platformVersion;
bool? isNfcHceSupported;
bool? isSecureNfcEnabled;
bool? isNfcEnabled;
void _getInfo() async {
platformVersion = await _flutterNfcHcePlugin.getPlatformVersion();
isNfcHceSupported = await _flutterNfcHcePlugin.isNfcHceSupported();
isSecureNfcEnabled = await _flutterNfcHcePlugin.isSecureNfcEnabled();
isNfcEnabled = await _flutterNfcHcePlugin.isNfcEnabled();
}
void _onScanButtonPressed() async {
_getInfo();
var content = 'flutter_nfc_hce';
var result = await _flutterNfcHcePlugin.startNfcHce(content, persistMessage: true);
print('---------------------------------->$result');
setState(() {
_showNFCScanDialog = true;
});
}
void _onCloseButtonPressed() async {
await _flutterNfcHcePlugin.stopNfcHce();
setState(() {
_showNFCScanDialog = false;
});
}
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin Nfc Hce example app'),
),
body: Container(
child: Stack(
children: [
// 背景Widget
Container(
color: Colors.transparent,
child: Center(
child: Column(
children: [
Text('platformVersion: ${platformVersion ?? ""}'),
SizedBox(height: 5),
Text('isSupportNfcHceFeature: ${isNfcHceSupported ?? ""}'),
SizedBox(height: 5),
Text('isSupportSecureNfcSupported: ${isSecureNfcEnabled ?? ""}'),
SizedBox(height: 5),
Text('isNfcEnagle: ${isNfcEnabled ?? ""}'),
],
),
),
),
// NFC扫描对话框
if (_showNFCScanDialog)
GestureDetector(
onTap: _onCloseButtonPressed,
child: Container(
color: Colors.black54,
alignment: Alignment.center,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset('assets/nfc_tag.png', width: 100, height: 100),
SizedBox(height: 16),
Text(
'Start Nfc Hce',
style: TextStyle(color: Colors.white, fontSize: 18),
),
],
),
),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _onScanButtonPressed,
child: Icon(Icons.nfc),
),
),
);
}
}
更多关于Flutter NFC主机卡模拟插件flutter_nfc_hce的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter NFC主机卡模拟插件flutter_nfc_hce的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter应用中使用flutter_nfc_hce
插件来实现NFC主机卡模拟的示例代码。这个插件允许你的设备在支持NFC的Android设备上模拟一个NFC卡。
首先,你需要在你的pubspec.yaml
文件中添加flutter_nfc_hce
依赖:
dependencies:
flutter:
sdk: flutter
flutter_nfc_hce: ^x.y.z # 请替换为最新版本号
然后运行flutter pub get
来安装依赖。
接下来,你需要在AndroidManifest.xml文件中添加NFC相关的权限和特性声明:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.yourapp">
<uses-permission android:name="android.permission.NFC" />
<application
...>
<service
android:name=".MyNfcHceService"
android:exported="true"
android:permission="android.permission.BIND_NFC_SERVICE">
<intent-filter>
<action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE" />
</intent-filter>
<meta-data
android:name="android.nfc.cardemulation.host_apdu_service"
android:resource="@xml/apdu_service" />
</service>
</application>
</manifest>
你还需要在res/xml
目录下创建一个名为apdu_service.xml
的文件,用于定义你的APDU服务:
<?xml version="1.0" encoding="utf-8"?>
<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
android:apduServiceDescriptor="@string/apdu_service_descriptor"
android:requireDeviceUnlock="false">
<aid-group
android:category="payment"
android:description="@string/aid_group_description"
android:priority="0">
<aid android:name="F28012040007A0000000871002" />
</aid-group>
</host-apdu-service>
然后,在res/values/strings.xml
中添加相应的字符串资源:
<resources>
<string name="apdu_service_descriptor">"com.example.yourapp.MyNfcHceService"</string>
<string name="aid_group_description">"My NFC AID Group"</string>
</resources>
接下来,创建一个服务类MyNfcHceService
来处理APDU命令:
import 'dart:typed_data';
import 'package:flutter/services.dart';
import 'package:flutter_nfc_hce/flutter_nfc_hce.dart';
class MyNfcHceService extends HostApduService {
@override
Future<Uint8List> processCommandApdu(Uint8List commandApdu) async {
// 这里处理接收到的APDU命令
// 例如,简单地回显接收到的命令
return commandApdu;
}
@override
Future<Uint8List> processChannelSelect(int aidLength, Uint8List aid) async {
// 处理SELECT命令
return Uint8List.fromList([0x90, 0x00]); // 状态字:成功
}
@override
Future<void> onDeactivated() async {
// 当卡被去激活时调用
}
}
注意:由于Dart和Flutter的限制,实际上你需要在原生Android代码(Kotlin或Java)中实现MyNfcHceService
类。但上面的代码展示了在Dart中你期望实现的功能。
在Android原生代码中(例如MyNfcHceService.kt
),你可能需要这样实现:
import android.nfc.cardemulation.HostApduService
import android.nfc.tech.IsoDep
import androidx.annotation.NonNull
import java.nio.ByteBuffer
import java.nio.ByteOrder
class MyNfcHceService : HostApduService() {
override fun onProcessCommandApdu(
@NonNull commandApdu: ByteArray?,
@NonNull extras: Bundle?
): ByteArray {
// 处理APDU命令
return commandApdu ?: byteArrayOf(0x90.toByte(), 0x00.toByte())
}
override fun onSelectApdu(aid: ByteArray?): ByteArray {
// 处理SELECT命令
return byteArrayOf(0x90.toByte(), 0x00.toByte())
}
override fun onDeactivated(reason: Int) {
// 当卡被去激活时调用
}
}
最后,在你的Flutter应用中启动和配置NFC主机卡模拟(注意:这部分操作通常也需要原生代码支持,因为Flutter本身对底层NFC操作的支持有限):
import 'package:flutter/material.dart';
import 'package:flutter_nfc_hce/flutter_nfc_hce.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter NFC HCE Demo'),
),
body: Center(
child: Text('NFC HCE Service is running in the background.'),
),
),
);
}
}
请注意,由于Flutter对NFC的直接操作有限,大部分NFC HCE相关的配置和处理需要在原生Android代码中进行。上面的示例展示了如何在Flutter中集成和使用flutter_nfc_hce
插件,但实际的NFC HCE服务实现需要在原生Android代码中完成。
希望这能帮助你开始使用flutter_nfc_hce
插件进行NFC主机卡模拟的开发!