using System.Collections; using System.Collections.Generic; using Unity.VisualScripting; using UnityEngine; using UnityEngine.SceneManagement; public class DCXManager : MonoBehaviour { private SerialCommunicationService _serialService; // public DataService _dataService; private UserLogService _userLogService; // 内存监控相关 private float _lastMemoryCheckTime = 0f; private const float MEMORY_CHECK_INTERVAL = 60f; // 每分钟检查一次内存 // 网络错误日志限流相关 private float _lastNetworkErrorLogTime = 0f; private const float NETWORK_ERROR_LOG_INTERVAL = 60f; // 每60秒记录一次网络错误 private int _networkErrorCount = 0; void Awake() { DontDestroyOnLoad(gameObject); #if UNITY_ANDROID && !UNITY_EDITOR // 设置服务在Awake阶段加载,文件日志也要先启动,才能记录启动恢复来源。 InitializeAndroidLogger(); #endif BootstrapServices(); // 注册Unity日志回调以捕获网络错误 Application.logMessageReceived += HandleUnityLogs; } void Start() { UIManager.Instance.ShowPanel(); } void Update() { // 确保串口服务在主线程中处理接收队列 _serialService?.Update(); // 定期内存检查 CheckMemoryUsage(); } /// /// 定期检查内存使用情况 /// private void CheckMemoryUsage() { if (Time.time - _lastMemoryCheckTime >= MEMORY_CHECK_INTERVAL) { var memoryUsage = System.GC.GetTotalMemory(false) / (1024 * 1024f); // MB #if UNITY_ANDROID && !UNITY_EDITOR // 记录内存使用到文件日志 AndroidFileLogger.Instance?.LogMemoryUsage(memoryUsage, $"队列状态: {_serialService?.GetQueueStatus() ?? "未知"}"); // 安卓板上内存使用过多时强制清理 if (memoryUsage > 300) // 超过300MB时强制清理 { AndroidFileLogger.Instance?.LogError("Memory", $"内存过高({memoryUsage:F1}MB),开始强制清理"); Debug.LogWarning($"[内存警告] 当前内存使用: {memoryUsage:F1}MB,开始强制清理"); // 清理串口队列 _serialService?.ForceCleanQueues(); // 强制垃圾回收 System.GC.Collect(); System.GC.WaitForPendingFinalizers(); System.GC.Collect(); // 二次回收 var memoryAfter = System.GC.GetTotalMemory(false) / (1024 * 1024f); AndroidFileLogger.Instance?.LogInfo("Memory", $"清理完成: {memoryUsage:F1}MB -> {memoryAfter:F1}MB, 释放: {(memoryUsage - memoryAfter):F1}MB"); Debug.Log($"[内存清理] 清理后内存: {memoryAfter:F1}MB,释放: {(memoryUsage - memoryAfter):F1}MB"); } else if (memoryUsage > 200) // 超过200MB时记录警告 { AndroidFileLogger.Instance?.LogInfo("Memory", $"内存使用较高: {memoryUsage:F1}MB"); Debug.LogWarning($"[内存监控] 内存使用较高: {memoryUsage:F1}MB"); // 每30秒强制执行一次内存清理 if (Time.time % 30f < 1f) { _serialService?.MonitorMemoryUsage(); } } #else // PC上只记录内存使用情况 if (memoryUsage > 500) { Debug.LogWarning($"[内存监控] 当前内存使用: {memoryUsage:F1}MB"); } #endif _lastMemoryCheckTime = Time.time; } } #if UNITY_ANDROID && !UNITY_EDITOR /// /// 初始化安卓文件日志系统 /// private void InitializeAndroidLogger() { try { // AndroidFileLogger会自动创建单例并初始化 var logger = AndroidFileLogger.Instance; if (logger != null) { logger.LogInfo("DCXManager", "安卓文件日志系统已初始化"); logger.LogInfo("DCXManager", $"应用启动时间: {System.DateTime.Now:yyyy-MM-dd HH:mm:ss}"); // 记录初始内存状态 var initialMemory = System.GC.GetTotalMemory(false) / (1024 * 1024f); logger.LogMemoryUsage(initialMemory, "应用启动"); Debug.Log($"[DCXManager] 安卓文件日志系统已启动,日志路径: {logger.GetCurrentLogFilePath()}"); } else { Debug.LogError("[DCXManager] 安卓文件日志系统初始化失败"); } } catch (System.Exception ex) { Debug.LogError($"[DCXManager] 初始化安卓文件日志系统异常: {ex.Message}"); } } #endif private void BootstrapServices() { // 首先注册数据持久化服务 if (!ServiceLocator.IsRegistered()) { ServiceLocator.Register(new DataPersistenceService()); } if (!ServiceLocator.IsRegistered()) { // 使用新的持久化认证服务替代内存版本 ServiceLocator.Register(new PersistentAuthenticationService()); } if(!ServiceLocator.IsRegistered()) { _userLogService = new UserLogService(); ServiceLocator.Register(_userLogService); } // 注册串口通信服务 if (!ServiceLocator.IsRegistered()) { _serialService = new SerialCommunicationService(); ServiceLocator.Register(_serialService); } if (!ServiceLocator.IsRegistered()) { ServiceLocator.Register(new SystemSettingsService()); } // if (!ServiceLocator.IsRegistered()) // { // ServiceLocator.Register(new PowerService()); // } if (!ServiceLocator.IsRegistered()) { ServiceLocator.Register(new DataExportService()); } if (!ServiceLocator.IsRegistered()) { ServiceLocator.Register(new PatientInfoService()); } // if (!ServiceLocator.IsRegistered()) // { // ServiceLocator.Register(_dataService); // } // 注册患者会话服务 if (!ServiceLocator.IsRegistered()) { ServiceLocator.Register(new PatientSessionService()); } } void OnDestroy() { // 取消注册日志回调 Application.logMessageReceived -= HandleUnityLogs; } /// /// 处理Unity日志,实现网络错误限流 /// private void HandleUnityLogs(string logString, string stackTrace, LogType type) { // 只处理Error和Exception类型的日志 if (type != LogType.Error && type != LogType.Exception) return; // 检测是否为网络相关错误 bool isNetworkError = logString.Contains("Network is unreachable") || logString.Contains("network") || logString.Contains("Network"); if (!isNetworkError) return; // 网络错误计数 _networkErrorCount++; // 每60秒记录一次,避免日志刷屏 if (Time.time - _lastNetworkErrorLogTime >= NETWORK_ERROR_LOG_INTERVAL) { Debug.Log($"[DCXManager] Unity底层网络检查(已忽略): {logString}"); _lastNetworkErrorLogTime = Time.time; #if UNITY_ANDROID && !UNITY_EDITOR AndroidFileLogger.Instance?.LogInfo("Network", $"Unity网络错误(过去{NETWORK_ERROR_LOG_INTERVAL}秒): {_networkErrorCount}次"); // 记录详细信息以便调试 if (_networkErrorCount == 1) { AndroidFileLogger.Instance?.LogInfo("Network", $"首次网络错误详情: {logString}"); } #endif // 重置计数器 _networkErrorCount = 0; } // 注意:不触发GC,不做其他重操作 // 网络错误是Unity Native层行为,不影响串口通信 } }