diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 32446a6..fd36261 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -7,6 +7,11 @@
+
+
+
+
+
@@ -103,6 +108,12 @@
android:name=".DebugActivity"
android:exported="false"
android:theme="@style/Theme.OxFaceLogin" />
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/baidu/idl/face/main/finance/utils/TestPopWindow.java b/app/src/main/java/com/baidu/idl/face/main/finance/utils/TestPopWindow.java
new file mode 100644
index 0000000..8c7e770
--- /dev/null
+++ b/app/src/main/java/com/baidu/idl/face/main/finance/utils/TestPopWindow.java
@@ -0,0 +1,81 @@
+package com.baidu.idl.face.main.finance.utils;
+
+import android.content.Context;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.PopupWindow;
+
+import com.baidu.idl.main.facesdk.financelibrary.R;
+
+public class TestPopWindow extends PopupWindow {
+ private String TAG = "TestPopWindow";
+ private final Context gContext;
+ private View view;
+
+ public TestPopWindow(Context context) {
+ this(context, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ Log.d(TAG, "TestPopWindow: " + ViewGroup.LayoutParams.WRAP_CONTENT
+ + "bbb:" + ViewGroup.LayoutParams.WRAP_CONTENT);
+ }
+
+ public TestPopWindow(Context context, int width, int height) {
+ super(context);
+ this.gContext = context;
+ view = View.inflate(context, R.layout.layout_no_face_detected, null);
+ view.findViewById(R.id.retest_detectBtn).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ mOnClickFinance.rester(true);
+ }
+ });
+ view.findViewById(R.id.back_homeBtn).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ mOnClickFinance.rester(false);
+ }
+ });
+
+ setContentView(view);
+ // 设置窗口的高和宽
+ setWidth(width);
+ setHeight(height);
+ // 设置弹窗内科点击
+ setTouchable(true);
+ setOutsideTouchable(true);
+ setFocusable(true);
+ // TODO去除背景
+ setBackgroundDrawable(null);
+
+ }
+
+ /**
+ * 显示popupWindow
+ */
+ public void showPopupWindow(View parent) {
+ if (!this.isShowing()) {
+ // 以下拉方式显示popupwindow,调整位置使其不会完全遮挡预览界面
+ this.showAtLocation(parent, Gravity.CENTER, 0, -50);
+ } else {
+ this.dismiss();
+ }
+ }
+
+ public void closePopupWindow() {
+ if (this.isShowing()) {
+ this.dismiss();
+ }
+ }
+
+
+ public void setmOnClickFinance(OnClickFinance mOnClickFinance) {
+ this.mOnClickFinance = mOnClickFinance;
+ }
+
+ public OnClickFinance mOnClickFinance;
+
+ public interface OnClickFinance {
+ void rester(boolean isReTest);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ouxuan/oxface/DebugActivity.java b/app/src/main/java/com/ouxuan/oxface/DebugActivity.java
index c27f412..6ab71e0 100644
--- a/app/src/main/java/com/ouxuan/oxface/DebugActivity.java
+++ b/app/src/main/java/com/ouxuan/oxface/DebugActivity.java
@@ -171,6 +171,15 @@ public class DebugActivity extends Activity {
}
});
+ // 人脸识别测试按钮
+ Button btnFaceRecognitionTest = findViewById(R.id.btnFaceRecognitionTest);
+ btnFaceRecognitionTest.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ startFaceRecognitionTest();
+ }
+ });
+
// 关闭按钮
Button btnClose = findViewById(R.id.btnClose);
btnClose.setOnClickListener(new View.OnClickListener() {
@@ -461,6 +470,23 @@ public class DebugActivity extends Activity {
}
/**
+ * 启动人脸识别测试
+ */
+ private void startFaceRecognitionTest() {
+ logMessage("启动人脸识别测试...");
+ try {
+ Intent intent = new Intent(this, OXFaceOnlineActivity.class);
+ startActivity(intent);
+ logMessage("已启动人脸识别测试界面");
+ showToast("已启动人脸识别测试界面");
+ } catch (Exception e) {
+ Log.e(TAG, "启动人脸识别测试失败", e);
+ logMessage("启动人脸识别测试失败: " + e.getMessage());
+ showToast("启动人脸识别测试失败");
+ }
+ }
+
+ /**
* 在日志输出区域添加消息
* @param message 要添加的消息
*/
diff --git a/app/src/main/java/com/ouxuan/oxface/MainActivity.java b/app/src/main/java/com/ouxuan/oxface/MainActivity.java
index a520b84..40c88f7 100644
--- a/app/src/main/java/com/ouxuan/oxface/MainActivity.java
+++ b/app/src/main/java/com/ouxuan/oxface/MainActivity.java
@@ -59,6 +59,7 @@ public class MainActivity extends AppCompatActivity {
private DeviceSelectDataManager deviceSelectDataManager; // 设备选择数据管理器
private KeepAliveManager keepAliveManager; // 保持活跃管理器
private AutoStartManager autoStartManager; // 自启动管理器
+ private Dialog currentDialog; // 用于跟踪当前显示的Dialog,防止WindowLeaked错误
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -110,6 +111,9 @@ public class MainActivity extends AppCompatActivity {
// 设置长按登录按钮显示日志路径信息(调试功能)
setupLogPathDebug();
+
+ //切换第六批设备
+ switchCameraByDeviceType(5);
}
/**
@@ -170,14 +174,17 @@ public class MainActivity extends AppCompatActivity {
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
- if (loginDataManager.isLoggedIn()) {
- showToast("自动登录成功!");
- showLoginSuccessDialog(loginDataManager.getLoginData());
- } else {
- android.util.Log.w("MainActivity", "自动登录失败,本地数据可能已失效");
- showToast("自动登录失败,请手动登录");
- // 清除可能已失效的登录数据
- loginDataManager.clearLoginData();
+ // 检查Activity是否仍然有效
+ if (!isFinishing() && !isDestroyed()) {
+ if (loginDataManager.isLoggedIn()) {
+ showToast("自动登录成功!");
+ showLoginSuccessDialog(loginDataManager.getLoginData());
+ } else {
+ android.util.Log.w("MainActivity", "自动登录失败,本地数据可能已失效");
+ showToast("自动登录失败,请手动登录");
+ // 清除可能已失效的登录数据
+ loginDataManager.clearLoginData();
+ }
}
}
}, 1000); // 延迟1秒
@@ -305,10 +312,12 @@ public class MainActivity extends AppCompatActivity {
// 打印存储的data
android.util.Log.d("MainActivity", "Login Data: " + data.toString());
-
- // 显示登录成功弹框,传入登录数据
- showToast("登录成功!");
- showLoginSuccessDialog(data);
+ // 检查Activity是否仍然有效再显示Dialog
+ if (!isFinishing() && !isDestroyed()) {
+ // 显示登录成功弹框,传入登录数据
+ showToast("登录成功!");
+ showLoginSuccessDialog(data);
+ }
}
@Override
@@ -384,6 +393,7 @@ public class MainActivity extends AppCompatActivity {
private void showLoginSuccessDialog(PadApiService.PadLoginResponse loginData) {
// 创建自定义弹框
Dialog dialog = new Dialog(this);
+ currentDialog = dialog; // 保存Dialog引用以防止WindowLeaked错误
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.dialog_login_success);
@@ -437,6 +447,7 @@ public class MainActivity extends AppCompatActivity {
@Override
public void onClick(View v) {
dialog.dismiss();
+ currentDialog = null; // 清除引用
}
});
@@ -496,6 +507,7 @@ public class MainActivity extends AppCompatActivity {
// 显示成功消息并关闭弹框
showToast("进入 " + selectedPlatform + " 成功!");
dialog.dismiss();
+ currentDialog = null; // 清除引用
// 这里可以添加跳转到主界面的逻辑
}
@@ -697,6 +709,7 @@ public class MainActivity extends AppCompatActivity {
initializeFaceSDKIfNeeded();
dialog.dismiss();
+ currentDialog = null; // 清除引用
// 这里可以添加跳转到主界面的逻辑
}
@@ -769,6 +782,19 @@ public class MainActivity extends AppCompatActivity {
android.util.Log.d("MainActivity", logMessage);
LogManager.logInfo("FaceSDK", logMessage);
+ // 先检查和初始化配置文件
+ final boolean configSuccess = initAndCheckFaceConfig(this);
+
+ // 在UI线程显示配置文件状态提示
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ Toast.makeText(MainActivity.this,
+ configSuccess ? "配置文件加载成功" : "初始配置失败,已重置为默认配置",
+ Toast.LENGTH_SHORT).show();
+ }
+ });
+
// 获取FaceSDKManager实例
com.baidu.idl.face.main.finance.manager.FaceSDKManager faceSDKManager =
com.baidu.idl.face.main.finance.manager.FaceSDKManager.getInstance();
@@ -865,11 +891,11 @@ public class MainActivity extends AppCompatActivity {
android.util.Log.e("MainActivity", logMessage, e);
LogManager.logError("FaceSDK", logMessage, e);
runOnUiThread(new Runnable() {
- @Override
- public void run() {
- showToast("人脸SDK初始化异常: " + e.getMessage());
- }
- });
+ @Override
+ public void run() {
+ showToast("人脸SDK初始化异常: " + e.getMessage());
+ }
+ });
}
}
@@ -887,6 +913,9 @@ public class MainActivity extends AppCompatActivity {
android.util.Log.d("MainActivity", logMessage);
LogManager.logInfo("FaceSDK", logMessage);
+ // 在初始化模型前再次检查配置文件,确保配置已正确加载
+ initAndCheckFaceConfig(this);
+
faceSDKManager.initModel(this, new com.baidu.idl.face.main.finance.listener.SdkInitListener() {
@Override
public void initStart() {
@@ -941,6 +970,39 @@ public class MainActivity extends AppCompatActivity {
}
}
+ /**
+ * 根据设备类型切换摄像头配置
+ * @param deviceType 设备类型,5表示第6批设备,其他值表示非第6批设备
+ */
+ private void switchCameraByDeviceType(int deviceType) {
+ try {
+ // 获取FaceSDKManager实例
+ com.baidu.idl.face.main.finance.manager.FaceSDKManager faceSDKManager =
+ com.baidu.idl.face.main.finance.manager.FaceSDKManager.getInstance();
+
+ // 调用FaceSDKManager中的方法
+ faceSDKManager.switchCameraByDeviceType(deviceType);
+
+ String logMessage = "已根据设备类型(" + deviceType + ")切换摄像头配置";
+ android.util.Log.d("MainActivity", logMessage);
+ LogManager.logInfo("FaceSDK", logMessage);
+
+ // 显示切换成功提示
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ Toast.makeText(MainActivity.this,
+ "摄像头配置已切换为" + (deviceType == 5 ? "第6批" : "非第6批") + "设备",
+ Toast.LENGTH_SHORT).show();
+ }
+ });
+ } catch (Exception e) {
+ String errorMessage = "切换摄像头配置失败: " + e.getMessage();
+ android.util.Log.e("MainActivity", errorMessage, e);
+ LogManager.logError("FaceSDK", errorMessage, e);
+ }
+ }
+
@Override
protected void onResume() {
super.onResume();
@@ -964,6 +1026,12 @@ public class MainActivity extends AppCompatActivity {
protected void onDestroy() {
super.onDestroy();
+ // 关闭任何正在显示的Dialog以防止WindowLeaked错误
+ if (currentDialog != null && currentDialog.isShowing()) {
+ currentDialog.dismiss();
+ currentDialog = null;
+ }
+
LogManager.logOperation("MainActivity", "主界面正在销毁");
// 只在应用真正退出时才停止保持活跃
@@ -1239,4 +1307,27 @@ public class MainActivity extends AppCompatActivity {
showToast("自启动管理器未初始化");
}
}
+
+ /**
+ * 初始化并检查人脸识别配置文件
+ * @param context 上下文
+ * @return 配置文件是否已成功初始化
+ */
+ private boolean initAndCheckFaceConfig(Context context) {
+ boolean isFinanceConfigExit = com.baidu.idl.face.main.finance.utils.FinanceConfigUtils.isConfigExit(context);
+ boolean isFinanceInitConfig = com.baidu.idl.face.main.finance.utils.FinanceConfigUtils.initConfig();
+
+ String logMessage = "配置文件状态: 存在=" + isFinanceConfigExit + ", 初始化=" + isFinanceInitConfig;
+ android.util.Log.d("MainActivity", logMessage);
+
+ if (isFinanceInitConfig && isFinanceConfigExit) {
+ LogManager.logInfo("FaceSDK", "配置文件加载成功");
+ return true;
+ } else {
+ LogManager.logWarning("FaceSDK", "初始配置失败,将重置文件内容为默认配置");
+ // 修改为默认配置
+ com.baidu.idl.face.main.finance.utils.FinanceConfigUtils.modityJson();
+ return false;
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/ouxuan/oxface/OXFaceOnlineActivity.java b/app/src/main/java/com/ouxuan/oxface/OXFaceOnlineActivity.java
new file mode 100644
index 0000000..19ac470
--- /dev/null
+++ b/app/src/main/java/com/ouxuan/oxface/OXFaceOnlineActivity.java
@@ -0,0 +1,547 @@
+package com.ouxuan.oxface;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.RectF;
+import android.hardware.Camera;
+import android.os.Bundle;
+import android.os.Handler;
+import android.util.Log;
+import android.view.TextureView;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+
+import com.baidu.idl.face.main.finance.activity.BaseActivity;
+import com.baidu.idl.face.main.finance.callback.CameraDataCallback;
+import com.baidu.idl.face.main.finance.callback.FaceDetectCallBack;
+import com.baidu.idl.face.main.finance.camera.AutoTexturePreviewView;
+import com.baidu.idl.face.main.finance.camera.CameraPreviewManager;
+import com.baidu.idl.face.main.finance.manager.FaceSDKManager;
+import com.baidu.idl.face.main.finance.model.LivenessModel;
+import com.baidu.idl.face.main.finance.model.SingleBaseConfig;
+import com.baidu.idl.face.main.finance.utils.BitmapUtils;
+import com.baidu.idl.face.main.finance.utils.FaceOnDrawTexturViewUtil;
+import com.baidu.idl.face.main.finance.utils.TestPopWindow;
+import com.baidu.idl.main.facesdk.FaceInfo;
+import com.baidu.idl.main.facesdk.model.BDFaceImageInstance;
+import com.ouxuan.oxface.utils.LogManager;
+
+/**
+ * 简化版人脸识别界面 - 只显示视频流
+ */
+public class OXFaceOnlineActivity extends BaseActivity implements View.OnClickListener {
+
+ private static final float MIN_FACE_AREA = 1500; //人脸靠近阈值: 人脸面积在屏幕中的像素乘积
+ private static final String TAG = "OXFaceOnlineActivity";
+ private static final int CAMERA_PERMISSION_REQUEST_CODE = 1001;
+
+ // 图片越大,性能消耗越大,也可以选择640*480, 1280*720
+ private static final int PREFER_WIDTH = SingleBaseConfig.getBaseConfig().getRgbAndNirWidth();
+ private static final int PERFER_HEIGH = SingleBaseConfig.getBaseConfig().getRgbAndNirHeight();
+ private Context mContext;
+ private AutoTexturePreviewView mAutoCameraPreviewView;
+ private TextureView mDrawDetectFaceView;
+ private RelativeLayout relativeLayout;
+ private boolean isNeedCamera = true;
+ private RectF rectF;
+ private Paint paint;
+ private Paint paintBg;
+ private boolean liveStatus;
+ private LivenessModel currentLivenessModel;
+
+ // 新增的视图元素
+ private TextView preText;
+ private ImageView previewView;
+ private RelativeLayout preViewRelativeLayout;
+
+ private TextView deveLop;
+ private RelativeLayout deveLopRelativeLayout;
+ private ImageView developView;
+ private TextView preToastText;
+ private TextView detectSurfaceText;
+ private ImageView isCheckImage;
+ private ImageView mFaceDetectImageView;
+ private TextView mTvDetect;
+ private TextView mTvLive;
+ private TextView mTvLiveScore;
+ private TextView mTvAllTime;
+ private RelativeLayout progressLayout;
+ private RelativeLayout layoutCompareStatus;
+ private TextView textCompareStatus;
+ private ImageView progressBarView;
+ private RelativeLayout payHintRl;
+ private boolean mIsPayHint = true;
+ private boolean count = true;
+ private RelativeLayout financeQualityTestFailed;
+ private TextView qualityTestTimeTv;
+ private TextView qualityDetectedTv;
+ private TextView qualityShelteredPart;
+ private Button qualityRetestDetectBtn;
+ private RelativeLayout financeByLivingDetection;
+ private RelativeLayout financeFailedInVivoTest;
+ private TextView failedInVivoTestRgb;
+ private TextView failedInVivoTestNir;
+ private TextView failedInVivoTestDepth;
+ private TextView failedInVivoTestTime;
+ private TextView failedInVivoTestFrames;
+ private TextView byLivingDetectionRgb;
+ private TextView byLivingDetectionNir;
+ private TextView byLivingDetectionDepth;
+ private TextView byLivingTetectionTime;
+ private TextView byLivingDetectionFrames;
+ private ImageView qualityDetectRegImageItem;
+ private ImageView noDetectRegImageItem;
+ private ImageView detectRegImageItem;
+ private TestPopWindow testPopWindow;
+ private View saveCamera;
+ private boolean isSaveImage;
+ private View spot;
+ private boolean isCheck = false;
+ private boolean isTime = true;
+ private long searshTime;
+ private boolean isCompareCheck = false;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_oxface_online);
+
+ mContext = this;
+ initView();
+
+ // 检查并请求相机权限
+ if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA)
+ != PackageManager.PERMISSION_GRANTED) {
+ ActivityCompat.requestPermissions(this,
+ new String[]{android.Manifest.permission.CAMERA},
+ CAMERA_PERMISSION_REQUEST_CODE);
+ } else {
+ LogManager.logInfo(TAG, "相机权限已授予");
+ }
+
+ LogManager.logInfo(TAG, "OXFaceOnlineActivity onCreate");
+ }
+
+ /**
+ * View
+ */
+ private void initView() {
+ LogManager.logInfo(TAG, "初始化界面视图");
+ // 获取整个布局
+ relativeLayout = findViewById(R.id.all_relative);
+
+ // 单目摄像头RGB 图像预览
+ mAutoCameraPreviewView = findViewById(R.id.auto_camera_preview_view);
+ // 画人脸框
+ rectF = new RectF();
+ paint = new Paint();
+ paintBg = new Paint();
+ mDrawDetectFaceView = findViewById(R.id.draw_detect_face_view);
+ mDrawDetectFaceView.setOpaque(false);
+ mDrawDetectFaceView.setKeepScreenOn(true);
+
+ LogManager.logInfo(TAG, "镜像设置getRgbRevert"+SingleBaseConfig.getBaseConfig().getRgbRevert());
+
+ //TODO 还需要根据实际情况继续调整摄像头镜像参数
+ android.util.Log.d( "OXFaceOnlineActivity", ": 666666" + SingleBaseConfig.getBaseConfig().getRgbRevert());
+ if (SingleBaseConfig.getBaseConfig().getRgbRevert()){
+ mDrawDetectFaceView.setRotationY(180);
+ }else{
+// mDrawDetectFaceView.setRotationY(0);
+ }
+
+ // 返回
+ ImageView mButReturn = findViewById(R.id.btn_back);
+ mButReturn.setOnClickListener(this);
+
+ // ***************预览模式*************
+ // 导航栏
+// preText = findViewById(R.id.preview_text);
+// if (preText != null) {
+// preText.setOnClickListener(this);
+// preText.setTextColor(Color.parseColor("#ffffff"));
+// }
+// previewView = findViewById(R.id.preview_view);
+ // 信息展示
+ preViewRelativeLayout = findViewById(R.id.yvlan_relativeLayout);
+ preToastText = findViewById(R.id.pre_toast_text);
+ progressLayout = findViewById(R.id.progress_layout);
+ progressBarView = findViewById(R.id.progress_bar_view);
+ // 隐藏圆形进度条
+ if (progressLayout != null) {
+ progressLayout.setVisibility(View.GONE);
+ }
+ // 预览模式下提示
+ payHintRl = findViewById(R.id.pay_hintRl);
+
+ // ***************开发模式*************
+ // 导航栏
+// deveLop = findViewById(R.id.develop_text);
+// if (deveLop != null) {
+// deveLop.setOnClickListener(this);
+// deveLop.setTextColor(Color.parseColor("#a9a9a9"));
+// }
+// developView = findViewById(R.id.develop_view);
+// if (developView != null) {
+// developView.setVisibility(View.GONE);
+// }
+ // 信息展示
+// deveLopRelativeLayout = findViewById(R.id.kaifa_relativeLayout);
+ // isCheckImage = findViewById(R.id.is_check_image);
+// detectSurfaceText = findViewById(R.id.detect_surface_text);
+// if (detectSurfaceText != null) {
+// detectSurfaceText.setVisibility(View.GONE);
+// }
+ // 送检RGB 图像回显
+// mFaceDetectImageView = findViewById(R.id.face_detect_image_view);
+// if (mFaceDetectImageView != null) {
+// mFaceDetectImageView.setVisibility(View.GONE);
+// }
+ // 检测耗时
+// mTvDetect = findViewById(R.id.tv_detect_time);
+ // RGB活体
+// mTvLive = findViewById(R.id.tv_rgb_live_time);
+// mTvLiveScore = findViewById(R.id.tv_rgb_live_score);
+ // 总耗时
+// mTvAllTime = findViewById(R.id.tv_all_time);
+ layoutCompareStatus = findViewById(R.id.layout_compare_status);
+ if (layoutCompareStatus != null) {
+ layoutCompareStatus.setVisibility(View.GONE);
+ }
+ textCompareStatus = findViewById(R.id.text_compare_status);
+ // 存图按钮
+ saveCamera = findViewById(R.id.save_camera);
+ if (saveCamera != null) {
+ saveCamera.setOnClickListener(this);
+ saveCamera.setVisibility(View.GONE);
+ }
+ spot = findViewById(R.id.spot);
+
+ // 质量检测未通过
+ financeQualityTestFailed = findViewById(R.id.finance_quality_test_failed);
+ qualityTestTimeTv = findViewById(R.id.quality_test_timeTv);
+ qualityDetectedTv = findViewById(R.id.quality_detectedTv);
+ qualityShelteredPart = findViewById(R.id.quality_sheltered_part);
+ qualityRetestDetectBtn = findViewById(R.id.quality_retest_detectBtn);
+ if (qualityRetestDetectBtn != null) {
+ qualityRetestDetectBtn.setOnClickListener(this);
+ }
+
+ // 活体通过
+ financeByLivingDetection = findViewById(R.id.finance_by_living_detection);
+ byLivingDetectionRgb = findViewById(R.id.by_living_detection_rgb);
+ byLivingDetectionNir = findViewById(R.id.by_living_detection_nir);
+ byLivingDetectionDepth = findViewById(R.id.by_living_detection_depth);
+ byLivingTetectionTime = findViewById(R.id.by_living_detection_time);
+ byLivingDetectionFrames = findViewById(R.id.by_living_detection_Frames);
+ Button byLivingDetectionBtn = findViewById(R.id.by_living_detection_btn);
+ if (byLivingDetectionBtn != null) {
+ byLivingDetectionBtn.setOnClickListener(this);
+ }
+ detectRegImageItem = findViewById(R.id.detect_reg_image_item);
+
+ // 活体未通过
+ financeFailedInVivoTest = findViewById(R.id.finance_failed_in_vivo_test);
+ failedInVivoTestRgb = findViewById(R.id.failed_in_vivo_test_rgb);
+ failedInVivoTestNir = findViewById(R.id.failed_in_vivo_test_nir);
+ failedInVivoTestDepth = findViewById(R.id.failed_in_vivo_test_depth);
+ failedInVivoTestTime = findViewById(R.id.failed_in_vivo_test_time);
+ failedInVivoTestFrames = findViewById(R.id.failed_in_vivo_test_Frames);
+ Button failed_in_vivo_testBtn = findViewById(R.id.failed_in_vivo_testBtn);
+ if (failed_in_vivo_testBtn != null) {
+ failed_in_vivo_testBtn.setOnClickListener(this);
+ }
+ noDetectRegImageItem = findViewById(R.id.no_detect_reg_image_item);
+
+ testPopWindow = new TestPopWindow(this,
+ ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+ testPopWindow.setmOnClickFinance(new TestPopWindow.OnClickFinance() {
+ @Override
+ public void rester(boolean isReTest) {
+ // 重新检测
+ if (isReTest) {
+ if (testPopWindow != null) {
+ testPopWindow.closePopupWindow();
+ }
+ if (payHintRl != null) {
+ payHintRl.setVisibility(View.GONE);
+ }
+ count = true;
+ new Handler().postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ if (count) {
+ isNeedCamera = true;
+ }
+ }
+ }, 500); // 延迟0.5秒执行
+ } else {
+ if (testPopWindow != null) {
+ testPopWindow.closePopupWindow();
+ }
+ finish();
+ }
+ }
+ });
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // 只有在拥有相机权限时才启动预览
+ if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA)
+ == PackageManager.PERMISSION_GRANTED) {
+ startTestOpenDebugRegisterFunction();
+ }
+ LogManager.logInfo(TAG, "OXFaceOnlineActivity onResume");
+ }
+
+ private void startTestOpenDebugRegisterFunction() {
+ LogManager.logInfo(TAG, "启动摄像头预览");
+ // 设置摄像头方向
+ if (SingleBaseConfig.getBaseConfig().getRBGCameraId() != -1){
+ CameraPreviewManager.getInstance().setCameraFacing(SingleBaseConfig.getBaseConfig().getRBGCameraId());
+ } else {
+ CameraPreviewManager.getInstance().setCameraFacing(CameraPreviewManager.CAMERA_FACING_FRONT);
+ }
+
+ CameraPreviewManager.getInstance().startPreview(mContext, mAutoCameraPreviewView,
+ PREFER_WIDTH, PERFER_HEIGH, new CameraDataCallback() {
+ @Override
+ public void onGetCameraData(byte[] data, Camera camera, int width, int height) {
+ // 摄像头预览数据进行人脸检测
+ if (isNeedCamera) {
+ FaceSDKManager.getInstance().onDetectCheck(data, null, null,
+ height, width, 1, new FaceDetectCallBack() {
+ @Override
+ public void onFaceDetectCallback(LivenessModel livenessModel) {
+ // 开发模式结果输出
+ checkOpenDebugResult(livenessModel);
+ }
+
+ @Override
+ public void onTip(int code, String msg) {
+ LogManager.logInfo(TAG, "人脸检测提示 - 代码: " + code + ", 消息: " + msg);
+ }
+
+ @Override
+ public void onFaceDetectDarwCallback(LivenessModel livenessModel) {
+ // 绘制人脸框
+ showFrame(livenessModel);
+ }
+ });
+ }
+ }
+ });
+ }
+
+ /**
+ * 绘制人脸框
+ */
+ private void showFrame(final LivenessModel model) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ Canvas canvas = mDrawDetectFaceView.lockCanvas();
+ if (canvas == null) {
+ mDrawDetectFaceView.unlockCanvasAndPost(canvas);
+ return;
+ }
+ if (model == null) {
+ // 清空canvas
+ canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
+ mDrawDetectFaceView.unlockCanvasAndPost(canvas);
+ return;
+ }
+ FaceInfo[] faceInfos = model.getTrackFaceInfo();
+
+ if (faceInfos == null || faceInfos.length == 0) {
+ // 清空canvas
+ canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
+ mDrawDetectFaceView.unlockCanvasAndPost(canvas);
+ return;
+ }
+ canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
+ for (int i = 0 ; i < faceInfos.length;i++) {
+ FaceInfo faceInfo = faceInfos[i];
+
+ rectF.set(FaceOnDrawTexturViewUtil.getFaceRectTwo(faceInfo));
+ // 检测图片的坐标和显示的坐标不一样,需要转换。
+ FaceOnDrawTexturViewUtil.mapFromOriginalRect(rectF,
+ mAutoCameraPreviewView, model.getBdFaceImageInstance());
+ // 人脸框颜色
+ FaceOnDrawTexturViewUtil.drawFaceColor(paint, paintBg, liveStatus, model);
+ // 绘制人脸框
+ FaceOnDrawTexturViewUtil.drawRect(canvas,
+ rectF, paint, 5f, 50f, 25f);
+ }
+ // 清空canvas
+ mDrawDetectFaceView.unlockCanvasAndPost(canvas);
+ }
+ });
+ }
+
+ @Override
+ public void onClick(View view) {
+ int id = view.getId();
+ if (id == R.id.btn_back) {
+ finish();
+ }
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ if (requestCode == CAMERA_PERMISSION_REQUEST_CODE) {
+ if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ LogManager.logInfo(TAG, "相机权限已授予,启动摄像头预览");
+ startTestOpenDebugRegisterFunction();
+ } else {
+ LogManager.logError(TAG, "相机权限被拒绝");
+ Toast.makeText(this, "需要相机权限才能使用人脸识别功能", Toast.LENGTH_LONG).show();
+ finish();
+ }
+ }
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ LogManager.logInfo(TAG, "OXFaceOnlineActivity onDestroy");
+ }
+
+ // ***************开发模式结果输出*************
+ private void checkOpenDebugResult(final LivenessModel livenessModel) {
+ // 当未检测到人脸UI显示
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ layoutCompareStatus.setBackgroundColor(Color.parseColor("#CC000000"));
+ if (livenessModel == null) {
+ liveStatus = false;
+ layoutCompareStatus.setVisibility(View.GONE);
+// mFaceDetectImageView.setImageResource(R.mipmap.ic_image_video);
+// mTvDetect.setText(String.format("检测耗时 :%s ms", 0));
+// mTvLive.setText(String.format("RGB活体检测耗时 :%s ms", 0));
+// mTvLiveScore.setText(String.format("RGB活体检测结果 :%s", false));
+// mTvAllTime.setText(String.format("总耗时 :%s ms", 0));
+ return;
+ }
+
+ BDFaceImageInstance image = livenessModel.getBdFaceImageInstance();
+ if (image != null) {
+// mFaceDetectImageView.setImageBitmap(BitmapUtils.getInstaceBmp(image));
+ float faceArea = livenessModel.getFaceInfo().width * livenessModel.getFaceInfo().height;
+ image.destory();
+
+ // 新增:人脸过小检测
+ if (faceArea < MIN_FACE_AREA) {
+ layoutCompareStatus.setVisibility(View.VISIBLE);
+ textCompareStatus.setTextColor(Color.parseColor("#fec133"));
+ textCompareStatus.setText("请靠近设备");
+ return;
+ }
+ }
+
+ // 模糊结果过滤
+ float blur = livenessModel.getFaceInfo().bluriness;
+ if (blur > SingleBaseConfig.getBaseConfig().getBlur()) {
+ //照片模糊
+ layoutCompareStatus.setVisibility(View.VISIBLE);
+ textCompareStatus.setTextColor(Color.parseColor("#fec133"));
+ textCompareStatus.setText("人脸模糊,请靠近");
+ return;
+ }
+
+ //质量检测
+ if (!livenessModel.isQualityCheck()) {
+ liveStatus = false;
+ } else {
+ // 活体检测逻辑
+ if (SingleBaseConfig.getBaseConfig().isLivingControl()) {
+ if (livenessModel.isRGBLiveStatus()) {
+ liveStatus = true;
+ layoutCompareStatus.setVisibility(View.VISIBLE);
+ textCompareStatus.setTextColor(Color.parseColor("#009874"));
+ textCompareStatus.setText("通过活体检测");
+ } else {
+ liveStatus = false;
+ layoutCompareStatus.setVisibility(View.VISIBLE);
+ textCompareStatus.setTextColor(Color.parseColor("#fec133"));
+ textCompareStatus.setText("未通过活体检测");
+ return;
+ }
+ }
+ }
+
+ FaceInfo faceInfo = livenessModel.getFaceInfo();
+ if (faceInfo.bestImageScore < SingleBaseConfig.getBaseConfig().getBestImageScore()) {
+ layoutCompareStatus.setVisibility(View.VISIBLE);
+ textCompareStatus.setTextColor(Color.parseColor("#fec133"));
+ textCompareStatus.setText("阈值低于" + SingleBaseConfig.getBaseConfig().getBestImageScore());
+ return;
+ }
+
+ //通过检测
+ if (livenessModel != null) {
+ checkResultOnline(livenessModel);//在线人脸检测
+ } else {
+ currentLivenessModel = null;
+ }
+ }
+ });
+ }
+
+ private void checkResultOnline(LivenessModel livenessModel) {
+ this.currentLivenessModel = livenessModel;
+ // 当未检测到人脸UI显示
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ if (livenessModel == null) {
+ return;
+ }
+ String base64img = getFaceImageBase64(currentLivenessModel);
+
+ if (base64img != null) {
+ // Log.i(TAG, "checkResultOnline: " + base64img);
+ Log.i(TAG, "checkResultOnline: Yes! Got a base64img!" );
+ } else {
+ Log.i(TAG, "run:checkResultOnline base64img score too low ");
+ layoutCompareStatus.setVisibility(View.VISIBLE);
+ textCompareStatus.setTextColor(Color.parseColor("#fec133"));
+ textCompareStatus.setText("请重新识别");
+ }
+ }
+ });
+ }
+
+ private String getFaceImageBase64(LivenessModel livenessModel) {
+ if (livenessModel == null) return null;
+ FaceInfo faceInfo = livenessModel.getFaceInfo();
+
+ if (true) { //判定条件
+ BDFaceImageInstance image = livenessModel.getBdFaceImageInstance();
+ Bitmap bitmap = BitmapUtils.getInstaceBmp(image);
+
+ String bitmap_str = BitmapUtils.bitmapToBase64(bitmap);
+ image.destory();
+ return bitmap_str; // 简化实现,实际项目中需要实现 bitmap 转 base64 的功能
+ } else {
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/finance_radius.xml b/app/src/main/res/drawable/finance_radius.xml
new file mode 100644
index 0000000..625c3d6
--- /dev/null
+++ b/app/src/main/res/drawable/finance_radius.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/gate_imageview_radius.xml b/app/src/main/res/drawable/gate_imageview_radius.xml
new file mode 100644
index 0000000..c191f76
--- /dev/null
+++ b/app/src/main/res/drawable/gate_imageview_radius.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/gate_radius_compare.xml b/app/src/main/res/drawable/gate_radius_compare.xml
new file mode 100644
index 0000000..4904079
--- /dev/null
+++ b/app/src/main/res/drawable/gate_radius_compare.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/spot.xml b/app/src/main/res/drawable/spot.xml
new file mode 100644
index 0000000..7820b18
--- /dev/null
+++ b/app/src/main/res/drawable/spot.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_debug.xml b/app/src/main/res/layout/activity_debug.xml
index 3d4a4d9..e016668 100644
--- a/app/src/main/res/layout/activity_debug.xml
+++ b/app/src/main/res/layout/activity_debug.xml
@@ -193,15 +193,14 @@
android:textSize="12sp" />
+ android:textSize="12sp" />