This commit is contained in:
2026-04-13 16:03:06 +08:00
parent e9f4844352
commit dc30881d38
4 changed files with 115 additions and 16 deletions

View File

@@ -15,6 +15,7 @@ import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.EventChannel;
import android.os.SystemClock;
@@ -32,18 +33,23 @@ public class ZhiwenPlugin implements FlutterPlugin, MethodCallHandler, ActivityA
// 常量定义
private static final String TAG = "ZhiwenPlugin";
private static final String CHANNEL_NAME = "zhiwen";
private static final String EVENT_CHANNEL_NAME = "zhiwen_progress";
private static final int DEFAULT_MAX_FP_COUNT = 3000;
private static final int ENROLL_STEP_COUNT = 3;
private static final int IMAGE_BUFFER_SIZE = 1024 * 100;
// 响应状态码
private static final int RESPONSE_SUCCESS = 1;
private static final int RESPONSE_FAIL = -1;
private static final int RESPONSE_NOT_FOUND = 0;
/// Flutter与Android原生通信的MethodChannel
/// 用于注册插件到Flutter引擎并在Activity分离时注销
private MethodChannel channel;
/// 进度事件通道用于向Flutter发送指纹录入进度
private EventChannel progressEventChannel;
private EventChannel.EventSink progressEventSink;
// 设备通信对象使用static确保全局唯一
private static DevComm m_devComm;
@@ -60,12 +66,28 @@ public class ZhiwenPlugin implements FlutterPlugin, MethodCallHandler, ActivityA
/**
* 插件附加到Flutter引擎时的回调
* 初始化MethodChannel并设置方法调用处理器
* 初始化MethodChannel和EventChannel并设置方法调用处理器
*/
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), CHANNEL_NAME);
channel.setMethodCallHandler(this);
// 初始化进度事件通道
progressEventChannel = new EventChannel(flutterPluginBinding.getBinaryMessenger(), EVENT_CHANNEL_NAME);
progressEventChannel.setStreamHandler(new EventChannel.StreamHandler() {
@Override
public void onListen(Object arguments, EventChannel.EventSink events) {
progressEventSink = events;
Log.d(TAG, "进度事件监听已启动");
}
@Override
public void onCancel(Object arguments) {
progressEventSink = null;
Log.d(TAG, "进度事件监听已取消");
}
});
// 注意这里不应该从ApplicationContext获取Activity应该等待onAttachedToActivity回调
}
@@ -290,24 +312,29 @@ public class ZhiwenPlugin implements FlutterPlugin, MethodCallHandler, ActivityA
final int[] duplicateId = new int[1];
final int[] imageWidth = new int[1];
final int[] imageHeight = new int[1];
try {
// 发送开始录入进度事件
sendProgressEvent(0, ENROLL_STEP_COUNT, "请准备放置手指");
// 录入指定次数的指纹
while (enrollStep < ENROLL_STEP_COUNT) {
Log.d(TAG, String.format("请放置手指进行第%d次录入", enrollStep + 1));
// 显示提示信息
showToastOnMainThread(String.format("请放置手指 (%d/%d)", enrollStep + 1, ENROLL_STEP_COUNT));
// 发送进度事件到Flutter
sendProgressEvent(enrollStep + 1, ENROLL_STEP_COUNT,
String.format("请放置手指 (%d/%d)", enrollStep + 1, ENROLL_STEP_COUNT));
// 采集指纹图像
if (captureFingerprint() < 0) {
sendProgressEvent(-1, ENROLL_STEP_COUNT, "指纹采集失败");
Map<String, Object> errorResult = createErrorResponse("指纹采集失败");
mainHandler.post(() -> result.success(errorResult));
return;
}
Log.d(TAG, "请移开手指");
showToastOnMainThread("请移开手指");
sendProgressEvent(enrollStep + 1, ENROLL_STEP_COUNT, "请移开手指");
// 上传指纹图像仅USB模式
if (m_devComm.m_nConnected == 2) {
@@ -315,6 +342,7 @@ public class ZhiwenPlugin implements FlutterPlugin, MethodCallHandler, ActivityA
if (uploadResult != DevComm.ERR_SUCCESS) {
String errorMsg = GetErrorMsg(uploadResult);
Log.e(TAG, "上传指纹图像失败: " + errorMsg);
sendProgressEvent(-1, ENROLL_STEP_COUNT, "上传图像失败: " + errorMsg);
Map<String, Object> errorResult = createErrorResponse(errorMsg);
mainHandler.post(() -> result.success(errorResult));
return;
@@ -326,11 +354,12 @@ public class ZhiwenPlugin implements FlutterPlugin, MethodCallHandler, ActivityA
if (generateResult != DevComm.ERR_SUCCESS) {
if (generateResult == DevComm.ERR_BAD_QUALITY) {
Log.w(TAG, "指纹质量不佳,请重试");
showToastOnMainThread("指纹质量不佳,请重试");
sendProgressEvent(enrollStep + 1, ENROLL_STEP_COUNT, "指纹质量不佳,请重试");
continue; // 重试当前步骤
} else {
String errorMsg = GetErrorMsg(generateResult);
Log.e(TAG, "生成指纹特征失败: " + errorMsg);
sendProgressEvent(-1, ENROLL_STEP_COUNT, "生成特征失败: " + errorMsg);
Map<String, Object> errorResult = createErrorResponse(errorMsg);
mainHandler.post(() -> result.success(errorResult));
return;
@@ -340,18 +369,25 @@ public class ZhiwenPlugin implements FlutterPlugin, MethodCallHandler, ActivityA
enrollStep++;
}
// 发送合并进度事件
sendProgressEvent(ENROLL_STEP_COUNT, ENROLL_STEP_COUNT, "正在合并指纹特征...");
// 合并多次录入的特征如果录入次数大于1
if (ENROLL_STEP_COUNT > 1) {
int mergeResult = m_devComm.Run_Merge(0, ENROLL_STEP_COUNT);
if (mergeResult != DevComm.ERR_SUCCESS) {
String errorMsg = GetErrorMsg(mergeResult);
Log.e(TAG, "合并指纹特征失败: " + errorMsg);
sendProgressEvent(-1, ENROLL_STEP_COUNT, "合并失败: " + errorMsg);
Map<String, Object> errorResult = createErrorResponse(errorMsg);
mainHandler.post(() -> result.success(errorResult));
return;
}
}
// 发送存储进度事件
sendProgressEvent(ENROLL_STEP_COUNT, ENROLL_STEP_COUNT, "正在存储指纹模板...");
// 存储指纹模板
int storeResult = m_devComm.Run_StoreChar(userId, 0, duplicateId);
if (storeResult != DevComm.ERR_SUCCESS) {
@@ -362,6 +398,7 @@ public class ZhiwenPlugin implements FlutterPlugin, MethodCallHandler, ActivityA
errorMsg = GetErrorMsg(storeResult);
}
Log.e(TAG, "存储指纹模板失败: " + errorMsg);
sendProgressEvent(-1, ENROLL_STEP_COUNT, "存储失败: " + errorMsg);
Map<String, Object> errorResult = createErrorResponse(errorMsg);
mainHandler.post(() -> result.success(errorResult));
return;
@@ -369,15 +406,16 @@ public class ZhiwenPlugin implements FlutterPlugin, MethodCallHandler, ActivityA
// 录入成功
Log.i(TAG, String.format("指纹录入成功用户ID: %d", userId));
sendProgressEvent(ENROLL_STEP_COUNT, ENROLL_STEP_COUNT, "指纹录入成功");
Map<String, Object> successResult = createSuccessResponse("指纹录入成功");
successResult.put("userId", userId);
mainHandler.post(() -> {
showToastOnMainThread("指纹录入成功");
result.success(successResult);
});
} catch (Exception e) {
Log.e(TAG, "指纹录入过程中发生异常: " + e.getMessage(), e);
sendProgressEvent(-1, ENROLL_STEP_COUNT, "录入异常: " + e.getMessage());
Map<String, Object> errorResult = createErrorResponse("录入过程发生异常: " + e.getMessage());
mainHandler.post(() -> result.success(errorResult));
} finally {
@@ -810,6 +848,30 @@ public class ZhiwenPlugin implements FlutterPlugin, MethodCallHandler, ActivityA
});
}
}
/**
* 发送进度事件到Flutter端
* @param step 当前步骤1-3
* @param totalSteps 总步骤数3
* @param message 进度消息
*/
private void sendProgressEvent(int step, int totalSteps, String message) {
if (progressEventSink != null) {
mainHandler.post(() -> {
try {
Map<String, Object> progressData = new HashMap<>();
progressData.put("step", step);
progressData.put("totalSteps", totalSteps);
progressData.put("progress", (double) step / totalSteps);
progressData.put("message", message);
progressEventSink.success(progressData);
Log.d(TAG, "发送进度事件: step=" + step + "/" + totalSteps + ", message=" + message);
} catch (Exception e) {
Log.w(TAG, "发送进度事件失败: " + e.getMessage());
}
});
}
}
/**
* 采集指纹图像重命名原Capturing方法
@@ -822,13 +884,20 @@ public class ZhiwenPlugin implements FlutterPlugin, MethodCallHandler, ActivityA
@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
Log.d(TAG, "插件从引擎分离");
// 清理资源
// 清理进度事件通道
if (progressEventChannel != null) {
progressEventChannel.setStreamHandler(null);
progressEventChannel = null;
progressEventSink = null;
}
// 清理方法通道
if (channel != null) {
channel.setMethodCallHandler(null);
channel = null;
}
// 关闭设备连接
if (m_devComm != null && m_devComm.IsInit()) {
try {
@@ -838,7 +907,7 @@ public class ZhiwenPlugin implements FlutterPlugin, MethodCallHandler, ActivityA
Log.e(TAG, "关闭设备连接时发生异常: " + e.getMessage());
}
}
// 关闭线程池
if (executorService != null && !executorService.isShutdown()) {
executorService.shutdown();

View File

@@ -1,5 +1,6 @@
import 'zhiwen_platform_interface.dart';
import 'dart:async';
class Zhiwen {
Future<String?> getPlatformVersion() {
@@ -37,4 +38,10 @@ class Zhiwen {
Future<Map<String, dynamic>> getUserCount() {
return ZhiwenPlatform.instance.getUserCount();
}
/// 获取指纹录入进度事件流
/// 返回包含 step, totalSteps, progress, message 的 Map
Stream<Map<String, dynamic>> get progressStream {
return ZhiwenPlatform.instance.progressStream;
}
}

View File

@@ -1,5 +1,6 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'dart:async';
import 'zhiwen_platform_interface.dart';
@@ -9,6 +10,13 @@ class MethodChannelZhiwen extends ZhiwenPlatform {
@visibleForTesting
final methodChannel = const MethodChannel('zhiwen');
/// The event channel for receiving fingerprint enrollment progress.
@visibleForTesting
final progressEventChannel = const EventChannel('zhiwen_progress');
/// 进度事件流控制器
Stream<Map<String, dynamic>>? _progressStream;
@override
Future<String?> getPlatformVersion() async {
final version = await methodChannel.invokeMethod<String>('getPlatformVersion');
@@ -64,4 +72,13 @@ class MethodChannelZhiwen extends ZhiwenPlatform {
final result = await methodChannel.invokeMethod('getUserCount');
return Map<String, dynamic>.from(result as Map);
}
/// 获取指纹录入进度事件流
@override
Stream<Map<String, dynamic>> get progressStream {
_progressStream ??= progressEventChannel
.receiveBroadcastStream()
.map((event) => Map<String, dynamic>.from(event as Map));
return _progressStream!;
}
}

View File

@@ -1,4 +1,5 @@
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
import 'dart:async';
import 'zhiwen_method_channel.dart';
@@ -24,6 +25,11 @@ abstract class ZhiwenPlatform extends PlatformInterface {
Future<Map<String, dynamic>> deleteOneFingerprint(int userId);
Future<Map<String, dynamic>> identifyFingerprint();
Future<Map<String, dynamic>> getUserCount();
/// 获取指纹录入进度事件流
/// 返回包含 step, totalSteps, progress, message 的 Map
Stream<Map<String, dynamic>> get progressStream;
/// Platform-specific implementations should set this with their own
/// platform-specific class that extends [ZhiwenPlatform] when
/// they register themselves.