Files
idcard/README.md
2026-03-31 08:51:18 +08:00

361 lines
9.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 身份证读卡器 Flutter 插件
一个用于读取中国二代身份证的 Flutter 插件集成了01SDK身份证识别功能支持USB和蓝牙连接方式。
## 功能特性
- ✅ 支持二代身份证读取
- ✅ 获取完整的身份证信息(姓名、性别、民族、出生日期、地址、身份证号、签发机关、有效期)
- ✅ 支持读取身份证照片
- ✅ 支持USB连接读卡器
- ✅ 支持蓝牙连接读卡器
- ✅ 完整的错误处理和状态管理
- ✅ 简单易用的API接口
## 支持平台
- ✅ Android
- ❌ iOS暂不支持
## 安装
`pubspec.yaml` 文件中添加依赖:
```yaml
dependencies:
idcard: ^0.0.1
```
然后运行:
```bash
flutter pub get
```
## Android 配置
### 权限配置
`android/app/src/main/AndroidManifest.xml` 中添加必要权限:
```xml
<!-- USB权限 -->
<uses-permission android:name="android.permission.USB_PERMISSION" />
<uses-feature android:name="android.hardware.usb.host" android:required="false" />
<!-- Android 12+ USB权限 -->
<uses-permission android:name="android.permission.MANAGE_USB" android:maxSdkVersion="30" />
<!-- 蓝牙权限 -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- Android 12+ 蓝牙权限 -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
```
### SDK版本配置
确保 `minSdkVersion` 至少为 21`targetSdkVersion` 为 34
```gradle
android {
compileSdk 34
defaultConfig {
minSdkVersion 21
targetSdkVersion 34
}
}
```
### Android 12+ 兼容性
本插件已针对 Android 12+ 进行了优化,包括:
- **PendingIntent 兼容性**:自动处理 Android 12+ 的 `FLAG_IMMUTABLE` 要求
- **USB 权限优化**:改进了权限请求流程,增加了超时处理
- **错误处理增强**:提供更详细的错误信息和用户指导
## 使用方法
### 基本用法
```dart
import 'package:idcard/idcard.dart';
class IdCardReader {
final _idcardPlugin = Idcard();
/// 连接设备并读取身份证
Future<void> readIdCard() async {
try {
// 1. 获取USB权限
int permissionResult = await _idcardPlugin.getUsbPermission();
if (permissionResult != 0) {
print('获取USB权限失败错误码$permissionResult');
return;
}
// 2. 打开设备
int openResult = await _idcardPlugin.openDevice();
if (openResult <= 0) {
print('打开设备失败,错误码:$openResult');
return;
}
print('设备打开成功,句柄:$openResult');
// 3. 读取身份证信息(完整流程)
IdCardInfo cardInfo = await _idcardPlugin.readCardComplete();
print('姓名:${cardInfo.name}');
print('身份证号:${cardInfo.idNumber}');
print('性别:${cardInfo.gender}');
// ... 其他信息
// 4. 关闭设备
await _idcardPlugin.closeDevice();
} catch (e) {
print('读卡失败:$e');
}
}
}
```
### 高级用法
#### 分步骤读取
```dart
// 手动控制每个步骤
try {
// 寻卡
int findResult = await _idcardPlugin.findCard();
if (findResult <= 0) {
throw Exception('寻卡失败,错误码:$findResult');
}
// 选卡
int selectResult = await _idcardPlugin.selectCard();
if (selectResult <= 0) {
throw Exception('选卡失败,错误码:$selectResult');
}
// 读取详细信息
IdCardInfo cardInfo = await _idcardPlugin.readCardInfo();
print('读取成功:${cardInfo.toString()}');
} catch (e) {
print('读卡过程出错:$e');
}
```
#### 蓝牙连接
```dart
// 使用蓝牙连接
int result = await _idcardPlugin.openDevice(
portType: 'BLUETOOTH',
portPara: 'BLUETOOTH_DEVICE_NAME', // 蓝牙设备名称
);
```
#### 读取原始数据
```dart
// 读取原始二进制数据
Map<String, dynamic> result = await _idcardPlugin.readCard(
cardType: 1,
infoEncoding: 0,
timeOut: 30000,
);
if (result['result'] > 0) {
List<int> rawData = result['data'];
// 处理原始数据
}
```
## 返回值说明
根据神思标准化接口规范,所有设备操作方法的返回值遵循以下规则:
- **大于0**:表示操作成功
- 对于 `openDevice()`:返回值是设备句柄,用于后续操作
- 对于其他方法:返回值表示操作成功的状态码
- **小于等于0**:表示操作失败,返回值为错误码
- 具体错误码含义请参考设备厂商提供的接口文档
### 重要提醒
在判断操作是否成功时,请使用 `> 0` 而不是 `== 0` 来判断成功状态:
```dart
// ✅ 正确的判断方式
int result = await _idcardPlugin.openDevice();
if (result > 0) {
print('设备打开成功,句柄:$result');
} else {
print('设备打开失败,错误码:$result');
}
// ❌ 错误的判断方式
if (result == 0) {
// 这样判断是错误的
}
```
## API 参考
### Idcard 类
#### 方法
| 方法 | 描述 | 参数 | 返回值 |
|------|------|------|--------|
| `getPlatformVersion()` | 获取平台版本 | 无 | `Future<String?>` |
| `getUsbPermission({int vid, int pid})` | 获取USB权限 | vid: 厂商ID, pid: 产品ID | `Future<int>` |
| `openDevice({String portType, String portPara, String extendPara})` | 打开设备 | portType: 端口类型, portPara: 端口参数, extendPara: 扩展参数 | `Future<int>` - 大于0表示成功设备句柄小于等于0表示失败 |
| `closeDevice()` | 关闭设备 | 无 | `Future<int>` - 大于0表示成功小于等于0表示失败 |
| `findCard()` | 寻卡 | 无 | `Future<int>` - 大于0表示成功小于等于0表示失败 |
| `selectCard()` | 选卡 | 无 | `Future<int>` - 大于0表示成功小于等于0表示失败 |
| `readCard({int cardType, int infoEncoding, int timeOut})` | 读取原始数据 | cardType: 卡片类型, infoEncoding: 编码, timeOut: 超时时间 | `Future<Map<String, dynamic>>` |
| `readCardInfo()` | 读取详细信息 | 无 | `Future<IdCardInfo>` |
| `readCardComplete({int timeOut})` | 完整读卡流程 | timeOut: 超时时间 | `Future<IdCardInfo>` |
| `isDeviceConnected()` | 检查设备连接状态 | 无 | `Future<bool>` |
### IdCardInfo 类
身份证信息数据模型:
```dart
class IdCardInfo {
final String name; // 姓名
final String gender; // 性别
final String nation; // 民族
final String birthDate; // 出生日期
final String address; // 地址
final String idNumber; // 身份证号
final String signOrgan; // 签发机关
final String validTerm; // 有效期
final List<int>? photo; // 照片数据JPEG格式
}
```
## 错误码说明
| 错误码 | 说明 |
|--------|------|
| 0 | 成功 |
| -1 | 设备未找到 |
| -2 | 设备接口错误 |
| -3 | 权限被拒绝 |
| 其他 | 具体错误码请参考01SDK文档 |
## 示例应用
查看 `example` 目录中的完整示例应用,演示了如何使用本插件的所有功能。
运行示例:
```bash
cd example
flutter run
```
## 故障排除
### Android 12+ USB权限问题
如果在Android 12或更高版本上遇到"获取USB权限失败"的问题,请尝试以下解决方案:
#### 1. 检查权限配置
确保在 `AndroidManifest.xml` 中正确配置了所有必要权限:
```xml
<uses-permission android:name="android.permission.USB_PERMISSION" />
<uses-permission android:name="android.permission.MANAGE_USB" android:maxSdkVersion="30" />
<uses-feature android:name="android.hardware.usb.host" android:required="false" />
```
#### 2. 手动授权USB权限
1. 进入 **设置** > **应用管理** > **您的应用**
2. 点击 **权限管理**
3. 找到并开启 **USB** 相关权限
4. 重新启动应用
#### 3. 开发者选项设置
1. 进入 **设置** > **开发者选项**
2. 开启 **USB调试**
3. 开启 **USB安装** (如果有)
4. 关闭 **监控ADB安装应用** (如果有)
#### 4. 设备连接顺序
1. 先启动应用
2. 再连接USB设备
3. 在权限对话框中点击"允许"
4. 调用 `getUsbPermission()` 方法
#### 5. 检查设备兼容性
确保您的身份证读卡器设备:
- 支持USB HID协议
- 与Android系统兼容
- VID/PID参数正确
### 常见错误码
| 错误码 | 含义 | 解决方案 |
|--------|------|----------|
| -1 | 设备未找到 | 检查设备连接和VID/PID |
| -2 | 接口错误 | 检查设备驱动和兼容性 |
| -3 | 权限被拒绝 | 手动授权USB权限 |
| -99 | 未知错误 | 重启应用或设备 |
### 其他常见问题
#### Q: 设备连接失败怎么办?
A: 请检查:
1. 设备是否正确连接
2. USB权限是否已授权
3. 设备驱动是否正常
4. VID/PID参数是否正确
#### Q: 读取身份证失败?
A: 请确保:
1. 身份证放置正确
2. 身份证芯片完好
3. 设备工作正常
4. 按正确顺序调用API
#### Q: 在模拟器上无法使用?
A: 身份证读卡功能需要物理USB设备模拟器不支持。请在真机上测试。
### Q: 照片数据如何显示?
A: 照片数据是JPEG格式的字节数组可以使用 `Image.memory()` 显示:
```dart
if (cardInfo.photo != null) {
Image.memory(Uint8List.fromList(cardInfo.photo!))
}
```
## 许可证
本项目采用 MIT 许可证。详见 [LICENSE](LICENSE) 文件。
## 贡献
欢迎提交 Issue 和 Pull Request
## 更新日志
### 0.0.1
- 初始版本
- 支持基本的身份证读取功能
- 集成01SDK
- 支持USB和蓝牙连接