package com.ouxuan.oxface; import androidx.appcompat.app.AppCompatActivity; import android.animation.ObjectAnimator; import android.app.Dialog; import android.content.Context; import android.content.Intent; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.text.InputType; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.Window; import android.widget.ArrayAdapter; import android.widget.EditText; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; import com.bumptech.glide.Glide; import com.bumptech.glide.load.resource.bitmap.CircleCrop; import com.bumptech.glide.request.RequestOptions; import com.google.gson.Gson; import com.ouxuan.oxface.data.DeviceSelectDataManager; import com.ouxuan.oxface.data.LoginDataManager; import com.ouxuan.oxface.device.DeviceUtils; import com.ouxuan.oxface.network.api.PadApiService; import com.ouxuan.oxface.network.api.UserApiService; import com.ouxuan.oxface.network.callback.CompleteApiResponseCallback; import com.ouxuan.oxface.network.callback.NetworkCallback; import com.ouxuan.oxface.network.model.ApiResponse; import com.ouxuan.oxface.network.utils.NetworkUtils; import com.ouxuan.oxface.utils.KeepAliveManager; import com.ouxuan.oxface.utils.AutoStartManager; import com.ouxuan.oxface.utils.LogManager; import com.ouxuan.oxface.utils.UtilCodeHelper; import org.json.JSONException; import org.json.JSONObject; public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; private EditText editTextUsername; private EditText editTextPassword; private View buttonLogin; private ImageView imageViewPasswordToggle; private Toast currentToast; // 用于管理Toast显示状态 private boolean isPasswordVisible = false; // 密码显示状态 private LoginDataManager loginDataManager; // 登录数据管理器 private DeviceSelectDataManager deviceSelectDataManager; // 设备选择数据管理器 private KeepAliveManager keepAliveManager; // 保持活跃管理器 private AutoStartManager autoStartManager; // 自启动管理器 private Dialog currentDialog; // 用于跟踪当前显示的Dialog,防止WindowLeaked错误 // 添加自动启动状态变量 private boolean isAutoStart = false; @Override protected void onCreate(Bundle savedInstanceState) { // 在setContentView之前切换到正常主题,解决白屏问题 setTheme(R.style.Theme_OxFaceLogin); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 隐藏ActionBar以获得全屏效果 if (getSupportActionBar() != null) { getSupportActionBar().hide(); } // 初始化视图组件 initViews(); // 初始化登录数据管理器 loginDataManager = LoginDataManager.getInstance(this); // 初始化设备选择数据管理器 deviceSelectDataManager = DeviceSelectDataManager.getInstance(this); // 初始化保持活跃管理器并启动(用于24小时无人值守) keepAliveManager = KeepAliveManager.getInstance(this); keepAliveManager.startKeepAlive(this); // 初始化自启动管理器并检查权限 autoStartManager = AutoStartManager.getInstance(this); autoStartManager.checkAndRequestAutoStartPermission(); // 记录应用启动 LogManager.logOperation("MainActivity", "主界面已初始化,开始24小时无人值守模式"); // 检查是否为自启动 checkAutoStartStatus(); // 检查是否可以自动登录 checkAutoLogin(); // 设置登录按钮点击事件 setupLoginButton(); // 设置按钮触摸动画 setupButtonAnimation(); // 设置密码显示/隐藏切换 setupPasswordToggle(); // 设置长按登录按钮显示日志路径信息(调试功能) setupLogPathDebug(); //切换第六批设备(0-5) switchCameraByDeviceType(5); } /** * 初始化视图组件 */ private void initViews() { editTextUsername = findViewById(R.id.editTextUsername); editTextPassword = findViewById(R.id.editTextPassword); buttonLogin = findViewById(R.id.buttonLogin); imageViewPasswordToggle = findViewById(R.id.imageViewPasswordToggle); } /** * 检查自启动状态 */ private void checkAutoStartStatus() { Intent intent = getIntent(); if (intent != null) { isAutoStart = intent.getBooleanExtra("auto_start", false); if (isAutoStart) { String bootReason = intent.getStringExtra("boot_reason"); String startSource = intent.getStringExtra("start_source"); long bootTime = intent.getLongExtra("boot_time", 0); long serviceStartTime = intent.getLongExtra("service_start_time", 0); LogManager.logOperation("MainActivity", "检测到自动启动:" + (bootReason != null ? bootReason : "无") + ", 来源:" + (startSource != null ? startSource : "直接启动")); // 显示自启动提示 if ("system_reboot".equals(bootReason)) { showToast("系统重启后自动恢复,24小时无人值守模式已启动"); } else { showToast("应用自动启动成功"); } // 清除Intent中的自启动标识,防止重复处理 intent.removeExtra("auto_start"); intent.removeExtra("boot_reason"); intent.removeExtra("start_source"); intent.removeExtra("boot_time"); intent.removeExtra("service_start_time"); } } } /** * 检查是否可以自动登录 */ private void checkAutoLogin() { if (loginDataManager.canAutoLogin()) { android.util.Log.d("MainActivity", "检测到有效的本地登录数据,尝试自动登录, isAutoStart: " + isAutoStart); // 显示自动登录提示 showToast("检测到登录信息,正在自动登录..."); // 延迟一下显示登录成功弹框,给用户看到自动登录的提示 new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { @Override public void run() { // 检查Activity是否仍然有效 if (!isFinishing() && !isDestroyed()) { if (loginDataManager.isLoggedIn()) { android.util.Log.d("MainActivity", "自动登录成功!isAutoStart: " + isAutoStart); showToast("自动登录成功!"); // isAutoStart = true; // 更新isAutoStart字段为true isAutoStart = true; showLoginSuccessDialog(loginDataManager.getLoginData()); } else { android.util.Log.w("MainActivity", "自动登录失败,本地数据可能已失效"); showToast("自动登录失败,请手动登录"); // 清除可能已失效的登录数据 loginDataManager.clearLoginData(); } } } }, 1000); // 延迟1秒 } else { android.util.Log.d("MainActivity", "无有效本地登录数据,需要手动登录"); } } private void setupLoginButton() { buttonLogin.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String username = editTextUsername.getText().toString().trim(); String password = editTextPassword.getText().toString().trim(); // 在测试环境下,如果用户名和密码都为空,自动填充默认账号 if (isTestEnvironment() && username.isEmpty() && password.isEmpty()) { username = "00167"; password = "123456"; // 更新输入框显示 editTextUsername.setText(username); editTextPassword.setText(password); // 显示提示信息 showToast("测试环境:已自动填充默认账号"); android.util.Log.d("MainActivity", "Test environment: Auto-filled default credentials"); } if (validateInput(username, password)) { performLogin(username, password); } } }); } private void setupButtonAnimation() { buttonLogin.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // 按下时缩小 ObjectAnimator scaleDownX = ObjectAnimator.ofFloat(v, "scaleX", 0.95f); ObjectAnimator scaleDownY = ObjectAnimator.ofFloat(v, "scaleY", 0.95f); scaleDownX.setDuration(100); scaleDownY.setDuration(100); scaleDownX.start(); scaleDownY.start(); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: // 释放时恢复 ObjectAnimator scaleUpX = ObjectAnimator.ofFloat(v, "scaleX", 1.0f); ObjectAnimator scaleUpY = ObjectAnimator.ofFloat(v, "scaleY", 1.0f); scaleUpX.setDuration(100); scaleUpY.setDuration(100); scaleUpX.start(); scaleUpY.start(); break; } return false; // 返回false以确保onClick事件仍然被触发 } }); } private boolean validateInput(String username, String password) { // if (username.isEmpty()) { // showToast("请输入登录账号"); // editTextUsername.requestFocus(); // return false; // } // if (password.isEmpty()) { // showToast("请输入密码"); // editTextPassword.requestFocus(); // return false; // } // if (password.length() < 6) { // showToast("密码长度至少6位"); // editTextPassword.requestFocus(); // return false; // } return true; } /** * 判断是否为测试环境 * @return true 如果是测试环境 */ private boolean isTestEnvironment() { // 根据 NetworkConfig 中的 BASE_URL 判断是否为测试环境 return com.ouxuan.oxface.network.NetworkConfig.BASE_URL.contains("testmanager"); } private void performLogin(String username, String password) { // 使用DeviceUtils获取设备ID进行真实的API调用 String deviceId = DeviceUtils.getFormattedDeviceId(this); // 打印设备信息到日志(便于调试) DeviceUtils.logDeviceInfo(this); NetworkUtils.padLogin(username, password, deviceId, new NetworkCallback() { @Override public void onStart() { // 显示loading状态 showToast("正在登录..."); } @Override public void onSuccess(PadApiService.PadLoginResponse data) { // 登录成功,使用LoginDataManager保存登录数据 android.util.Log.d("MainActivity", "Login success - data: " + (data != null ? data.toString() : "null")); if (data != null) { android.util.Log.d("MainActivity", "Token: " + data.getToken()); android.util.Log.d("MainActivity", "Name: " + data.getName()); android.util.Log.d("MainActivity", "Brand ID: " + data.getBrandId()); } // 使用LoginDataManager保存登录数据 loginDataManager.saveLoginData(data); // 打印存储的data android.util.Log.d("MainActivity", "Login Data: " + data.toString()); // 检查Activity是否仍然有效再显示Dialog if (!isFinishing() && !isDestroyed()) { // 显示登录成功弹框,传入登录数据 showToast("登录成功!"); showLoginSuccessDialog(data); } } @Override public void onError(int errorCode, String errorMessage) { // 登录失败,打印详细错误日志并显示错误信息 android.util.Log.e("MainActivity", "=== 登录接口请求异常 ==="); android.util.Log.e("MainActivity", "Error Code: " + errorCode); android.util.Log.e("MainActivity", "Error Message: " + errorMessage); android.util.Log.e("MainActivity", "==========================="); // 根据错误代码显示不同的提示信息 String displayMessage; switch (errorCode) { case 502: displayMessage = "服务器暂时不可用,请稍后再试"; break; case 400: displayMessage = "请求参数错误"; break; case 401: displayMessage = "用户名或密码错误"; break; case 403: displayMessage = "访问被禁止"; break; case 404: displayMessage = "登录接口未找到"; break; case 500: displayMessage = "服务器内部错误"; break; case 503: displayMessage = "服务暂时不可用"; break; case 504: displayMessage = "网关超时"; break; default: // 如果errorMessage包含具体的错误信息,则显示具体信息,否则显示通用信息 if (errorMessage != null && !errorMessage.isEmpty() && !errorMessage.equals("请求失败: ")) { displayMessage = errorMessage; } else { displayMessage = "登录失败,请检查网络连接"; } break; } // 显示Toast错误信息 showToast(displayMessage); } @Override public void onComplete() { // 请求完成 } }); } /** * 显示Toast消息,确保只显示最新的消息 * @param message 要显示的消息 */ private void showToast(String message) { // 如果之前有Toast正在显示,先取消它 if (currentToast != null) { currentToast.cancel(); } // 创建新的Toast并显示 currentToast = Toast.makeText(this, message, Toast.LENGTH_SHORT); currentToast.show(); } /** * 设置密码显示/隐藏切换功能 */ private void setupPasswordToggle() { imageViewPasswordToggle.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { togglePasswordVisibility(); } }); } /** * 切换密码的显示/隐藏状态 */ private void togglePasswordVisibility() { if (isPasswordVisible) { // 当前是显示状态,切换为隐藏 editTextPassword.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD); imageViewPasswordToggle.setImageResource(R.drawable.ic_eye_closed); isPasswordVisible = false; } else { // 当前是隐藏状态,切换为显示 editTextPassword.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD); imageViewPasswordToggle.setImageResource(R.drawable.ic_eye_open); isPasswordVisible = true; } // 保持光标在文本末尾 editTextPassword.setSelection(editTextPassword.getText().length()); } /** * 显示登录成功弹框 * @param loginData 登录响应数据 */ private void showLoginSuccessDialog(PadApiService.PadLoginResponse loginData) { android.util.Log.d("MainActivity", "显示登录成功弹框, isAutoStart: " + isAutoStart); // 创建自定义弹框 Dialog dialog = new Dialog(this); currentDialog = dialog; // 保存Dialog引用以防止WindowLeaked错误 dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); dialog.setContentView(R.layout.dialog_login_success); // 设置弹框背景透明并调整尺寸 if (dialog.getWindow() != null) { dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); // 设置弹框宽度为屏幕宽度的85%,确保在屏幕中自然居中 android.view.WindowManager.LayoutParams layoutParams = dialog.getWindow().getAttributes(); android.util.DisplayMetrics displayMetrics = new android.util.DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); int screenWidth = displayMetrics.widthPixels; layoutParams.width = (int) (screenWidth * 0.85); // 设置为屏幕宽度的85% layoutParams.height = android.view.WindowManager.LayoutParams.WRAP_CONTENT; dialog.getWindow().setAttributes(layoutParams); } // 初始化弹框的组件 Spinner spinnerPlatform = dialog.findViewById(R.id.spinnerPlatform); View buttonEnter = dialog.findViewById(R.id.buttonEnter); View buttonClose = dialog.findViewById(R.id.buttonClose); TextView textViewStoreName = dialog.findViewById(R.id.textViewStoreName); ImageView imageViewStoreLogo = dialog.findViewById(R.id.imageViewStoreLogo); // 更新店铺信息 if (loginData != null) { // 更新店铺名称 if (loginData.getName() != null && !loginData.getName().isEmpty()) { textViewStoreName.setText("尊敬的" + loginData.getName()); } // 加载店铺 Logo(如果有的话) if (loginData.getLogo() != null && !loginData.getLogo().isEmpty()) { android.util.Log.d("MainActivity", "Loading store logo from: " + loginData.getLogo()); // 使用 Glide 加载网络图片,设置圆形裁剪和默认图片 Glide.with(this) .load(loginData.getLogo()) .apply(RequestOptions.bitmapTransform(new CircleCrop())) .placeholder(R.drawable.ic_warriors_logo) // 加载中显示默认图片 .error(R.drawable.ic_warriors_logo) // 加载失败显示默认图片 .into(imageViewStoreLogo); } else { // 如果没有 Logo URL,使用默认图片 imageViewStoreLogo.setImageResource(R.drawable.ic_warriors_logo); } } // 设置关闭按钮点击事件 buttonClose.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dialog.dismiss(); currentDialog = null; // 清除引用 } }); // 设置平台选择下拉框的数据 loadPadList(dialog, spinnerPlatform); // 设置进入使用按钮点击事件 buttonEnter.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int selectedPosition = spinnerPlatform.getSelectedItemPosition(); if (selectedPosition == 0) { showToast("请选择设备"); } else { // 获取选中的设备名称 String selectedPlatform = spinnerPlatform.getSelectedItem().toString(); // 显示loading动画 showLoadingInDialog(dialog, buttonEnter, selectedPlatform); } } }); // 显示弹框 dialog.show(); } /** * 在弹框中显示loading动画 * @param dialog 弹框实例 * @param buttonEnter 进入按钮 * @param selectedPlatform 选中的平台 */ private void showLoadingInDialog(Dialog dialog, View buttonEnter, String selectedPlatform) { // 禁用按钮防止重复点击 buttonEnter.setEnabled(false); // 禁用设置平台选择下拉框 Spinner spinnerPlatform = dialog.findViewById(R.id.spinnerPlatform); spinnerPlatform.setEnabled(false); // 保存原始按钮文字 TextView buttonText = (TextView) buttonEnter; String originalText = buttonText.getText().toString(); // 显示loading文字 buttonText.setText("正在进入..."); // 注意:这里不再使用延时,而是通过设备选择和SDK初始化流程来控制 // 实际的进入操作会在selectPadAndEnter方法中处理 } /** * 获取用户ID * @return 用户ID */ private String getUserId() { return loginDataManager.getUserId(); } /** * 获取认证Token(统一认证方式) * @return Token字符串 */ private String getAuthToken() { return loginDataManager.getAuthToken(); } /** * 加载Pad列表数据 * @param dialog 弹框实例 * @param spinner 下拉框组件 */ private void loadPadList(Dialog dialog, Spinner spinner) { android.util.Log.d("MainActivity", "开始加载Pad列表, isAutoStart: " + isAutoStart); // 首先设置默认的加载中选项 String[] loadingItems = {"正在加载设备列表..."}; ArrayAdapter loadingAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, loadingItems); loadingAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(loadingAdapter); // 调用API获取Pad列表,传入登录时获取的stadium_id、device_id和token if (loginDataManager.isLoggedIn()) { int stadiumId = loginDataManager.getStadiumId(); String token = loginDataManager.getAuthToken(); String deviceId = DeviceUtils.getFormattedDeviceId(this); android.util.Log.d("MainActivity", "Loading pad list with stadium_id: " + stadiumId + ", device_id: " + deviceId + ", token: " + (token != null ? "present" : "null")); NetworkUtils.getPadList(stadiumId, deviceId, token, new NetworkCallback() { @Override public void onStart() { // 加载开始 } @Override public void onSuccess(PadApiService.PadListResponse data) { android.util.Log.d("MainActivity", "Pad列表加载成功, isAutoStart: " + isAutoStart); // 加载成功,更新下拉框数据 java.util.List padList = data.getPads(); // 使用getPads()而不是getPadList() java.util.List padNames = new java.util.ArrayList<>(); padNames.add("请选择设备"); // 默认选项 if (padList != null && !padList.isEmpty()) { for (PadApiService.PadInfo padInfo : padList) { // 使用hardware_name和status字段 String displayName = padInfo.getHardwareName(); if (padInfo.getStatus() != null && !padInfo.getStatus().equals("unknown")) { displayName += " (" + padInfo.getStatus() + ")"; } padNames.add(displayName); } android.util.Log.d("MainActivity", "成功加载 " + padList.size() + " 个设备"); android.util.Log.d("MainActivity", "店铺Logo: " + data.getLogo()); android.util.Log.d("MainActivity", "店铺名称: " + data.getName()); } else { padNames.add("暂无可用设备"); android.util.Log.w("MainActivity", "服务器返回的设备列表为空"); } // 更新Spinner数据 ArrayAdapter adapter = new ArrayAdapter<>(MainActivity.this, android.R.layout.simple_spinner_item, padNames); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(adapter); // 检查是否为自动登录且只有一个真实设备,如果是则自动选择 android.util.Log.d("MainActivity", "检查自动选择条件: isAutoStart=" + isAutoStart + ", padList.size()=" + (padList != null ? padList.size() : 0) + ", padList=" + (padList != null ? padList.toString() : "null")); if (isAutoStart && padList != null && padList.size() == 1) { // 清除padNames.add("请选择设备"); android.util.Log.d("MainActivity", "满足自动选择条件,开始自动选择设备"); // 自动选择唯一设备(忽略"请选择设备"这类提示项) autoSelectSingleDevice(dialog, padList.get(0)); } else { android.util.Log.d("MainActivity", "不满足自动选择条件,显示设备选择界面"); // 更新进入按钮的点击事件,传入真实的Pad数据 updateEnterButtonClickListener(dialog, padList); } } @Override public void onError(int errorCode, String errorMessage) { // 加载失败,打印详细错误日志并显示错误信息 android.util.Log.e("MainActivity", "=== 获取设备列表接口请求异常 ==="); android.util.Log.e("MainActivity", "Error Code: " + errorCode); android.util.Log.e("MainActivity", "Error Message: " + errorMessage); android.util.Log.e("MainActivity", "================================"); // 显示错误信息 String[] errorItems = {"加载失败,请重试"}; ArrayAdapter errorAdapter = new ArrayAdapter<>(MainActivity.this, android.R.layout.simple_spinner_item, errorItems); errorAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(errorAdapter); showToast("获取设备列表失败: " + errorMessage); } }); } else { // 如果没有登录数据,显示错误 String[] errorItems = {"登录数据丢失,请重新登录"}; ArrayAdapter errorAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, errorItems); errorAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(errorAdapter); showToast("登录数据丢失,请重新登录"); } } /** * 自动选择唯一设备并进入使用 * @param dialog 弹框实例 * @param padInfo 唯一的Pad信息 */ private void autoSelectSingleDevice(Dialog dialog, PadApiService.PadInfo padInfo) { android.util.Log.d("MainActivity", "自动登录且只有一个设备,自动选择设备: " + padInfo.getHardwareName()); showToast("自动选择设备: " + padInfo.getHardwareName()); // 获取进入按钮并设置为加载状态 View buttonEnter = dialog.findViewById(R.id.buttonEnter); if (buttonEnter != null) { // buttonEnter.setEnabled(false); TextView buttonText = (TextView) buttonEnter; buttonText.setText("正在进入..."); } // 直接调用选择Pad并进入的方法 selectPadAndEnter(dialog, buttonEnter, padInfo); } /** * 更新进入按钮的点击事件 * @param dialog 弹框实例 * @param padList Pad列表数据 */ private void updateEnterButtonClickListener(Dialog dialog, java.util.List padList) { View buttonEnter = dialog.findViewById(R.id.buttonEnter); Spinner spinnerPlatform = dialog.findViewById(R.id.spinnerPlatform); buttonEnter.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int selectedPosition = spinnerPlatform.getSelectedItemPosition(); if (selectedPosition == 0) { showToast("请选择设备"); } else if (padList != null && selectedPosition <= padList.size()) { // 获取选中的Pad信息 PadApiService.PadInfo selectedPad = padList.get(selectedPosition - 1); // 减1因为第0个是"请选择设备" // 调用Pad选择API selectPadAndEnter(dialog, buttonEnter, selectedPad); } else { showToast("请选择有效的设备"); } } }); } /** * 选择Pad并进入使用 * @param dialog 弹框实例 * @param buttonEnter 进入按钮 * @param selectedPad 选中的Pad信息 */ private void selectPadAndEnter(Dialog dialog, View buttonEnter, PadApiService.PadInfo selectedPad) { System.out.println("MainActivity: selectPadAndEnter called"); System.out.println("MainActivity: selectPadAndEnter thread: " + Thread.currentThread().getName()); android.util.Log.d("MainActivity", "selectPadAndEnter called"); android.util.Log.d("MainActivity", "selectPadAndEnter thread: " + Thread.currentThread().getName()); // 禁用按钮防止重复点击 buttonEnter.setEnabled(false); // 保存原始按钮文字 TextView buttonText = (TextView) buttonEnter; String originalText = buttonText.getText().toString(); // 显示loading文字 buttonText.setText("已自动选择设备..."); // 获取所需参数 int hardwareId = selectedPad.getHardwareId(); String deviceId = DeviceUtils.getFormattedDeviceId(this); String token = getAuthToken(); // 输出调试日志 android.util.Log.d("MainActivity", "=== 设备选择参数 ==="); android.util.Log.d("MainActivity", "Hardware ID: " + hardwareId); android.util.Log.d("MainActivity", "Device ID: " + deviceId); android.util.Log.d("MainActivity", "token: " + token); android.util.Log.d("MainActivity", "Token: " + (token != null && !token.isEmpty() ? "present" : "null")); android.util.Log.d("MainActivity", "Selected Pad Name: " + selectedPad.getHardwareName()); android.util.Log.d("MainActivity", "=========================="); // 添加更多调试信息 System.out.println("MainActivity: About to call selectPadWithFullResponse"); System.out.println("MainActivity: hardwareId: " + hardwareId); System.out.println("MainActivity: deviceId: " + deviceId); System.out.println("MainActivity: token: " + (token != null ? "present" : "null")); System.out.println("MainActivity: selectedPad: " + (selectedPad != null ? selectedPad.getHardwareName() : "null")); // 调用Pad选择API(使用新的API格式,支持完整API响应) NetworkUtils.selectPadWithFullResponse(hardwareId, deviceId, token, new CompleteApiResponseCallback() { @Override public void onSuccessWithFullResponse(ApiResponse apiResponse) { // 选择成功,保存完整的API响应数据(code和data) showToast("进入 " + selectedPad.getHardwareName() + " 成功!"); android.util.Log.d("MainActivity", "=== onSuccessWithFullResponse ==="); // 保存完整的API响应数据到本地进行持久化保存 deviceSelectDataManager.saveCompleteApiResponse(apiResponse, selectedPad); // 记录操作日志 LogManager.logOperation("MainActivity", "设备选择成功: " + selectedPad.getHardwareName() + ", Hardware ID: " + hardwareId + ", API Code: " + apiResponse.getCode() + ", Data Size: " + (apiResponse.getData() != null ? "present" : "null")); // 输出保存的数据信息用于调试 android.util.Log.d("MainActivity", "=== 保存的API响应数据 ==="); android.util.Log.d("MainActivity", "API Code: " + deviceSelectDataManager.getApiResponseCode()); android.util.Log.d("MainActivity", "API Data JSON长度: " + deviceSelectDataManager.getApiResponseDataJson().length()); android.util.Log.d("MainActivity", "API Message: " + deviceSelectDataManager.getApiResponseMessage()); android.util.Log.d("MainActivity", "==============================="); // 添加成功信息输出到日志 LogManager.logInfo("MainActivity", "设备选择成功: " + selectedPad.getHardwareName() + ", Hardware ID: " + hardwareId + ", API Code: " + apiResponse.getCode()); // 新增:调用获取小程序码接口和上传人脸小程序码接口 // 使用计数器确保两个请求都完成后再进入人脸识别界面 final int[] completedRequests = {0}; final Object lock = new Object(); // 完成一个请求的回调 Runnable onOneRequestComplete = new Runnable() { @Override public void run() { synchronized (lock) { completedRequests[0]++; android.util.Log.d("MainActivity", "请求完成计数: " + completedRequests[0] + "/2"); // 当两个请求都完成时,进入人脸识别界面 if (completedRequests[0] >= 2) { android.util.Log.d("MainActivity", "所有请求完成,准备进入人脸识别界面"); initializeFaceSDKIfNeeded(dialog, buttonEnter, buttonText, originalText); } } } }; // 调用获取小程序码接口 fetchAndSaveMiniQrcode(token, hardwareId, dialog, buttonEnter, buttonText, originalText, onOneRequestComplete); // 调用获取上传人脸小程序码接口 fetchAndSaveUploadFaceMiniQrcode(token, hardwareId, dialog, buttonEnter, buttonText, originalText, onOneRequestComplete); } @Override public void onError(int errorCode, String errorMessage) { // 选择失败,打印详细错误日志并显示错误信息 android.util.Log.e("MainActivity", "=== 设备选择接口请求异常 ==="); android.util.Log.e("MainActivity", "Error Code: " + errorCode); android.util.Log.e("MainActivity", "Error Message: " + errorMessage); android.util.Log.e("MainActivity", "Hardware ID: " + hardwareId); android.util.Log.e("MainActivity", "Device ID: " + deviceId); android.util.Log.e("MainActivity", "Selected Pad: " + (selectedPad != null ? selectedPad.getHardwareName() : "null")); android.util.Log.e("MainActivity", "=============================="); // 显示错误信息 showToast("选择设备失败: 当前设备ID: " + deviceId + errorMessage); // 恢复按钮状态 buttonEnter.setEnabled(true); buttonText.setText(originalText); } @Override public void onException(Throwable throwable) { // 异常处理 showToast("选择设备时发生异常: " + throwable.getMessage()); // 恢复按钮状态 buttonEnter.setEnabled(true); buttonText.setText(originalText); } @Override public void onComplete() { // 请求完成 android.util.Log.d("MainActivity", "设备选择请求完成"); } }); System.out.println("MainActivity: selectPadWithFullResponse method called"); System.out.println("MainActivity: After calling selectPadWithFullResponse, thread: " + Thread.currentThread().getName()); } /** * 检查是否需要初始化人脸SDK并在需要时执行初始化 */ private void initializeFaceSDKIfNeeded(Dialog dialog, View buttonEnter, TextView buttonText, String originalText) { try { // 检查是否有人脸识别许可证 if (deviceSelectDataManager.hasFaceLicense()) { String faceLicense = deviceSelectDataManager.getFaceLicense(); String logMessage = "检测到人脸识别许可证,开始初始化人脸SDK,许可证长度: " + (faceLicense != null ? faceLicense.length() : 0); android.util.Log.d("MainActivity", logMessage); LogManager.logInfo("FaceSDK", logMessage); // 在后台线程中初始化人脸SDK new Thread(new Runnable() { @Override public void run() { initializeFaceSDK(faceLicense, dialog, buttonEnter, buttonText, originalText); } }).start(); } else { String logMessage = "未检测到有效的人脸识别许可证,跳过人脸SDK初始化,直接进入人脸识别界面"; android.util.Log.w("MainActivity", logMessage); LogManager.logWarning("FaceSDK", logMessage); // 没有人脸识别许可证,直接进入人脸识别界面 runOnUiThread(new Runnable() { @Override public void run() { enterFaceRecognitionActivity(dialog); } }); } } catch (Exception e) { String logMessage = "检查人脸SDK初始化条件时发生异常: " + e.getMessage(); android.util.Log.e("MainActivity", logMessage, e); LogManager.logError("FaceSDK", logMessage, e); // 即使发生异常,也要确保弹框被关闭 if (dialog != null && dialog.isShowing()) { dialog.dismiss(); } currentDialog = null; // 清除引用 } } /** * 初始化人脸SDK * @param faceLicense 人脸识别许可证 */ private void initializeFaceSDK(String faceLicense, Dialog dialog, View buttonEnter, TextView buttonText, String originalText) { try { String logMessage = "开始人脸SDK初始化流程..."; 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(); // 检查设备是否已经授权 if (faceSDKManager.initStatus == com.baidu.idl.face.main.finance.manager.FaceSDKManager.SDK_INIT_SUCCESS || faceSDKManager.initStatus == com.baidu.idl.face.main.finance.manager.FaceSDKManager.SDK_MODEL_LOAD_SUCCESS) { String alreadyAuthorizedMessage = "设备已授权,无需重复授权"; android.util.Log.d("MainActivity", alreadyAuthorizedMessage); LogManager.logInfo("FaceSDK", alreadyAuthorizedMessage); // 获取并记录授权信息 String licenseData = faceSDKManager.getLicenseData(this); LogManager.logInfo("FaceSDK", "设备授权有效期至: " + licenseData); // 直接进入人脸识别界面 runOnUiThread(new Runnable() { @Override public void run() { showToast("设备已授权"); enterFaceRecognitionActivity(dialog); } }); return; } // 创建同步锁以等待初始化完成 final Object initLock = new Object(); final boolean[] initCompleted = {false}; final boolean[] initSuccess = {false}; // 在主线程中执行初始化 runOnUiThread(new Runnable() { @Override public void run() { faceSDKManager.init(MainActivity.this, faceLicense, new com.baidu.idl.face.main.finance.listener.SdkInitListener() { @Override public void initStart() { String logMessage = "人脸SDK授权初始化开始..."; android.util.Log.d("MainActivity", logMessage); LogManager.logInfo("FaceSDK", logMessage); } @Override public void initLicenseSuccess() { String logMessage = "人脸SDK授权成功"; android.util.Log.d("MainActivity", logMessage); LogManager.logInfo("FaceSDK", logMessage); // 授权成功后继续初始化模型 initFaceModels(faceSDKManager, initLock, initCompleted, initSuccess, dialog, buttonEnter, buttonText, originalText); } @Override public void initLicenseFail(int errorCode, String msg) { String logMessage = "人脸SDK授权失败 - 错误码: " + errorCode + ", 错误信息: " + msg; android.util.Log.e("MainActivity", logMessage); LogManager.logError("FaceSDK", logMessage); synchronized (initLock) { initCompleted[0] = true; initSuccess[0] = false; initLock.notifyAll(); } // 授权失败时,仍然进入人脸识别界面 runOnUiThread(new Runnable() { @Override public void run() { enterFaceRecognitionActivity(dialog); } }); } @Override public void initModelSuccess() { // 这个回调在init方法中不会触发 } @Override public void initModelFail(int errorCode, String msg) { // 这个回调在init方法中不会触发 } }); } }); // 等待初始化完成(最多等待30秒) synchronized (initLock) { if (!initCompleted[0]) { try { initLock.wait(30000); // 等待最多30秒 } catch (InterruptedException e) { logMessage = "人脸SDK初始化等待被中断: " + e.getMessage(); android.util.Log.e("MainActivity", logMessage); LogManager.logError("FaceSDK", logMessage); } } } // 检查初始化结果 if (initSuccess[0]) { logMessage = "人脸SDK初始化成功"; android.util.Log.d("MainActivity", logMessage); LogManager.logInfo("FaceSDK", logMessage); runOnUiThread(new Runnable() { @Override public void run() { showToast("人脸SDK初始化成功"); // 进入人脸识别界面 enterFaceRecognitionActivity(dialog); } }); } else { logMessage = "人脸SDK初始化失败,但仍进入人脸识别界面"; android.util.Log.e("MainActivity", logMessage); LogManager.logError("FaceSDK", logMessage); runOnUiThread(new Runnable() { @Override public void run() { showToast("人脸SDK初始化失败,但仍进入人脸识别界面"); // 即使初始化失败,也进入人脸识别界面 enterFaceRecognitionActivity(dialog); } }); } } catch (Exception e) { String logMessage = "初始化人脸SDK时发生异常: " + e.getMessage(); android.util.Log.e("MainActivity", logMessage, e); LogManager.logError("FaceSDK", logMessage, e); runOnUiThread(new Runnable() { @Override public void run() { showToast("人脸SDK初始化异常: " + e.getMessage()); // 发生异常时,仍然进入人脸识别界面 enterFaceRecognitionActivity(dialog); } }); } } /** * 初始化人脸模型 * @param faceSDKManager FaceSDKManager实例 * @param initLock 初始化同步锁 * @param initCompleted 初始化完成标志 * @param initSuccess 初始化成功标志 */ private void initFaceModels(com.baidu.idl.face.main.finance.manager.FaceSDKManager faceSDKManager, Object initLock, boolean[] initCompleted, boolean[] initSuccess, Dialog dialog, View buttonEnter, TextView buttonText, String originalText) { try { String logMessage = "开始初始化人脸模型..."; 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() { String logMessage = "人脸模型初始化开始..."; android.util.Log.d("MainActivity", logMessage); LogManager.logInfo("FaceSDK", logMessage); } @Override public void initLicenseSuccess() { // 授权已在initFaceSDK中处理 } @Override public void initLicenseFail(int errorCode, String msg) { // 授权已在initFaceSDK中处理 } @Override public void initModelSuccess() { String logMessage = "人脸SDK模型初始化成功"; android.util.Log.d("MainActivity", logMessage); LogManager.logInfo("FaceSDK", logMessage); synchronized (initLock) { initCompleted[0] = true; initSuccess[0] = true; initLock.notifyAll(); } // 模型初始化成功后,进入人脸识别界面 runOnUiThread(new Runnable() { @Override public void run() { enterFaceRecognitionActivity(dialog); } }); } @Override public void initModelFail(int errorCode, String msg) { String logMessage = "人脸SDK模型初始化失败 - 错误码: " + errorCode + ", 错误信息: " + msg; android.util.Log.e("MainActivity", logMessage); LogManager.logError("FaceSDK", logMessage); synchronized (initLock) { initCompleted[0] = true; initSuccess[0] = false; initLock.notifyAll(); } // 即使模型初始化失败,也进入人脸识别界面 runOnUiThread(new Runnable() { @Override public void run() { enterFaceRecognitionActivity(dialog); } }); } }); } catch (Exception e) { String logMessage = "初始化人脸模型时发生异常: " + e.getMessage(); android.util.Log.e("MainActivity", logMessage, e); LogManager.logError("FaceSDK", logMessage, e); synchronized (initLock) { initCompleted[0] = true; initSuccess[0] = false; initLock.notifyAll(); } // 发生异常时,仍然进入人脸识别界面 runOnUiThread(new Runnable() { @Override public void run() { enterFaceRecognitionActivity(dialog); } }); } } /** * 进入人脸识别界面 * @param dialog 弹框实例 */ private void enterFaceRecognitionActivity(Dialog dialog) { try { String logMessage = "准备进入人脸识别界面"; android.util.Log.d("MainActivity", logMessage); LogManager.logInfo("FaceSDK", logMessage); // 检查人脸SDK状态 com.baidu.idl.face.main.finance.manager.FaceSDKManager faceSDKManager = com.baidu.idl.face.main.finance.manager.FaceSDKManager.getInstance(); String sdkStatus = "SDK状态 - 授权: " + faceSDKManager.initStatus + ", 模型: " + faceSDKManager.initModelSuccess; android.util.Log.d("MainActivity", sdkStatus); LogManager.logInfo("FaceSDK", sdkStatus); // 关闭弹框 if (dialog != null && dialog.isShowing()) { dialog.dismiss(); } currentDialog = null; // 清除引用 // 跳转到人脸识别界面 Intent intent = new Intent(MainActivity.this, OXFaceOnlineActivity.class); startActivity(intent); logMessage = "已启动人脸识别界面"; android.util.Log.d("MainActivity", logMessage); LogManager.logInfo("FaceSDK", logMessage); } catch (Exception e) { String logMessage = "进入人脸识别界面时发生异常: " + e.getMessage(); android.util.Log.e("MainActivity", logMessage, e); LogManager.logError("FaceSDK", logMessage, e); // 即使发生异常,也要确保弹框被关闭 if (dialog != null && dialog.isShowing()) { dialog.dismiss(); } currentDialog = null; // 清除引用 } } /** * 根据设备类型切换摄像头配置 * @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(); // 确保保持活跃功能正常运行 if (keepAliveManager != null && !keepAliveManager.isKeepingAlive()) { keepAliveManager.startKeepAlive(this); LogManager.logOperation("MainActivity", "恢复保持活跃状态"); } } @Override protected void onPause() { super.onPause(); // 24小时无人值守模式下,不停止保持活跃功能 LogManager.logDebug("MainActivity", "应用进入后台,但保持活跃状态继续运行"); } @Override protected void onDestroy() { super.onDestroy(); // 关闭任何正在显示的Dialog以防止WindowLeaked错误 if (currentDialog != null && currentDialog.isShowing()) { currentDialog.dismiss(); currentDialog = null; } LogManager.logOperation("MainActivity", "主界面正在销毁"); // 只在应用真正退出时才停止保持活跃 if (isFinishing() && keepAliveManager != null) { keepAliveManager.stopKeepAlive(this); LogManager.logOperation("MainActivity", "应用退出,停止保持活跃功能"); } } /** * 获取并保存小程序码 * @param token 访问令牌 * @param hardwareId 硬件ID * @param dialog 弹框实例 * @param buttonEnter 进入按钮 * @param buttonText 按钮文字视图 * @param originalText 原始按钮文字 * @param onComplete 请求完成回调 */ private void fetchAndSaveMiniQrcode(String token, int hardwareId, Dialog dialog, View buttonEnter, TextView buttonText, String originalText, Runnable onComplete) { // 调用获取小程序码接口 NetworkUtils.miniQrcode(token, hardwareId, new NetworkCallback() { @Override public void onStart() { // 开始请求 android.util.Log.d("MainActivity", "开始请求小程序码"); } @Override public void onSuccess(PadApiService.MiniQrcodeResponse data) { // 获取小程序码成功 if (data != null && data.getQrcodeUrl() != null && !data.getQrcodeUrl().isEmpty()) { // 保存小程序码链接到本地 deviceSelectDataManager.saveMiniQrcodeUrl(data.getQrcodeUrl()); android.util.Log.d("MainActivity", "小程序码获取并保存成功: " + data.getQrcodeUrl()); LogManager.logOperation("MainActivity", "小程序码获取并保存成功"); // 添加调试日志,验证保存是否成功 String savedUrl = deviceSelectDataManager.getMiniQrcodeUrl(); boolean hasUrl = deviceSelectDataManager.hasMiniQrcodeUrl(); android.util.Log.d("MainActivity", "验证保存结果 - 是否存在: " + hasUrl + ", 保存的URL: " + savedUrl); } else { android.util.Log.w("MainActivity", "获取到的小程序码数据为空或URL为空"); LogManager.logWarning("MainActivity", "获取到的小程序码数据为空或URL为空"); } // 执行完成回调 if (onComplete != null) { onComplete.run(); } } @Override public void onError(int errorCode, String errorMessage) { // 获取小程序码失败 android.util.Log.e("MainActivity", "获取小程序码失败 - 错误码: " + errorCode + ", 错误信息: " + errorMessage); LogManager.logError("MainActivity", "获取小程序码失败 - 错误码: " + errorCode + ", 错误信息: " + errorMessage); // 即使获取小程序码失败,也执行完成回调 if (onComplete != null) { onComplete.run(); } } @Override public void onComplete() { // 请求完成 } }); } /** * 获取并保存上传人脸小程序码 * @param token 访问令牌 * @param hardwareId 硬件ID * @param dialog 弹框实例 * @param buttonEnter 进入按钮 * @param buttonText 按钮文字视图 * @param originalText 原始按钮文字 * @param onComplete 请求完成回调 */ private void fetchAndSaveUploadFaceMiniQrcode(String token, int hardwareId, Dialog dialog, View buttonEnter, TextView buttonText, String originalText, Runnable onComplete) { // 获取品牌ID int brandId = loginDataManager.getBrandId(); // 检查brandId是否有效 if (brandId <= 0) { android.util.Log.e("MainActivity", "无效的品牌ID: " + brandId); LogManager.logError("MainActivity", "获取上传人脸小程序码失败 - 无效的品牌ID: " + brandId); // 即使获取上传人脸小程序码失败,也执行完成回调 if (onComplete != null) { onComplete.run(); } return; } // 调用获取上传人脸小程序码接口 NetworkUtils.getWXACodeUnlimit(token, hardwareId, brandId, new NetworkCallback() { @Override public void onStart() { // 开始请求 android.util.Log.d("MainActivity", "开始请求上传人脸小程序码"); } @Override public void onSuccess(PadApiService.GetWXACodeResponse data) { // 获取上传人脸小程序码成功 if (data != null && data.getUrl() != null && !data.getUrl().isEmpty()) { // 保存上传人脸小程序码链接到本地 deviceSelectDataManager.saveUploadFaceMiniQrcodeUrl(data.getUrl()); android.util.Log.d("MainActivity", "上传人脸小程序码获取并保存成功: " + data.getUrl()); LogManager.logOperation("MainActivity", "上传人脸小程序码获取并保存成功"); // 添加调试日志,验证保存是否成功 String savedUrl = deviceSelectDataManager.getUploadFaceMiniQrcodeUrl(); boolean hasUrl = deviceSelectDataManager.hasUploadFaceMiniQrcodeUrl(); android.util.Log.d("MainActivity", "验证保存结果 - 是否存在: " + hasUrl + ", 保存的URL: " + savedUrl); } else { android.util.Log.w("MainActivity", "获取到的上传人脸小程序码数据为空或URL为空"); LogManager.logWarning("MainActivity", "获取到的上传人脸小程序码数据为空或URL为空"); } // 执行完成回调 if (onComplete != null) { onComplete.run(); } } @Override public void onError(int errorCode, String errorMessage) { // 获取上传人脸小程序码失败 android.util.Log.e("MainActivity", "获取上传人脸小程序码失败 - 错误码: " + errorCode + ", 错误信息: " + errorMessage); LogManager.logError("MainActivity", "获取上传人脸小程序码失败 - 错误码: " + errorCode + ", 错误信息: " + errorMessage); // 即使获取上传人脸小程序码失败,也执行完成回调 if (onComplete != null) { onComplete.run(); } } @Override public void onComplete() { // 请求完成 } }); } /** * 设置日志路径调试功能(长按登录按钮) */ private void setupLogPathDebug() { buttonLogin.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { // 显示自启动状态信息(调试功能) showAutoStartStatusInfo(); return true; } }); // 添加长按版本号打开调试界面的功能 setupVersionLongClick(); // 添加双击测试功能 setupDoubleTapTest(); } /** * 设置长按版本号打开调试界面的功能 */ private void setupVersionLongClick() { // 查找版本号TextView(在布局文件中没有明确的ID,我们需要通过遍历查找) View bottomInfoLayout = findViewById(R.id.bottomInfoLayout); if (bottomInfoLayout instanceof LinearLayout) { LinearLayout layout = (LinearLayout) bottomInfoLayout; // 遍历子视图找到包含版本号的LinearLayout for (int i = 0; i < layout.getChildCount(); i++) { View child = layout.getChildAt(i); if (child instanceof LinearLayout) { LinearLayout versionLayout = (LinearLayout) child; // 查找版本号TextView for (int j = 0; j < versionLayout.getChildCount(); j++) { View versionChild = versionLayout.getChildAt(j); if (versionChild instanceof TextView) { TextView versionTextView = (TextView) versionChild; // 检查是否包含版本号文本 if (versionTextView.getText().toString().contains("Version")) { // 设置长按监听器 versionTextView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { // 打开调试界面 openDebugActivity(); return true; } }); break; } } } } } } } /** * 打开调试界面 */ private void openDebugActivity() { Intent intent = new Intent(this, DebugActivity.class); startActivity(intent); } /** * 设置双击测试功能 */ private void setupDoubleTapTest() { final long[] taps = new long[3]; // 增加到3个点击点 final int[] tapCount = {0}; buttonLogin.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { long currentTime = System.currentTimeMillis(); taps[tapCount[0] % 3] = currentTime; tapCount[0]++; // 检查是否在300ms内三击 if (tapCount[0] >= 3 && (currentTime - taps[(tapCount[0] - 3) % 3]) < 300) { // 三击触发直接启动测试 triggerDirectStartTest(); tapCount[0] = 0; // 重置计数 } // 检查是否在300ms内双击 else if (tapCount[0] >= 2 && (currentTime - taps[(tapCount[0] - 2) % 3]) < 300) { // 双击触发自启动测试 triggerAutoStartTest(); tapCount[0] = 0; // 重置计数 } else { // 正常的登录按钮点击事件 handleLoginButtonClick(); } } }); } /** * 处理登录按钮点击事件 */ private void handleLoginButtonClick() { String username = editTextUsername.getText().toString().trim(); String password = editTextPassword.getText().toString().trim(); // 在测试环境下,如果用户名和密码都为空,自动填充默认账号 if (isTestEnvironment() && username.isEmpty() && password.isEmpty()) { username = "00167"; password = "123456"; // 更新输入框显示 editTextUsername.setText(username); editTextPassword.setText(password); // 显示提示信息 showToast("测试环境:已自动填充默认账号"); android.util.Log.d("MainActivity", "Test environment: Auto-filled default credentials"); } if (validateInput(username, password)) { performLogin(username, password); } } /** * 触发自启动测试 */ private void triggerAutoStartTest() { try { // 使用反射调用测试辅助类 Class testHelperClass = Class.forName("com.ouxuan.oxface.utils.BootSimulationHelper"); java.lang.reflect.Method testMethod = testHelperClass.getMethod("simulateBootCompleted", android.content.Context.class); testMethod.invoke(null, this); showToast("自启动测试已触发"); } catch (Exception e) { android.util.Log.e(TAG, "触发自启动测试失败", e); showToast("触发自启动测试失败"); } } /** * 直接启动应用测试 */ private void triggerDirectStartTest() { try { // 使用反射调用测试辅助类 Class testHelperClass = Class.forName("com.ouxuan.oxface.utils.BootSimulationHelper"); java.lang.reflect.Method testMethod = testHelperClass.getMethod("directStartApp", android.content.Context.class); testMethod.invoke(null, this); showToast("直接启动测试已触发"); } catch (Exception e) { android.util.Log.e(TAG, "触发直接启动测试失败", e); showToast("触发直接启动测试失败"); } } /** * 显示日志路径信息 */ private void showLogPathInfo() { String pathInfo = LogManager.getLogPathInfo(this); // 在日志中记录 android.util.Log.i("MainActivity", "日志路径信息:\n" + pathInfo); // 写入一条测试日志 LogManager.logOperation("调试", "用户查看日志路径信息"); // 创建对话框显示路径信息 android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(this); builder.setTitle("日志路径信息(调试)"); builder.setMessage(pathInfo); builder.setPositiveButton("复制路径", new android.content.DialogInterface.OnClickListener() { @Override public void onClick(android.content.DialogInterface dialog, int which) { // 复制日志目录路径到剪贴板 android.content.ClipboardManager clipboard = (android.content.ClipboardManager) getSystemService(android.content.Context.CLIPBOARD_SERVICE); if (clipboard != null) { LogManager logManager = LogManager.getInstance(MainActivity.this); String logDirPath = logManager.getLogDirectory().getAbsolutePath(); android.content.ClipData clip = android.content.ClipData.newPlainText("日志目录路径", logDirPath); clipboard.setPrimaryClip(clip); showToast("日志目录路径已复制: " + logDirPath); } } }); builder.setNegativeButton("关闭", null); builder.setNeutralButton("写入测试日志", new android.content.DialogInterface.OnClickListener() { @Override public void onClick(android.content.DialogInterface dialog, int which) { // 写入一些测试日志 LogManager.logInfo("DEBUG", "这是一条测试信息日志 - " + new java.util.Date()); LogManager.logWarning("DEBUG", "这是一条测试警告日志 - " + new java.util.Date()); LogManager.logError("DEBUG", "这是一条测试错误日志 - " + new java.util.Date()); LogManager.logOperation("测试操作", "用户触发测试日志写入"); LogManager.logPerformance("测试性能", 88); showToast("测试日志已写入,请稍后再查看路径信息"); } }); builder.show(); } /** * 显示api_response_data_json */ private void showToastU_api_response_data() { UtilCodeHelper.Toast.cancel(); // 将 device_select_prefs.xml 中的 使用gson转为json,并用toast显示其中的hardware_name DeviceSelectDataManager deviceSelectDataManager = DeviceSelectDataManager.getInstance(this); String json = deviceSelectDataManager.getApiResponseDataJson(); try { JSONObject jsonObject = new JSONObject(json); String hardware_name = jsonObject.getString("hardware_name"); // Toast.showShort(hardware_name); UtilCodeHelper.Toast.showLong(hardware_name); } catch (JSONException e) { e.printStackTrace(); } // Gson gson = new Gson(); // String apiResponseDataJson = deviceSelectDataManager.getApiResponseDataJson(); // PadApiService.PadSelectResponse apiResponse = gson.fromJson(apiResponseDataJson, PadApiService.PadSelectResponse.class); // LogManager.logDebug("api_response_data_json", apiResponseDataJson); // UtilCodeHelper.Toast.showShort(apiResponseDataJson); } /** * 显示自启动状态信息(调试功能) */ private void showAutoStartStatusInfo() { if (autoStartManager != null) { String statusInfo = autoStartManager.getAutoStartStatusInfo(); LogManager.logDebug(TAG, "自启动状态信息:\n" + statusInfo); // 创建弹框显示详细状态 android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(this); builder.setTitle("自启动功能状态(调试)"); builder.setMessage(statusInfo); builder.setPositiveButton("测试自启动", new android.content.DialogInterface.OnClickListener() { @Override public void onClick(android.content.DialogInterface dialog, int which) { // 执行自启动功能测试 autoStartManager.testAutoStartFunction(); showToast("自启动测试已执行,请查看日志"); } }); builder.setNegativeButton("关闭", null); builder.setNeutralButton("重置统计", new android.content.DialogInterface.OnClickListener() { @Override public void onClick(android.content.DialogInterface dialog, int which) { autoStartManager.resetAutoStartStats(); showToast("自启动统计信息已重置"); } }); builder.show(); } else { 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; } } }