import 'package:flutter/material.dart'; import 'dart:async'; import 'package:flutter/services.dart'; import 'package:idcard/idcard.dart'; import 'package:idcard/idcard_platform_interface.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatefulWidget { const MyApp({super.key}); @override State createState() => _MyAppState(); } class _MyAppState extends State { String _platformVersion = 'Unknown'; String _status = '未连接'; IdCardInfo? _cardInfo; bool _isReading = false; bool _isLoading = false; bool _isConnected = false; String _statusMessage = '未连接'; final _idcardPlugin = Idcard(); final String _portType = "USB"; final String _portPara = "0400C35A"; final String _portExtend = "MI"; @override void initState() { super.initState(); initPlatformState(); } /// 初始化平台状态 Future initPlatformState() async { String platformVersion; try { platformVersion = await _idcardPlugin.getPlatformVersion() ?? 'Unknown platform version'; } on PlatformException { platformVersion = 'Failed to get platform version.'; } if (!mounted) return; setState(() { _platformVersion = platformVersion; }); } /// 连接设备 Future _connectDevice() async { setState(() { _isLoading = true; _statusMessage = '正在连接设备...'; _status = '正在连接设备...'; }); try { // 首先获取USB权限 setState(() { _statusMessage = '正在请求USB权限...'; _status = '正在请求USB权限...'; }); // int vid = int.parse(portPara.substring(0, 4), radix: 16); // int pid = int.parse(portPara.substring(4, 8), radix: 16); final permissionResult = await _idcardPlugin.getUsbPermission(vid: int.parse(_portPara.substring(0, 4), radix: 16), pid: int.parse(_portPara.substring(4, 8), radix: 16)); if (permissionResult != 0) { throw Exception('获取USB权限失败: $permissionResult'); } // 打开设备 setState(() { _statusMessage = '正在打开设备...'; _status = '正在打开设备...'; }); // "USB", "0400C35A", "MI"; final openResult = await _idcardPlugin.openDevice(portType: _portType, portPara: _portPara, extendPara: _portExtend); print("设备句柄:$openResult"); if (openResult <= 0) { throw Exception('打开设备失败: $openResult'); } setState(() { _isConnected = true; _statusMessage = '设备连接成功'; _status = '设备连接成功'; }); } on PlatformException catch (e) { String errorMessage = '连接失败: ${e.message}'; // 针对不同错误提供用户友好的提示 if (e.code == 'PERMISSION_DENIED') { errorMessage = 'USB权限被拒绝。\n\n解决方法:\n1. 请在弹出的权限对话框中点击"允许"\n2. 或者在系统设置中手动授权USB权限\n3. 确保设备已正确连接'; } else if (e.code == 'DEVICE_NOT_FOUND') { errorMessage = '未找到身份证读卡器设备。\n\n请检查:\n1. 设备是否已连接\n2. 设备驱动是否正常\n3. VID/PID是否正确'; } setState(() { _statusMessage = errorMessage; _status = errorMessage; _isConnected = false; }); } catch (e) { setState(() { _statusMessage = '连接失败: $e'; _status = '连接失败: $e'; _isConnected = false; }); } finally { setState(() { _isLoading = false; }); } } /// 断开设备连接 Future _disconnectDevice() async { try { await _idcardPlugin.closeDevice(); setState(() { _status = '设备已断开'; _statusMessage = '设备已断开'; _isConnected = false; _cardInfo = null; }); } catch (e) { setState(() { _status = '断开连接失败:$e'; _statusMessage = '断开连接失败:$e'; }); } } /// 读取身份证 Future _readCard() async { if (_isReading) return; setState(() { _isReading = true; _status = '请将身份证放在读卡器上...'; _cardInfo = null; }); try { // 使用完整的读卡流程 IdCardInfo cardInfo = await _idcardPlugin.readCardComplete(); print(cardInfo); setState(() { _cardInfo = cardInfo; _status = '读卡成功'; _isReading = false; }); } catch (e) { setState(() { _status = '读卡失败:$e'; _isReading = false; }); } } /// 构建身份证信息显示卡片 Widget _buildCardInfoWidget() { if (_cardInfo == null) { return const SizedBox.shrink(); } return Card( margin: const EdgeInsets.all(16), child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( '身份证信息', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), const SizedBox(height: 16), _buildInfoRow('姓名', _cardInfo!.name), _buildInfoRow('性别', _cardInfo!.gender), _buildInfoRow('民族', _cardInfo!.nation), _buildInfoRow('出生日期', _cardInfo!.birthDate), _buildInfoRow('身份证号', _cardInfo!.idNumber), _buildInfoRow('地址', _cardInfo!.address), _buildInfoRow('签发机关', _cardInfo!.signOrgan), _buildInfoRow('有效期', _cardInfo!.validTerm), if (_cardInfo!.photo != null) ...[ const SizedBox(height: 16), const Text('照片:'), const SizedBox(height: 8), Container( width: 120, height: 160, decoration: BoxDecoration( border: Border.all(color: Colors.grey), borderRadius: BorderRadius.circular(8), ), child: Image.memory( Uint8List.fromList(_cardInfo!.photo!), fit: BoxFit.cover, errorBuilder: (context, error, stackTrace) { return const Center( child: Text('照片加载失败'), ); }, ), ), ], ], ), ), ); } /// 构建信息行 Widget _buildInfoRow(String label, String value) { return Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( width: 80, child: Text( '$label:', style: const TextStyle(fontWeight: FontWeight.w500), ), ), Expanded( child: Text(value), ), ], ), ); } @override Widget build(BuildContext context) { return MaterialApp( title: '身份证读卡器示例', theme: ThemeData( primarySwatch: Colors.blue, useMaterial3: true, ), home: Scaffold( appBar: AppBar( title: const Text('身份证读卡器示例'), backgroundColor: Theme.of(context).colorScheme.inversePrimary, ), body: SingleChildScrollView( child: Column( children: [ // 平台信息 Card( margin: const EdgeInsets.all(16), child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( '平台信息', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), const SizedBox(height: 8), Text('运行平台:$_platformVersion'), const SizedBox(height: 8), Text('设备状态:$_status'), ], ), ), ), // 操作按钮 Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Row( children: [ Expanded( child: ElevatedButton( onPressed: (_isLoading || _isConnected) ? null : _connectDevice, child: _isLoading ? const Row( mainAxisAlignment: MainAxisAlignment.center, children: [ SizedBox( width: 16, height: 16, child: CircularProgressIndicator( strokeWidth: 2, ), ), SizedBox(width: 8), Text('连接中...'), ], ) : const Text('连接设备'), ), ), const SizedBox(width: 16), Expanded( child: ElevatedButton( onPressed: (_isLoading || !_isConnected) ? null : _disconnectDevice, child: const Text('断开连接'), ), ), ], ), ), const SizedBox(height: 16), // 读卡按钮 Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: SizedBox( width: double.infinity, child: ElevatedButton( onPressed: (_isReading || !_isConnected || _isLoading) ? null : _readCard, style: ElevatedButton.styleFrom( backgroundColor: Colors.green, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 16), ), child: _isReading ? const Row( mainAxisAlignment: MainAxisAlignment.center, children: [ SizedBox( width: 20, height: 20, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(Colors.white), ), ), SizedBox(width: 8), Text('正在读卡...'), ], ) : const Text( '读取身份证', style: TextStyle(fontSize: 16), ), ), ), ), // 身份证信息显示 _buildCardInfoWidget(), ], ), ), ), ); } }