250 lines
9.0 KiB
C#
250 lines
9.0 KiB
C#
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<StandByPanel>();
|
||
}
|
||
|
||
void Update()
|
||
{
|
||
// 确保串口服务在主线程中处理接收队列
|
||
_serialService?.Update();
|
||
|
||
// 定期内存检查
|
||
CheckMemoryUsage();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 定期检查内存使用情况
|
||
/// </summary>
|
||
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
|
||
/// <summary>
|
||
/// 初始化安卓文件日志系统
|
||
/// </summary>
|
||
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<IDataPersistenceService>())
|
||
{
|
||
ServiceLocator.Register<IDataPersistenceService>(new DataPersistenceService());
|
||
}
|
||
|
||
if (!ServiceLocator.IsRegistered<IAuthenticationService>())
|
||
{
|
||
// 使用新的持久化认证服务替代内存版本
|
||
ServiceLocator.Register<IAuthenticationService>(new PersistentAuthenticationService());
|
||
}
|
||
if(!ServiceLocator.IsRegistered<UserLogService>())
|
||
{
|
||
_userLogService = new UserLogService();
|
||
ServiceLocator.Register<UserLogService>(_userLogService);
|
||
}
|
||
// 注册串口通信服务
|
||
if (!ServiceLocator.IsRegistered<ISerialCommunicationService>())
|
||
{
|
||
_serialService = new SerialCommunicationService();
|
||
ServiceLocator.Register<ISerialCommunicationService>(_serialService);
|
||
}
|
||
if (!ServiceLocator.IsRegistered<ISystemSettingsService>())
|
||
{
|
||
ServiceLocator.Register<ISystemSettingsService>(new SystemSettingsService());
|
||
}
|
||
// if (!ServiceLocator.IsRegistered<IPowerService>())
|
||
// {
|
||
// ServiceLocator.Register<IPowerService>(new PowerService());
|
||
// }
|
||
if (!ServiceLocator.IsRegistered<IDataExportService>())
|
||
{
|
||
ServiceLocator.Register<IDataExportService>(new DataExportService());
|
||
}
|
||
if (!ServiceLocator.IsRegistered<IPatientInfoService>())
|
||
{
|
||
ServiceLocator.Register<IPatientInfoService>(new PatientInfoService());
|
||
}
|
||
// if (!ServiceLocator.IsRegistered<IDataService>())
|
||
// {
|
||
// ServiceLocator.Register<IDataService>(_dataService);
|
||
// }
|
||
|
||
// 注册患者会话服务
|
||
if (!ServiceLocator.IsRegistered<PatientSessionService>())
|
||
{
|
||
ServiceLocator.Register<PatientSessionService>(new PatientSessionService());
|
||
}
|
||
}
|
||
|
||
void OnDestroy()
|
||
{
|
||
// 取消注册日志回调
|
||
Application.logMessageReceived -= HandleUnityLogs;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 处理Unity日志,实现网络错误限流
|
||
/// </summary>
|
||
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层行为,不影响串口通信
|
||
}
|
||
}
|