Flutter泰国身份证读取插件thai_idcard_reader_flutter的使用
Flutter泰国身份证读取插件thai_idcard_reader_flutter的使用
简介
thai_idcard_reader_flutter
是一个用于与ACS ACR39U智能卡读卡器通信以即时读取泰国身份证的插件。
支持
- Android 5.0 或更新版本
- iOS 不可用
测试设备
- ACR39U-NF PocketMate II 智能卡读卡器(USB Type-C)
- 或任何由ACS制造的产品,如果它们可以正常工作
开始使用
以下是完整的示例代码,展示如何在Flutter应用中使用 thai_idcard_reader_flutter
插件来读取泰国身份证信息。
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:thai_idcard_reader_flutter/thai_idcard_reader_flutter.dart';
import 'package:intl/date_symbol_data_local.dart';
import 'package:intl/intl.dart';
void main() {
Intl.defaultLocale = 'th_TH';
initializeDateFormatting('th_TH', null);
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
ThaiIDCard? _data;
var _error;
UsbDevice? _device;
var _card;
StreamSubscription? subscription;
final List _idCardType = [
ThaiIDType.cid,
ThaiIDType.photo,
ThaiIDType.nameTH,
ThaiIDType.nameEN,
ThaiIDType.gender,
ThaiIDType.birthdate,
ThaiIDType.address,
ThaiIDType.issueDate,
ThaiIDType.expireDate,
];
List<String> selectedTypes = [];
@override
void initState() {
super.initState();
// 监听设备连接事件
ThaiIdcardReaderFlutter.deviceHandlerStream.listen(_onUSB);
}
// 处理设备连接事件
void _onUSB(usbEvent) {
try {
if (usbEvent.hasPermission) {
// 如果设备已连接并获得权限,监听卡片插入事件
subscription = ThaiIdcardReaderFlutter.cardHandlerStream.listen(_onData);
} else {
// 如果设备断开连接,取消监听卡片插入事件
if (subscription == null) {
subscription?.cancel();
subscription = null;
}
_clear();
}
setState(() {
_device = usbEvent;
});
} catch (e) {
setState(() {
_error = "_onUSB " + e.toString();
});
}
}
// 处理卡片插入事件
void _onData(readerEvent) {
try {
setState(() {
_card = readerEvent;
});
if (readerEvent.isReady) {
// 读取卡片数据
readCard(only: selectedTypes);
} else {
_clear();
}
} catch (e) {
setState(() {
_error = "_onData " + e.toString();
});
}
}
// 读取卡片数据
readCard({List<String> only = const []}) async {
try {
var response = await ThaiIdcardReaderFlutter.read(only: only);
setState(() {
_data = response;
});
} catch (e) {
setState(() {
_error = 'ERR readCard $e';
});
}
}
// 格式化日期
formattedDate(dt) {
try {
DateTime dateTime = DateTime.parse(dt);
String formattedDate = DateFormat.yMMMMd('th_TH').format(dateTime);
return formattedDate;
} catch (e) {
return dt.split('').toString() + e.toString();
}
}
// 清除数据
_clear() {
setState(() {
_data = null;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Thai ID Card Reader'),
),
body: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (_device != null)
UsbDeviceCard(
device: _device,
),
if (_card != null) Text(_card.toString()),
if (_device == null || !_device!.isAttached) ...[
const EmptyHeader(
text: '请插入读卡器',
),
],
if (_error != null) Text(_error.toString()),
if (_data == null && (_device != null && _device!.hasPermission)) ...[
const EmptyHeader(
icon: Icons.credit_card,
text: '请插入身份证',
),
SizedBox(
height: 200,
child: Wrap(children: [
Row(
mainAxisSize: MainAxisSize.min,
children: [
Checkbox(
value: selectedTypes.isEmpty,
onChanged: (val) {
setState(() {
if (selectedTypes.isNotEmpty) {
selectedTypes = [];
}
});
}),
const Text('读取全部'),
],
),
for (var ea in _idCardType)
Row(
mainAxisSize: MainAxisSize.min,
children: [
Checkbox(
value: selectedTypes.contains(ea),
onChanged: (val) {
print(ea);
setState(() {
if (selectedTypes.contains(ea)) {
selectedTypes.remove(ea);
} else {
selectedTypes.add(ea);
}
});
}),
Text('$ea'),
],
),
]),
),
],
if (_data != null) ...[
const Padding(padding: EdgeInsets.all(8.0)),
if (_data!.photo.isNotEmpty)
Center(
child: Image.memory(
Uint8List.fromList(_data!.photo),
),
),
if (_data!.cid != null) DisplayInfo(title: '身份证号码', value: _data!.cid!),
if (_data!.firstnameTH != null)
DisplayInfo(
title: '姓名(泰语)',
value: '${_data!.titleTH} ${_data!.firstnameTH} ${_data?.lastnameTH!}'),
if (_data!.firstnameEN != null)
DisplayInfo(
title: '姓名(英语)',
value: '${_data!.titleEN} ${_data!.firstnameEN} ${_data!.lastnameEN}'),
if (_data!.gender != null)
DisplayInfo(title: '性别', value: '(${_data!.gender}) ${_data!.gender == 1 ? '男' : '女'}'),
if (_data!.birthdate != null)
DisplayInfo(
title: '出生日期',
value: '${_data!.birthdate.toString()}\n${formattedDate(_data!.birthdate)}'),
if (_data!.address != null) DisplayInfo(title: '地址', value: _data!.address!),
if (_data!.issueDate != null)
DisplayInfo(
title: '发证日期', value: '${_data!.issueDate.toString()}\n${formattedDate(_data!.issueDate)}'),
if (_data!.expireDate != null)
DisplayInfo(
title: '有效期至',
value: '${_data!.expireDate.toString()}\n${formattedDate(_data!.expireDate)}'),
],
],
),
),
),
);
}
}
// 显示空状态的组件
class EmptyHeader extends StatelessWidget {
final IconData? icon;
final String? text;
const EmptyHeader({
this.icon,
this.text,
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Card(
child: SizedBox(
height: 300,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
icon ?? Icons.usb,
size: 60,
),
Center(
child: Text(
text ?? 'Empty',
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 32,
fontWeight: FontWeight.bold,
),
)),
],
)));
}
}
// 显示USB设备信息的组件
class UsbDeviceCard extends StatelessWidget {
final dynamic device;
const UsbDeviceCard({
Key? key,
this.device,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Opacity(
opacity: device.isAttached ? 1.0 : 0.5,
child: Card(
child: ListTile(
leading: const Icon(
Icons.usb,
size: 32,
),
title: Text('${device!.manufacturerName} ${device!.productName}'),
subtitle: Text(device!.identifier ?? ''),
trailing: Container(
padding: const EdgeInsets.all(8),
color: device!.hasPermission ? Colors.green : Colors.grey,
child: Text(device!.hasPermission ? 'Listening' : (device!.isAttached ? 'Connected' : 'Disconnected'),
style: const TextStyle(
fontWeight: FontWeight.bold,
)),
),
),
),
);
}
}
// 显示信息的组件
class DisplayInfo extends StatelessWidget {
const DisplayInfo({
Key? key,
required this.title,
required this.value,
}) : super(key: key);
final String title;
final String value;
@override
Widget build(BuildContext context) {
TextStyle sTitle = const TextStyle(fontSize: 24, fontWeight: FontWeight.bold);
TextStyle sVal = const TextStyle(fontSize: 28);
// 复制文本到剪贴板
_copyFn(value) {
Clipboard.setData(ClipboardData(text: value)).then((_) {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("已复制")));
});
}
return Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Row(
children: [
Text(
'$title : ',
style: sTitle,
),
],
),
Stack(
alignment: Alignment.centerRight,
children: [
Row(
children: [
Flexible(
child: Text(
value,
style: sVal,
),
),
],
),
GestureDetector(
onTap: () => _copyFn(value),
child: const Icon(Icons.copy),
)
],
),
const Divider(
color: Colors.black,
),
],
),
);
}
}
可选参数
你可以通过传递不同的参数来读取特定的数据:
// 读取所有数据
await ThaiIdcardReaderFlutter.read();
// 仅读取特定数据
await ThaiIdcardReaderFlutter.read(only: [
ThaiIDType.cid,
ThaiIDType.photo,
ThaiIDType.nameTH,
ThaiIDType.nameEN,
ThaiIDType.gender,
ThaiIDType.birthdate,
ThaiIDType.address,
ThaiIDType.issueDate,
ThaiIDType.expireDate,
]);
更多关于Flutter泰国身份证读取插件thai_idcard_reader_flutter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter泰国身份证读取插件thai_idcard_reader_flutter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter项目中使用thai_idcard_reader_flutter
插件来读取泰国身份证信息的示例代码。这个插件主要用于扫描和解析泰国身份证信息。
首先,确保你已经在pubspec.yaml
文件中添加了thai_idcard_reader_flutter
依赖:
dependencies:
flutter:
sdk: flutter
thai_idcard_reader_flutter: ^最新版本号 # 请替换为实际的最新版本号
然后,运行flutter pub get
来获取依赖。
接下来,在你的Flutter项目中,你可以使用以下代码来集成并使用该插件:
import 'package:flutter/material.dart';
import 'package:thai_idcard_reader_flutter/thai_idcard_reader_flutter.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Thai ID Card Reader Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: IDCardReaderScreen(),
);
}
}
class IDCardReaderScreen extends StatefulWidget {
@override
_IDCardReaderScreenState createState() => _IDCardReaderScreenState();
}
class _IDCardReaderScreenState extends State<IDCardReaderScreen> {
ThaiIDCardData? idCardData;
Future<void> _scanIDCard() async {
try {
// 调用插件方法来扫描身份证
idCardData = await ThaiIDCardReaderFlutter.scanIDCard();
// 更新UI
setState(() {});
} catch (e) {
// 处理错误
print('Error scanning ID card: $e');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Thai ID Card Reader Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: _scanIDCard,
child: Text('Scan ID Card'),
),
SizedBox(height: 20),
if (idCardData != null)
Padding(
padding: const EdgeInsets.all(8.0),
child: Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Full Name: ${idCardData!.fullName}'),
Text('Birth Date: ${idCardData!.birthDate}'),
Text('Address: ${idCardData!.address}'),
Text('ID Number: ${idCardData!.idNumber}'),
// 根据需要添加更多字段
],
),
),
),
],
),
),
);
}
}
class ThaiIDCardData {
final String fullName;
final String birthDate;
final String address;
final String idNumber;
// 根据需要添加更多字段
ThaiIDCardData({
required this.fullName,
required this.birthDate,
required this.address,
required this.idNumber,
// 根据需要添加更多字段的初始化
});
}
// 注意:ThaiIDCardData 类是一个示例,实际使用时需要根据插件返回的字段来定义
注意事项:
-
权限处理:在实际应用中,你可能需要处理相机权限和存储权限。你可以在
AndroidManifest.xml
和Info.plist
文件中声明这些权限,并在运行时请求它们。 -
错误处理:示例代码中已经包含了基本的错误处理,但在实际项目中,你可能需要更详细的错误处理逻辑。
-
插件更新:确保你使用的是插件的最新版本,以获取最新的功能和修复。
-
UI调整:根据实际需求调整UI布局和样式。
-
字段映射:
ThaiIDCardData
类中的字段需要根据thai_idcard_reader_flutter
插件实际返回的字段进行映射。请参考插件的官方文档以获取详细的字段信息。
这个示例代码展示了如何在Flutter应用中集成并使用thai_idcard_reader_flutter
插件来读取泰国身份证信息。希望这对你有所帮助!