361 lines
9.6 KiB
Markdown
361 lines
9.6 KiB
Markdown
# 身份证读卡器 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和蓝牙连接
|
||
|