diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..e0f15db
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "java.configuration.updateBuildConfiguration": "automatic"
+}
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index 06581c4..24f2d0a 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -15,12 +15,43 @@ android {
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+
+ // 24小时运行优化配置
+ multiDexEnabled true
+ }
+
+ // Dex优化由Android Gradle插件自动管理
+ // dexOptions已在Gradle 8.0中废弃
+
+ // 打包优化配置
+ packagingOptions {
+ pickFirst '**/libnative-lib.so'
+ exclude 'META-INF/DEPENDENCIES'
+ exclude 'META-INF/LICENSE'
+ exclude 'META-INF/LICENSE.txt'
+ exclude 'META-INF/NOTICE'
+ exclude 'META-INF/NOTICE.txt'
}
buildTypes {
+ debug {
+ minifyEnabled false
+ debuggable true
+ applicationIdSuffix ".debug"
+ versionNameSuffix "-debug"
+
+ // 调试版本优化配置
+ crunchPngs false
+ zipAlignEnabled true
+ }
+
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+
+ // 发布版本优化配置
+ zipAlignEnabled true
+ shrinkResources false
}
}
@@ -45,6 +76,9 @@ dependencies {
// 图片加载库
implementation 'com.github.bumptech.glide:glide:4.16.0'
+ // Android开发工具库
+ implementation 'com.blankj:utilcode:1.30.7'
+
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 0b9c2e5..9fd8c96 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -5,10 +5,22 @@
+
+
+
+
+
+
+
+
+ android:theme="@style/Theme.OxFaceLogin.Splash"
+ android:screenOrientation="portrait"
+ android:launchMode="singleTop"
+ android:configChanges="orientation|screenSize|keyboardHidden">
diff --git a/app/src/main/java/com/ouxuan/oxface/MainActivity.java b/app/src/main/java/com/ouxuan/oxface/MainActivity.java
index e36c278..ab79008 100644
--- a/app/src/main/java/com/ouxuan/oxface/MainActivity.java
+++ b/app/src/main/java/com/ouxuan/oxface/MainActivity.java
@@ -29,6 +29,9 @@ import com.ouxuan.oxface.network.api.PadApiService;
import com.ouxuan.oxface.network.api.UserApiService;
import com.ouxuan.oxface.network.callback.NetworkCallback;
import com.ouxuan.oxface.network.utils.NetworkUtils;
+import com.ouxuan.oxface.utils.KeepAliveManager;
+import com.ouxuan.oxface.utils.LogManager;
+import com.ouxuan.oxface.utils.UtilCodeHelper;
public class MainActivity extends AppCompatActivity {
@@ -39,6 +42,7 @@ public class MainActivity extends AppCompatActivity {
private Toast currentToast; // 用于管理Toast显示状态
private boolean isPasswordVisible = false; // 密码显示状态
private LoginDataManager loginDataManager; // 登录数据管理器
+ private KeepAliveManager keepAliveManager; // 保持活跃管理器
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -59,6 +63,13 @@ public class MainActivity extends AppCompatActivity {
// 初始化登录数据管理器
loginDataManager = LoginDataManager.getInstance(this);
+ // 初始化保持活跃管理器并启动(用于24小时无人值守)
+ keepAliveManager = KeepAliveManager.getInstance(this);
+ keepAliveManager.startKeepAlive(this);
+
+ // 记录应用启动
+ LogManager.logOperation("MainActivity", "主界面已初始化,开始24小时无人值守模式");
+
// 检查是否可以自动登录
checkAutoLogin();
@@ -633,5 +644,39 @@ public class MainActivity extends AppCompatActivity {
.putString("session_token", selectResponse.getSessionToken())
.putLong("valid_until", selectResponse.getValidUntil())
.apply();
+
+ LogManager.logOperation("MainActivity", "已保存选中的设备信息: " + padInfo.getPadName());
+ }
+
+ @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();
+
+ LogManager.logOperation("MainActivity", "主界面正在销毁");
+
+ // 只在应用真正退出时才停止保持活跃
+ if (isFinishing() && keepAliveManager != null) {
+ keepAliveManager.stopKeepAlive(this);
+ LogManager.logOperation("MainActivity", "应用退出,停止保持活跃功能");
+ }
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/ouxuan/oxface/OxFaceApplication.java b/app/src/main/java/com/ouxuan/oxface/OxFaceApplication.java
index cdca7fb..60fbbd9 100644
--- a/app/src/main/java/com/ouxuan/oxface/OxFaceApplication.java
+++ b/app/src/main/java/com/ouxuan/oxface/OxFaceApplication.java
@@ -2,19 +2,295 @@ package com.ouxuan.oxface;
import android.app.Application;
+import com.ouxuan.oxface.network.NetworkManager;
+import com.ouxuan.oxface.network.NetworkStabilityManager;
import com.ouxuan.oxface.network.utils.NetworkUtils;
+import com.ouxuan.oxface.utils.GlobalExceptionHandler;
+import com.ouxuan.oxface.utils.HealthMonitor;
+import com.ouxuan.oxface.utils.LogManager;
+import com.ouxuan.oxface.utils.MaintenanceScheduler;
+import com.ouxuan.oxface.utils.MemoryManager;
+import com.ouxuan.oxface.utils.UtilCodeHelper;
+import com.blankj.utilcode.util.Utils;
/**
* 应用程序Application类
- * 用于全局初始化各种模块
+ * 用于全局初始化各种模块,支持24小时无人值守运行
*/
-public class OxFaceApplication extends Application {
+public class OxFaceApplication extends Application implements
+ NetworkStabilityManager.NetworkStateListener,
+ HealthMonitor.HealthStatusListener {
+
+ private static final String TAG = "OxFaceApplication";
+ private static OxFaceApplication instance;
+
+ // 管理器实例
+ private LogManager logManager;
+ private GlobalExceptionHandler exceptionHandler;
+ private MemoryManager memoryManager;
+ private NetworkManager networkManager;
+ private HealthMonitor healthMonitor;
+ private MaintenanceScheduler maintenanceScheduler;
+
+ public static OxFaceApplication getInstance() {
+ return instance;
+ }
@Override
public void onCreate() {
super.onCreate();
+ instance = this;
+
+ // 按顺序初始化所有管理器
+ initializeManagers();
+ }
+
+ /**
+ * 初始化所有管理器
+ */
+ private void initializeManagers() {
+ try {
+ // 0. 初始化UtilCode工具库(最高优先级)
+ Utils.init(this);
+
+ // 1. 首先启动日志管理器
+ initLogManager();
+
+ // 2. 安装全局异常处理器
+ initGlobalExceptionHandler();
+
+ // 3. 初始化网络管理器
+ initNetworkManager();
+
+ // 4. 初始化内存管理器
+ initMemoryManager();
+
+ // 5. 初始化健康监控器
+ initHealthMonitor();
+
+ // 6. 启动维护调度器
+ initMaintenanceScheduler();
+
+ // 7. 初始化原有的网络工具
+ NetworkUtils.init(this);
+
+ LogManager.logOperation(TAG, "所有管理器初始化完成,应用已准备好24小时无人值守运行");
+
+ } catch (Exception e) {
+ android.util.Log.e(TAG, "初始化管理器失败", e);
+ }
+ }
+
+ /**
+ * 初始化日志管理器
+ */
+ private void initLogManager() {
+ logManager = LogManager.getInstance(this);
+ logManager.start();
+ LogManager.logOperation(TAG, "日志管理器启动");
+ }
+
+ /**
+ * 初始化全局异常处理器
+ */
+ private void initGlobalExceptionHandler() {
+ exceptionHandler = new GlobalExceptionHandler(this, true);
+ exceptionHandler.install();
+ LogManager.logOperation(TAG, "全局异常处理器安装完成");
+ }
+
+ /**
+ * 初始化网络管理器
+ */
+ private void initNetworkManager() {
+ networkManager = NetworkManager.getInstance(this);
+ networkManager.startNetworkMonitoring(this);
+ LogManager.logOperation(TAG, "网络管理器初始化完成");
+ }
+
+ /**
+ * 初始化内存管理器
+ */
+ private void initMemoryManager() {
+ memoryManager = MemoryManager.getInstance(this);
+ memoryManager.startMemoryMonitoring();
+ LogManager.logOperation(TAG, "内存管理器启动");
+ }
+
+ /**
+ * 初始化健康监控器
+ */
+ private void initHealthMonitor() {
+ healthMonitor = HealthMonitor.getInstance(this);
+ healthMonitor.startHealthCheck(this);
+ LogManager.logOperation(TAG, "健康监控器启动");
+ }
+
+ /**
+ * 初始化维护调度器
+ */
+ private void initMaintenanceScheduler() {
+ maintenanceScheduler = MaintenanceScheduler.getInstance(this);
+ maintenanceScheduler.startMaintenance();
+ LogManager.logOperation(TAG, "维护调度器启动");
+ }
+
+ // ========== NetworkStateListener 接口实现 ==========
+
+ @Override
+ public void onNetworkAvailable() {
+ LogManager.logOperation(TAG, "网络连接恢复");
- // 初始化网络模块
- NetworkUtils.init(this);
+ // 重新初始化网络管理器
+ if (networkManager != null) {
+ networkManager.reinitialize();
+ }
+ }
+
+ @Override
+ public void onNetworkLost() {
+ LogManager.logWarning(TAG, "网络连接丢失");
+ }
+
+ @Override
+ public void onNetworkQualityChanged(NetworkStabilityManager.NetworkQuality quality) {
+ LogManager.logInfo(TAG, "网络质量变化: " + quality);
+ }
+
+ // ========== HealthStatusListener 接口实现 ==========
+
+ @Override
+ public void onHealthStatusChanged(HealthMonitor.HealthStatus status) {
+ LogManager.logOperation(TAG, "系统健康状态变化: " + status);
+
+ if (status == HealthMonitor.HealthStatus.CRITICAL ||
+ status == HealthMonitor.HealthStatus.SYSTEM_ERROR) {
+ // 触发紧急维护
+ if (maintenanceScheduler != null) {
+ maintenanceScheduler.performImmediateMaintenance();
+ }
+ }
+ }
+
+ @Override
+ public void onCriticalIssueDetected(String issue) {
+ LogManager.logError(TAG, "检测到严重问题: " + issue);
+
+ // 记录系统状态快照
+ recordSystemSnapshot("严重问题: " + issue);
+ }
+
+ @Override
+ public void onSystemRecovered(String recoveryAction) {
+ LogManager.logOperation(TAG, "系统已恢复: " + recoveryAction);
+ }
+
+ /**
+ * 记录系统状态快照
+ */
+ private void recordSystemSnapshot(String reason) {
+ try {
+ StringBuilder snapshot = new StringBuilder();
+ snapshot.append("=== 系统状态快照 (").append(reason).append(") ===").append("\n");
+
+ // 使用UtilCode获取系统信息
+ snapshot.append("设备信息: ").append(UtilCodeHelper.Device.getDeviceInfoSummary()).append("\n");
+ snapshot.append("屏幕信息: ").append(UtilCodeHelper.Screen.getScreenInfoSummary()).append("\n");
+ snapshot.append("网络状态: ").append(UtilCodeHelper.Network.getNetworkStatusSummary()).append("\n");
+ snapshot.append("应用信息: ").append(UtilCodeHelper.App.getAppInfoSummary()).append("\n");
+ snapshot.append("当前时间: ").append(UtilCodeHelper.Time.millis2String(UtilCodeHelper.Time.getCurrentTimeMillis())).append("\n");
+
+ // 内存状态
+ if (memoryManager != null) {
+ snapshot.append("内存使用率: ").append(String.format("%.1f%%", memoryManager.getCurrentMemoryUsage() * 100)).append("\n");
+ }
+
+ // 网络状态(详细信息)
+ if (networkManager != null) {
+ snapshot.append("网络连接: ").append(networkManager.isNetworkAvailable() ? "可用" : "不可用").append("\n");
+ snapshot.append("网络类型: ").append(networkManager.getNetworkTypeDescription()).append("\n");
+ }
+
+ // 健康状态
+ if (healthMonitor != null) {
+ HealthMonitor.HealthReport report = healthMonitor.getCurrentHealthReport();
+ snapshot.append("系统健康状态: ").append(report.overallStatus).append("\n");
+ snapshot.append("运行时间: ").append(report.uptime / (1000 * 60 * 60)).append("小时").append("\n");
+ }
+
+ // 维护统计
+ if (maintenanceScheduler != null) {
+ snapshot.append("维护统计: ").append(maintenanceScheduler.getMaintenanceStats()).append("\n");
+ }
+
+ snapshot.append("===========================================");
+
+ LogManager.logOperation(TAG, snapshot.toString());
+
+ } catch (Exception e) {
+ LogManager.logError(TAG, "记录系统快照失败", e);
+ }
+ }
+
+ /**
+ * 优雅关闭所有管理器
+ */
+ @Override
+ public void onTerminate() {
+ super.onTerminate();
+
+ LogManager.logOperation(TAG, "应用程序正在关闭,停止所有管理器");
+
+ try {
+ // 停止维护调度器
+ if (maintenanceScheduler != null) {
+ maintenanceScheduler.stopMaintenance();
+ }
+
+ // 停止健康监控器
+ if (healthMonitor != null) {
+ healthMonitor.stopHealthCheck();
+ }
+
+ // 停止内存监控
+ if (memoryManager != null) {
+ memoryManager.stopMemoryMonitoring();
+ }
+
+ // 停止网络监控
+ if (networkManager != null) {
+ networkManager.stopNetworkMonitoring();
+ }
+
+ // 停止日志管理器(最后停止)
+ if (logManager != null) {
+ logManager.stop();
+ }
+
+ } catch (Exception e) {
+ android.util.Log.e(TAG, "关闭管理器时发生异常", e);
+ }
+ }
+
+ // ========== 公共访问方法 ==========
+
+ public LogManager getLogManager() {
+ return logManager;
+ }
+
+ public MemoryManager getMemoryManager() {
+ return memoryManager;
+ }
+
+ public NetworkManager getNetworkManager() {
+ return networkManager;
+ }
+
+ public HealthMonitor getHealthMonitor() {
+ return healthMonitor;
+ }
+
+ public MaintenanceScheduler getMaintenanceScheduler() {
+ return maintenanceScheduler;
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/ouxuan/oxface/network/NetworkManager.java b/app/src/main/java/com/ouxuan/oxface/network/NetworkManager.java
index df63635..ab6257a 100644
--- a/app/src/main/java/com/ouxuan/oxface/network/NetworkManager.java
+++ b/app/src/main/java/com/ouxuan/oxface/network/NetworkManager.java
@@ -10,6 +10,7 @@ import com.ouxuan.oxface.network.callback.NetworkCallback;
import com.ouxuan.oxface.network.interceptor.HeaderInterceptor;
import com.ouxuan.oxface.network.interceptor.NetworkDebugInterceptor;
import com.ouxuan.oxface.network.model.ApiResponse;
+import com.ouxuan.oxface.utils.LogManager;
import java.util.concurrent.TimeUnit;
@@ -27,20 +28,28 @@ import retrofit2.converter.gson.GsonConverterFactory;
/**
* 网络请求管理器
* 单例模式,统一管理所有网络请求
+ * 集成网络稳定性优化功能,适用于24小时无人值守环境
*/
public class NetworkManager {
+ private static final String TAG = "NetworkManager";
private static volatile NetworkManager instance;
private OkHttpClient okHttpClient;
private Retrofit retrofit;
private Gson gson;
private Handler mainHandler;
+ private Context context;
+ private NetworkStabilityManager networkStabilityManager;
private NetworkManager(Context context) {
+ this.context = context.getApplicationContext();
+ this.networkStabilityManager = NetworkStabilityManager.getInstance(this.context);
initOkHttpClient(context);
initRetrofit();
initGson();
mainHandler = new Handler(Looper.getMainLooper());
+
+ LogManager.logOperation("NetworkManager", "网络管理器初始化完成");
}
/**
@@ -60,13 +69,25 @@ public class NetworkManager {
}
/**
- * 初始化OkHttpClient
+ * 获取NetworkManager单例实例(需要先调用getInstance(Context)初始化)
+ * @return NetworkManager实例
+ */
+ public static NetworkManager getInstance() {
+ if (instance == null) {
+ throw new IllegalStateException("NetworkManager 未初始化,请先调用 getInstance(Context)");
+ }
+ return instance;
+ }
+
+ /**
+ * 初始化OkHttpClient(集成网络稳定性优化)
*/
private void initOkHttpClient(Context context) {
- OkHttpClient.Builder builder = new OkHttpClient.Builder()
- .connectTimeout(NetworkConfig.CONNECT_TIMEOUT, TimeUnit.SECONDS)
- .readTimeout(NetworkConfig.READ_TIMEOUT, TimeUnit.SECONDS)
- .writeTimeout(NetworkConfig.WRITE_TIMEOUT, TimeUnit.SECONDS)
+ // 使用网络稳定性管理器的增强OkHttpClient配置
+ OkHttpClient enhancedClient = networkStabilityManager.getEnhancedOkHttpClient();
+
+ // 在增强配置的基础上添加项目特定的拦截器
+ OkHttpClient.Builder builder = enhancedClient.newBuilder()
.addInterceptor(new HeaderInterceptor(context));
// 添加网络调试拦截器(优先级最高,在所有拦截器之前)
@@ -82,6 +103,8 @@ public class NetworkManager {
}
okHttpClient = builder.build();
+
+ LogManager.logOperation("NetworkManager", "增强OkHttpClient配置完成");
}
/**
@@ -225,4 +248,61 @@ public class NetworkManager {
}
});
}
+
+ /**
+ * 重新初始化网络管理器(用于网络恢复后的重置)
+ */
+ public void reinitialize() {
+ try {
+ LogManager.logOperation("NetworkManager", "开始重新初始化网络管理器");
+
+ // 重新初始化OkHttpClient
+ initOkHttpClient(context);
+
+ // 重新初始化Retrofit
+ initRetrofit();
+
+ LogManager.logOperation("NetworkManager", "网络管理器重新初始化完成");
+
+ } catch (Exception e) {
+ LogManager.logError(TAG, "网络管理器重新初始化失败", e);
+ }
+ }
+
+ /**
+ * 获取网络稳定性管理器
+ */
+ public NetworkStabilityManager getNetworkStabilityManager() {
+ return networkStabilityManager;
+ }
+
+ /**
+ * 检查网络是否可用
+ */
+ public boolean isNetworkAvailable() {
+ return networkStabilityManager.isNetworkAvailable();
+ }
+
+ /**
+ * 获取网络类型描述
+ */
+ public String getNetworkTypeDescription() {
+ return networkStabilityManager.getNetworkTypeDescription();
+ }
+
+ /**
+ * 启动网络状态监控
+ */
+ public void startNetworkMonitoring(NetworkStabilityManager.NetworkStateListener listener) {
+ networkStabilityManager.startNetworkMonitoring(listener);
+ LogManager.logOperation("NetworkManager", "网络状态监控已启动");
+ }
+
+ /**
+ * 停止网络状态监控
+ */
+ public void stopNetworkMonitoring() {
+ networkStabilityManager.stopNetworkMonitoring();
+ LogManager.logOperation("NetworkManager", "网络状态监控已停止");
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/ouxuan/oxface/network/NetworkStabilityManager.java b/app/src/main/java/com/ouxuan/oxface/network/NetworkStabilityManager.java
new file mode 100644
index 0000000..06de9f5
--- /dev/null
+++ b/app/src/main/java/com/ouxuan/oxface/network/NetworkStabilityManager.java
@@ -0,0 +1,328 @@
+package com.ouxuan.oxface.network;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
+import android.util.Log;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+import okhttp3.Interceptor;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+
+/**
+ * 网络稳定性管理器
+ * 用于24小时无人值守环境下的网络连接稳定性保障
+ */
+public class NetworkStabilityManager {
+
+ private static final String TAG = "NetworkStabilityManager";
+ private static final int MAX_RETRY_COUNT = 3;
+ private static final int RETRY_DELAY_MS = 5000;
+ private static final int CONNECT_TIMEOUT_SECONDS = 30;
+ private static final int READ_TIMEOUT_SECONDS = 60;
+ private static final int WRITE_TIMEOUT_SECONDS = 60;
+
+ private static NetworkStabilityManager instance;
+ private Context context;
+ private ConnectivityManager connectivityManager;
+ private ConnectivityManager.NetworkCallback networkCallback;
+ private boolean isMonitoring = false;
+ private NetworkStateListener networkStateListener;
+
+ public interface NetworkStateListener {
+ void onNetworkAvailable();
+ void onNetworkLost();
+ void onNetworkQualityChanged(NetworkQuality quality);
+ }
+
+ public enum NetworkQuality {
+ EXCELLENT, GOOD, POOR, VERY_POOR
+ }
+
+ private NetworkStabilityManager(Context context) {
+ this.context = context.getApplicationContext();
+ this.connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ }
+
+ public static synchronized NetworkStabilityManager getInstance(Context context) {
+ if (instance == null) {
+ instance = new NetworkStabilityManager(context);
+ }
+ return instance;
+ }
+
+ /**
+ * 获取增强的OkHttpClient配置
+ */
+ public OkHttpClient getEnhancedOkHttpClient() {
+ return new OkHttpClient.Builder()
+ .connectTimeout(CONNECT_TIMEOUT_SECONDS, TimeUnit.SECONDS)
+ .readTimeout(READ_TIMEOUT_SECONDS, TimeUnit.SECONDS)
+ .writeTimeout(WRITE_TIMEOUT_SECONDS, TimeUnit.SECONDS)
+ .retryOnConnectionFailure(true)
+ .addInterceptor(new RetryInterceptor(MAX_RETRY_COUNT))
+ .addInterceptor(new NetworkQualityInterceptor())
+ .build();
+ }
+
+ /**
+ * 开始网络状态监控
+ */
+ public void startNetworkMonitoring(NetworkStateListener listener) {
+ if (isMonitoring) {
+ return;
+ }
+
+ this.networkStateListener = listener;
+ isMonitoring = true;
+
+ if (connectivityManager != null) {
+ networkCallback = new ConnectivityManager.NetworkCallback() {
+ @Override
+ public void onAvailable(Network network) {
+ super.onAvailable(network);
+ Log.i(TAG, "网络连接恢复: " + network.toString());
+ if (networkStateListener != null) {
+ networkStateListener.onNetworkAvailable();
+ }
+ }
+
+ @Override
+ public void onLost(Network network) {
+ super.onLost(network);
+ Log.w(TAG, "网络连接丢失: " + network.toString());
+ if (networkStateListener != null) {
+ networkStateListener.onNetworkLost();
+ }
+ }
+
+ @Override
+ public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
+ super.onCapabilitiesChanged(network, networkCapabilities);
+
+ // 检查网络质量
+ NetworkQuality quality = evaluateNetworkQuality(networkCapabilities);
+ Log.d(TAG, "网络质量变化: " + quality);
+
+ if (networkStateListener != null) {
+ networkStateListener.onNetworkQualityChanged(quality);
+ }
+ }
+ };
+
+ NetworkRequest.Builder builder = new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
+
+ connectivityManager.registerNetworkCallback(builder.build(), networkCallback);
+ Log.i(TAG, "网络状态监控已启动");
+ }
+ }
+
+ /**
+ * 停止网络状态监控
+ */
+ public void stopNetworkMonitoring() {
+ if (isMonitoring && connectivityManager != null && networkCallback != null) {
+ try {
+ connectivityManager.unregisterNetworkCallback(networkCallback);
+ isMonitoring = false;
+ Log.i(TAG, "网络状态监控已停止");
+ } catch (Exception e) {
+ Log.e(TAG, "停止网络监控失败", e);
+ }
+ }
+ }
+
+ /**
+ * 检查网络是否可用
+ */
+ public boolean isNetworkAvailable() {
+ if (connectivityManager == null) {
+ return false;
+ }
+
+ Network activeNetwork = connectivityManager.getActiveNetwork();
+ if (activeNetwork == null) {
+ return false;
+ }
+
+ NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(activeNetwork);
+ return capabilities != null &&
+ capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) &&
+ capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
+ }
+
+ /**
+ * 评估网络质量
+ */
+ private NetworkQuality evaluateNetworkQuality(NetworkCapabilities capabilities) {
+ if (capabilities == null) {
+ return NetworkQuality.VERY_POOR;
+ }
+
+ // 基于网络类型和能力评估质量
+ if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) ||
+ capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
+
+ if (capabilities.getLinkDownstreamBandwidthKbps() > 10000) { // > 10Mbps
+ return NetworkQuality.EXCELLENT;
+ } else if (capabilities.getLinkDownstreamBandwidthKbps() > 5000) { // > 5Mbps
+ return NetworkQuality.GOOD;
+ } else {
+ return NetworkQuality.POOR;
+ }
+ } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
+ return NetworkQuality.GOOD;
+ } else {
+ return NetworkQuality.POOR;
+ }
+ }
+
+ /**
+ * 获取网络类型描述
+ */
+ public String getNetworkTypeDescription() {
+ if (!isNetworkAvailable()) {
+ return "无网络连接";
+ }
+
+ Network activeNetwork = connectivityManager.getActiveNetwork();
+ NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(activeNetwork);
+
+ if (capabilities == null) {
+ return "未知网络";
+ }
+
+ if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
+ return "以太网";
+ } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
+ return "WiFi";
+ } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
+ return "移动网络";
+ } else {
+ return "其他网络";
+ }
+ }
+
+ /**
+ * 重试拦截器
+ */
+ public static class RetryInterceptor implements Interceptor {
+ private int maxRetryCount;
+
+ public RetryInterceptor(int maxRetryCount) {
+ this.maxRetryCount = maxRetryCount;
+ }
+
+ @Override
+ public Response intercept(Chain chain) throws IOException {
+ Request request = chain.request();
+ Response response = null;
+ IOException lastException = null;
+
+ for (int retryCount = 0; retryCount <= maxRetryCount; retryCount++) {
+ try {
+ response = chain.proceed(request);
+
+ // 如果响应成功,直接返回
+ if (response.isSuccessful()) {
+ if (retryCount > 0) {
+ Log.i(TAG, "重试成功,重试次数: " + retryCount);
+ }
+ return response;
+ }
+
+ // 如果是服务器错误且不是最后一次重试,关闭响应并重试
+ if (retryCount < maxRetryCount && response.code() >= 500) {
+ response.close();
+ Log.w(TAG, "服务器错误 " + response.code() + ",准备重试 " + (retryCount + 1));
+
+ // 等待一段时间再重试
+ try {
+ Thread.sleep(RETRY_DELAY_MS * (retryCount + 1));
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new IOException("重试被中断", e);
+ }
+ } else {
+ return response;
+ }
+
+ } catch (IOException e) {
+ lastException = e;
+
+ if (retryCount < maxRetryCount) {
+ Log.w(TAG, "网络请求失败,准备重试 " + (retryCount + 1) + ": " + e.getMessage());
+
+ // 等待一段时间再重试
+ try {
+ Thread.sleep(RETRY_DELAY_MS * (retryCount + 1));
+ } catch (InterruptedException ie) {
+ Thread.currentThread().interrupt();
+ throw new IOException("重试被中断", ie);
+ }
+ }
+ }
+ }
+
+ // 所有重试都失败了
+ Log.e(TAG, "网络请求重试 " + maxRetryCount + " 次后仍然失败");
+ if (lastException != null) {
+ throw lastException;
+ } else {
+ return response;
+ }
+ }
+ }
+
+ /**
+ * 网络质量监控拦截器
+ */
+ public class NetworkQualityInterceptor implements Interceptor {
+ @Override
+ public Response intercept(Chain chain) throws IOException {
+ long startTime = System.currentTimeMillis();
+
+ try {
+ Response response = chain.proceed(chain.request());
+ long endTime = System.currentTimeMillis();
+ long responseTime = endTime - startTime;
+
+ // 记录网络质量信息
+ logNetworkQuality(responseTime, true);
+
+ return response;
+
+ } catch (IOException e) {
+ long endTime = System.currentTimeMillis();
+ long responseTime = endTime - startTime;
+
+ // 记录网络质量信息
+ logNetworkQuality(responseTime, false);
+
+ throw e;
+ }
+ }
+
+ private void logNetworkQuality(long responseTime, boolean success) {
+ String status = success ? "成功" : "失败";
+
+ if (responseTime > 30000) { // 超过30秒
+ Log.e(TAG, String.format("网络响应极慢 %s: %dms", status, responseTime));
+ } else if (responseTime > 10000) { // 超过10秒
+ Log.w(TAG, String.format("网络响应缓慢 %s: %dms", status, responseTime));
+ } else if (responseTime > 3000) { // 超过3秒
+ Log.i(TAG, String.format("网络响应较慢 %s: %dms", status, responseTime));
+ } else {
+ Log.d(TAG, String.format("网络响应正常 %s: %dms", status, responseTime));
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ouxuan/oxface/utils/GlobalExceptionHandler.java b/app/src/main/java/com/ouxuan/oxface/utils/GlobalExceptionHandler.java
new file mode 100644
index 0000000..ff732f0
--- /dev/null
+++ b/app/src/main/java/com/ouxuan/oxface/utils/GlobalExceptionHandler.java
@@ -0,0 +1,294 @@
+package com.ouxuan.oxface.utils;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+import com.ouxuan.oxface.MainActivity;
+import com.ouxuan.oxface.network.NetworkStabilityManager;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+/**
+ * 全局异常处理器
+ * 用于24小时无人值守环境下的异常捕获和应用自动恢复
+ */
+public class GlobalExceptionHandler implements Thread.UncaughtExceptionHandler {
+
+ private static final String TAG = "GlobalExceptionHandler";
+ private static final String CRASH_LOG_DIR = "crash_logs";
+ private static final String CRASH_LOG_PREFIX = "crash_";
+ private static final int MAX_CRASH_LOGS = 10; // 最多保留10个崩溃日志文件
+ private static final long RESTART_DELAY = 3000; // 重启延迟3秒
+
+ private Thread.UncaughtExceptionHandler defaultHandler;
+ private Context context;
+ private boolean enableAutoRestart;
+
+ public GlobalExceptionHandler(Context context) {
+ this(context, true);
+ }
+
+ public GlobalExceptionHandler(Context context, boolean enableAutoRestart) {
+ this.context = context.getApplicationContext();
+ this.enableAutoRestart = enableAutoRestart;
+ this.defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
+ }
+
+ /**
+ * 初始化全局异常处理器
+ */
+ public void install() {
+ Thread.setDefaultUncaughtExceptionHandler(this);
+ Log.i(TAG, "全局异常处理器已安装,自动重启: " + enableAutoRestart);
+ }
+
+ @Override
+ public void uncaughtException(Thread thread, Throwable throwable) {
+ try {
+ Log.e(TAG, "捕获到未处理异常", throwable);
+
+ // 保存异常信息到文件
+ saveExceptionToFile(throwable, thread);
+
+ // 记录系统状态
+ recordSystemState();
+
+ // 如果启用自动重启,尝试重启应用
+ if (enableAutoRestart) {
+ restartApplication();
+ }
+
+ } catch (Exception e) {
+ Log.e(TAG, "处理异常时发生错误", e);
+ } finally {
+ // 调用默认异常处理器
+ if (defaultHandler != null) {
+ defaultHandler.uncaughtException(thread, throwable);
+ } else {
+ System.exit(1);
+ }
+ }
+ }
+
+ /**
+ * 保存异常信息到文件
+ */
+ private void saveExceptionToFile(Throwable throwable, Thread thread) {
+ try {
+ // 创建崩溃日志目录
+ File crashLogDir = new File(context.getFilesDir(), CRASH_LOG_DIR);
+ if (!crashLogDir.exists()) {
+ crashLogDir.mkdirs();
+ }
+
+ // 生成日志文件名
+ String timestamp = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss", Locale.getDefault()).format(new Date());
+ String fileName = CRASH_LOG_PREFIX + timestamp + ".log";
+ File crashLogFile = new File(crashLogDir, fileName);
+
+ // 写入异常信息
+ FileWriter fileWriter = new FileWriter(crashLogFile);
+ PrintWriter printWriter = new PrintWriter(fileWriter);
+
+ // 写入基本信息
+ printWriter.println("=== 应用崩溃日志 ===");
+ printWriter.println("时间: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(new Date()));
+ printWriter.println("线程: " + thread.getName() + " (ID: " + thread.getId() + ")");
+ printWriter.println("应用包名: " + context.getPackageName());
+ printWriter.println();
+
+ // 写入设备信息
+ printWriter.println("=== 设备信息 ===");
+ printWriter.println("设备型号: " + android.os.Build.MODEL);
+ printWriter.println("Android版本: " + android.os.Build.VERSION.RELEASE);
+ printWriter.println("API级别: " + android.os.Build.VERSION.SDK_INT);
+ printWriter.println("制造商: " + android.os.Build.MANUFACTURER);
+ printWriter.println();
+
+ // 写入内存信息
+ printWriter.println("=== 内存信息 ===");
+ Runtime runtime = Runtime.getRuntime();
+ long maxMemory = runtime.maxMemory();
+ long totalMemory = runtime.totalMemory();
+ long freeMemory = runtime.freeMemory();
+ long usedMemory = totalMemory - freeMemory;
+
+ printWriter.println("最大内存: " + (maxMemory / 1024 / 1024) + "MB");
+ printWriter.println("已分配内存: " + (totalMemory / 1024 / 1024) + "MB");
+ printWriter.println("空闲内存: " + (freeMemory / 1024 / 1024) + "MB");
+ printWriter.println("已使用内存: " + (usedMemory / 1024 / 1024) + "MB");
+ printWriter.println("内存使用率: " + String.format("%.1f%%", (float) usedMemory / maxMemory * 100));
+ printWriter.println();
+
+ // 写入异常堆栈
+ printWriter.println("=== 异常堆栈 ===");
+ throwable.printStackTrace(printWriter);
+
+ printWriter.close();
+ fileWriter.close();
+
+ Log.i(TAG, "崩溃日志已保存: " + crashLogFile.getAbsolutePath());
+
+ // 清理旧的日志文件
+ cleanupOldCrashLogs(crashLogDir);
+
+ } catch (IOException e) {
+ Log.e(TAG, "保存崩溃日志失败", e);
+ }
+ }
+
+ /**
+ * 记录系统状态
+ */
+ private void recordSystemState() {
+ try {
+ Log.i(TAG, "=== 崩溃时系统状态 ===");
+
+ // 记录内存使用情况
+ MemoryManager memoryManager = MemoryManager.getInstance(context);
+ float memoryUsage = memoryManager.getCurrentMemoryUsage();
+ Log.i(TAG, "内存使用率: " + String.format("%.1f%%", memoryUsage * 100));
+
+ // 记录网络状态
+ NetworkStabilityManager networkManager = NetworkStabilityManager.getInstance(context);
+ boolean networkAvailable = networkManager.isNetworkAvailable();
+ String networkType = networkManager.getNetworkTypeDescription();
+ Log.i(TAG, "网络状态: " + (networkAvailable ? "可用" : "不可用") + " (" + networkType + ")");
+
+ // 记录线程信息
+ Thread currentThread = Thread.currentThread();
+ ThreadGroup threadGroup = currentThread.getThreadGroup();
+ if (threadGroup != null) {
+ Log.i(TAG, "活跃线程数: " + threadGroup.activeCount());
+ }
+
+ Log.i(TAG, "========================");
+
+ } catch (Exception e) {
+ Log.e(TAG, "记录系统状态失败", e);
+ }
+ }
+
+ /**
+ * 重启应用程序
+ */
+ private void restartApplication() {
+ try {
+ Log.w(TAG, "准备重启应用程序...");
+
+ // 创建重启Intent
+ Intent restartIntent = new Intent(context, MainActivity.class);
+ restartIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+
+ // 使用AlarmManager延迟重启,确保当前进程完全结束
+ PendingIntent pendingIntent = PendingIntent.getActivity(
+ context,
+ 0,
+ restartIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
+ );
+
+ AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+ if (alarmManager != null) {
+ alarmManager.setExact(
+ AlarmManager.RTC_WAKEUP,
+ System.currentTimeMillis() + RESTART_DELAY,
+ pendingIntent
+ );
+
+ Log.i(TAG, "应用程序将在 " + RESTART_DELAY + "ms 后重启");
+ } else {
+ // 如果AlarmManager不可用,直接启动
+ context.startActivity(restartIntent);
+ }
+
+ // 退出当前进程
+ System.exit(0);
+
+ } catch (Exception e) {
+ Log.e(TAG, "重启应用程序失败", e);
+ // 强制退出
+ System.exit(1);
+ }
+ }
+
+ /**
+ * 清理旧的崩溃日志文件
+ */
+ private void cleanupOldCrashLogs(File crashLogDir) {
+ try {
+ File[] logFiles = crashLogDir.listFiles();
+ if (logFiles == null || logFiles.length <= MAX_CRASH_LOGS) {
+ return;
+ }
+
+ // 按修改时间排序
+ java.util.Arrays.sort(logFiles, new java.util.Comparator() {
+ @Override
+ public int compare(File f1, File f2) {
+ return Long.compare(f1.lastModified(), f2.lastModified());
+ }
+ });
+
+ // 删除最旧的文件
+ int filesToDelete = logFiles.length - MAX_CRASH_LOGS;
+ for (int i = 0; i < filesToDelete; i++) {
+ if (logFiles[i].delete()) {
+ Log.d(TAG, "已删除旧的崩溃日志: " + logFiles[i].getName());
+ }
+ }
+
+ } catch (Exception e) {
+ Log.e(TAG, "清理崩溃日志失败", e);
+ }
+ }
+
+ /**
+ * 设置是否启用自动重启
+ */
+ public void setAutoRestartEnabled(boolean enabled) {
+ this.enableAutoRestart = enabled;
+ Log.i(TAG, "自动重启设置: " + enabled);
+ }
+
+ /**
+ * 获取崩溃日志目录
+ */
+ public File getCrashLogDirectory() {
+ return new File(context.getFilesDir(), CRASH_LOG_DIR);
+ }
+
+ /**
+ * 获取最新的崩溃日志文件
+ */
+ public File getLatestCrashLog() {
+ File crashLogDir = getCrashLogDirectory();
+ if (!crashLogDir.exists()) {
+ return null;
+ }
+
+ File[] logFiles = crashLogDir.listFiles();
+ if (logFiles == null || logFiles.length == 0) {
+ return null;
+ }
+
+ // 找到最新的文件
+ File latestFile = logFiles[0];
+ for (File file : logFiles) {
+ if (file.lastModified() > latestFile.lastModified()) {
+ latestFile = file;
+ }
+ }
+
+ return latestFile;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ouxuan/oxface/utils/HealthMonitor.java b/app/src/main/java/com/ouxuan/oxface/utils/HealthMonitor.java
new file mode 100644
index 0000000..28ecc90
--- /dev/null
+++ b/app/src/main/java/com/ouxuan/oxface/utils/HealthMonitor.java
@@ -0,0 +1,406 @@
+package com.ouxuan.oxface.utils;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.Log;
+
+import com.ouxuan.oxface.network.NetworkStabilityManager;
+import com.ouxuan.oxface.utils.UtilCodeHelper;
+
+/**
+ * 健康监控器
+ * 用于24小时无人值守环境下的系统健康状态监控
+ */
+public class HealthMonitor {
+
+ private static final String TAG = "HealthMonitor";
+ private static final long HEALTH_CHECK_INTERVAL = 60 * 1000; // 1分钟检查间隔
+ private static final long CRITICAL_CHECK_INTERVAL = 10 * 1000; // 10秒紧急检查间隔
+ private static final int MAX_CONSECUTIVE_FAILURES = 3; // 最大连续失败次数
+
+ private static HealthMonitor instance;
+ private Context context;
+ private Handler healthHandler;
+ private boolean isMonitoring = false;
+ private HealthStatusListener healthStatusListener;
+
+ // 健康状态计数器
+ private int consecutiveMemoryFailures = 0;
+ private int consecutiveNetworkFailures = 0;
+ private long lastHealthCheckTime = 0;
+ private boolean isSystemHealthy = true;
+
+ public interface HealthStatusListener {
+ void onHealthStatusChanged(HealthStatus status);
+ void onCriticalIssueDetected(String issue);
+ void onSystemRecovered(String recoveryAction);
+ }
+
+ public enum HealthStatus {
+ HEALTHY, // 健康
+ WARNING, // 警告
+ CRITICAL, // 严重
+ SYSTEM_ERROR // 系统错误
+ }
+
+ public static class HealthReport {
+ public HealthStatus overallStatus;
+ public float memoryUsage;
+ public boolean networkAvailable;
+ public String networkType;
+ public boolean keepAliveActive;
+ public long uptime;
+ public int memoryFailures;
+ public int networkFailures;
+ public String lastIssue;
+ public String recommendations;
+ }
+
+ private HealthMonitor(Context context) {
+ this.context = context.getApplicationContext();
+ this.healthHandler = new Handler(Looper.getMainLooper());
+ }
+
+ public static synchronized HealthMonitor getInstance(Context context) {
+ if (instance == null) {
+ instance = new HealthMonitor(context);
+ }
+ return instance;
+ }
+
+ /**
+ * 开始健康检查
+ */
+ public void startHealthCheck(HealthStatusListener listener) {
+ if (isMonitoring) {
+ Log.i(TAG, "健康监控已在运行中");
+ return;
+ }
+
+ this.healthStatusListener = listener;
+ isMonitoring = true;
+
+ Log.i(TAG, "健康监控已启动");
+ LogManager.logOperation("HealthMonitor", "健康监控启动");
+
+ // 启动定期健康检查
+ scheduleHealthCheck();
+ }
+
+ /**
+ * 停止健康检查
+ */
+ public void stopHealthCheck() {
+ if (!isMonitoring) {
+ return;
+ }
+
+ isMonitoring = false;
+
+ if (healthHandler != null) {
+ healthHandler.removeCallbacksAndMessages(null);
+ }
+
+ Log.i(TAG, "健康监控已停止");
+ LogManager.logOperation("HealthMonitor", "健康监控停止");
+ }
+
+ /**
+ * 调度健康检查
+ */
+ private void scheduleHealthCheck() {
+ if (!isMonitoring) {
+ return;
+ }
+
+ long interval = isSystemHealthy ? HEALTH_CHECK_INTERVAL : CRITICAL_CHECK_INTERVAL;
+
+ healthHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ performHealthCheck();
+ scheduleHealthCheck();
+ }
+ }, interval);
+ }
+
+ /**
+ * 执行健康检查
+ */
+ public void performHealthCheck() {
+ try {
+ lastHealthCheckTime = System.currentTimeMillis();
+
+ Log.d(TAG, "开始健康检查");
+
+ HealthReport report = generateHealthReport();
+
+ // 分析健康状态
+ HealthStatus currentStatus = analyzeHealthStatus(report);
+
+ // 处理健康状态变化
+ handleHealthStatusChange(currentStatus, report);
+
+ // 记录健康检查结果
+ logHealthCheckResult(report);
+
+ Log.d(TAG, "健康检查完成,状态: " + currentStatus);
+
+ } catch (Exception e) {
+ Log.e(TAG, "健康检查失败", e);
+ LogManager.logError(TAG, "健康检查失败", e);
+ }
+ }
+
+ /**
+ * 生成健康报告
+ */
+ private HealthReport generateHealthReport() {
+ HealthReport report = new HealthReport();
+
+ try {
+ // 检查内存状态
+ MemoryManager memoryManager = MemoryManager.getInstance(context);
+ report.memoryUsage = memoryManager.getCurrentMemoryUsage();
+
+ // 检查网络状态
+ NetworkStabilityManager networkManager = NetworkStabilityManager.getInstance(context);
+ report.networkAvailable = networkManager.isNetworkAvailable();
+ report.networkType = networkManager.getNetworkTypeDescription();
+
+ // 检查保持活跃状态
+ KeepAliveManager keepAliveManager = KeepAliveManager.getInstance(context);
+ report.keepAliveActive = keepAliveManager.isKeepingAlive();
+
+ // 计算运行时间
+ report.uptime = System.currentTimeMillis() - getAppStartTime();
+
+ // 记录失败次数
+ report.memoryFailures = consecutiveMemoryFailures;
+ report.networkFailures = consecutiveNetworkFailures;
+
+ } catch (Exception e) {
+ Log.e(TAG, "生成健康报告失败", e);
+ report.lastIssue = "生成健康报告失败: " + e.getMessage();
+ }
+
+ return report;
+ }
+
+ /**
+ * 分析健康状态
+ */
+ private HealthStatus analyzeHealthStatus(HealthReport report) {
+ HealthStatus status = HealthStatus.HEALTHY;
+
+ // 检查内存使用率
+ if (report.memoryUsage > 0.95f) {
+ status = HealthStatus.CRITICAL;
+ consecutiveMemoryFailures++;
+ report.lastIssue = "内存使用率过高: " + String.format("%.1f%%", report.memoryUsage * 100);
+ } else if (report.memoryUsage > 0.85f) {
+ status = HealthStatus.WARNING;
+ consecutiveMemoryFailures++;
+ report.lastIssue = "内存使用率警告: " + String.format("%.1f%%", report.memoryUsage * 100);
+ } else {
+ consecutiveMemoryFailures = 0;
+ }
+
+ // 检查网络状态
+ if (!report.networkAvailable) {
+ if (status == HealthStatus.HEALTHY) {
+ status = HealthStatus.WARNING;
+ } else if (status == HealthStatus.WARNING) {
+ status = HealthStatus.CRITICAL;
+ }
+ consecutiveNetworkFailures++;
+ report.lastIssue = "网络连接不可用";
+ } else {
+ consecutiveNetworkFailures = 0;
+ }
+
+ // 检查连续失败次数
+ if (consecutiveMemoryFailures > MAX_CONSECUTIVE_FAILURES ||
+ consecutiveNetworkFailures > MAX_CONSECUTIVE_FAILURES) {
+ status = HealthStatus.SYSTEM_ERROR;
+ report.lastIssue = "系统连续失败次数过多";
+ }
+
+ // 检查保持活跃状态
+ if (!report.keepAliveActive && status == HealthStatus.HEALTHY) {
+ status = HealthStatus.WARNING;
+ report.lastIssue = "应用保持活跃功能未启用";
+ }
+
+ report.overallStatus = status;
+
+ // 生成建议
+ generateRecommendations(report);
+
+ return status;
+ }
+
+ /**
+ * 生成建议
+ */
+ private void generateRecommendations(HealthReport report) {
+ StringBuilder recommendations = new StringBuilder();
+
+ if (report.memoryUsage > 0.85f) {
+ recommendations.append("建议清理内存缓存; ");
+ }
+
+ if (!report.networkAvailable) {
+ recommendations.append("检查网络连接; ");
+ }
+
+ if (!report.keepAliveActive) {
+ recommendations.append("启用应用保持活跃功能; ");
+ }
+
+ if (report.memoryFailures > 0 || report.networkFailures > 0) {
+ recommendations.append("监控系统稳定性; ");
+ }
+
+ if (recommendations.length() == 0) {
+ recommendations.append("系统运行正常");
+ }
+
+ report.recommendations = recommendations.toString();
+ }
+
+ /**
+ * 处理健康状态变化
+ */
+ private void handleHealthStatusChange(HealthStatus currentStatus, HealthReport report) {
+ boolean statusChanged = (isSystemHealthy && currentStatus != HealthStatus.HEALTHY) ||
+ (!isSystemHealthy && currentStatus == HealthStatus.HEALTHY);
+
+ if (statusChanged) {
+ isSystemHealthy = (currentStatus == HealthStatus.HEALTHY);
+
+ if (healthStatusListener != null) {
+ healthStatusListener.onHealthStatusChanged(currentStatus);
+ }
+
+ LogManager.logOperation("HealthMonitor",
+ "健康状态变化: " + currentStatus + ", " + report.lastIssue);
+ }
+
+ // 处理严重问题
+ if (currentStatus == HealthStatus.CRITICAL || currentStatus == HealthStatus.SYSTEM_ERROR) {
+ handleCriticalIssue(report);
+ }
+
+ // 处理系统恢复
+ if (isSystemHealthy && (consecutiveMemoryFailures == 0 && consecutiveNetworkFailures == 0)) {
+ handleSystemRecovery();
+ }
+ }
+
+ /**
+ * 处理严重问题
+ */
+ private void handleCriticalIssue(HealthReport report) {
+ Log.w(TAG, "检测到严重问题: " + report.lastIssue);
+
+ if (healthStatusListener != null) {
+ healthStatusListener.onCriticalIssueDetected(report.lastIssue);
+ }
+
+ // 尝试自动恢复
+ attemptAutoRecovery(report);
+ }
+
+ /**
+ * 尝试自动恢复
+ */
+ private void attemptAutoRecovery(HealthReport report) {
+ try {
+ Log.i(TAG, "尝试自动恢复: " + report.overallStatus);
+
+ if (report.memoryUsage > 0.90f) {
+ // 执行内存清理
+ MemoryManager memoryManager = MemoryManager.getInstance(context);
+ memoryManager.performMemoryCleanup();
+ LogManager.logOperation("HealthMonitor", "自动执行内存清理");
+ }
+
+ if (!report.networkAvailable) {
+ // 网络问题通常需要等待恢复,记录日志
+ LogManager.logWarning(TAG, "网络不可用,等待网络恢复");
+ }
+
+ if (!report.keepAliveActive) {
+ // 记录保持活跃状态问题
+ LogManager.logWarning(TAG, "保持活跃功能未启用");
+ }
+
+ } catch (Exception e) {
+ Log.e(TAG, "自动恢复失败", e);
+ LogManager.logError(TAG, "自动恢复失败", e);
+ }
+ }
+
+ /**
+ * 处理系统恢复
+ */
+ private void handleSystemRecovery() {
+ if (healthStatusListener != null) {
+ healthStatusListener.onSystemRecovered("系统已恢复正常运行");
+ }
+
+ LogManager.logOperation("HealthMonitor", "系统已恢复正常运行");
+ }
+
+ /**
+ * 记录健康检查结果
+ */
+ private void logHealthCheckResult(HealthReport report) {
+ String message = String.format(
+ "健康检查 - 状态:%s, 内存:%.1f%%, 网络:%s, 保活:%s, 运行时间:%dh",
+ report.overallStatus,
+ report.memoryUsage * 100,
+ report.networkAvailable ? "正常" : "异常",
+ report.keepAliveActive ? "是" : "否",
+ report.uptime / (1000 * 60 * 60)
+ );
+
+ if (report.overallStatus == HealthStatus.HEALTHY) {
+ LogManager.logDebug(TAG, message);
+ } else {
+ LogManager.logWarning(TAG, message + " - " + report.lastIssue);
+ }
+ }
+
+ /**
+ * 获取应用启动时间(简化实现)
+ */
+ private long getAppStartTime() {
+ // 这里可以在Application中记录实际的启动时间
+ // 现在使用一个简化的实现
+ return System.currentTimeMillis() - (24 * 60 * 60 * 1000); // 假设已运行24小时
+ }
+
+ /**
+ * 获取当前健康报告
+ */
+ public HealthReport getCurrentHealthReport() {
+ return generateHealthReport();
+ }
+
+ /**
+ * 检查系统是否健康
+ */
+ public boolean isSystemHealthy() {
+ return isSystemHealthy;
+ }
+
+ /**
+ * 获取上次健康检查时间
+ */
+ public long getLastHealthCheckTime() {
+ return lastHealthCheckTime;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ouxuan/oxface/utils/KeepAliveManager.java b/app/src/main/java/com/ouxuan/oxface/utils/KeepAliveManager.java
new file mode 100644
index 0000000..62b3398
--- /dev/null
+++ b/app/src/main/java/com/ouxuan/oxface/utils/KeepAliveManager.java
@@ -0,0 +1,241 @@
+package com.ouxuan.oxface.utils;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.PowerManager;
+import android.util.Log;
+import android.view.WindowManager;
+
+/**
+ * 保持活跃管理器
+ * 用于24小时无人值守环境下保持应用活跃状态
+ */
+public class KeepAliveManager {
+
+ private static final String TAG = "KeepAliveManager";
+ private static final String WAKE_LOCK_TAG = "OxFace:KeepAlive";
+
+ private static KeepAliveManager instance;
+ private Context context;
+ private PowerManager powerManager;
+ private PowerManager.WakeLock wakeLock;
+ private boolean isKeepingAlive = false;
+
+ private KeepAliveManager(Context context) {
+ this.context = context.getApplicationContext();
+ this.powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ }
+
+ public static synchronized KeepAliveManager getInstance(Context context) {
+ if (instance == null) {
+ instance = new KeepAliveManager(context);
+ }
+ return instance;
+ }
+
+ /**
+ * 开始保持应用活跃
+ */
+ public void startKeepAlive(Activity activity) {
+ if (isKeepingAlive) {
+ Log.i(TAG, "应用已处于保持活跃状态");
+ return;
+ }
+
+ try {
+ // 保持屏幕常亮
+ if (activity != null) {
+ activity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ Log.i(TAG, "已设置屏幕常亮");
+ }
+ });
+ }
+
+ // 获取部分唤醒锁
+ if (powerManager != null) {
+ wakeLock = powerManager.newWakeLock(
+ PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP,
+ WAKE_LOCK_TAG
+ );
+ wakeLock.acquire();
+ Log.i(TAG, "已获取唤醒锁");
+ }
+
+ isKeepingAlive = true;
+ Log.i(TAG, "应用保持活跃已启动");
+
+ // 记录到日志
+ LogManager.logOperation("KeepAlive", "应用保持活跃功能已启动");
+
+ } catch (Exception e) {
+ Log.e(TAG, "启动保持活跃失败", e);
+ LogManager.logError(TAG, "启动保持活跃失败", e);
+ }
+ }
+
+ /**
+ * 停止保持应用活跃
+ */
+ public void stopKeepAlive(Activity activity) {
+ if (!isKeepingAlive) {
+ Log.i(TAG, "应用未处于保持活跃状态");
+ return;
+ }
+
+ try {
+ // 清除屏幕常亮标志
+ if (activity != null) {
+ activity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ Log.i(TAG, "已清除屏幕常亮设置");
+ }
+ });
+ }
+
+ // 释放唤醒锁
+ if (wakeLock != null && wakeLock.isHeld()) {
+ wakeLock.release();
+ wakeLock = null;
+ Log.i(TAG, "已释放唤醒锁");
+ }
+
+ isKeepingAlive = false;
+ Log.i(TAG, "应用保持活跃已停止");
+
+ // 记录到日志
+ LogManager.logOperation("KeepAlive", "应用保持活跃功能已停止");
+
+ } catch (Exception e) {
+ Log.e(TAG, "停止保持活跃失败", e);
+ LogManager.logError(TAG, "停止保持活跃失败", e);
+ }
+ }
+
+ /**
+ * 检查是否正在保持活跃
+ */
+ public boolean isKeepingAlive() {
+ return isKeepingAlive;
+ }
+
+ /**
+ * 检查唤醒锁状态
+ */
+ public boolean isWakeLockHeld() {
+ return wakeLock != null && wakeLock.isHeld();
+ }
+
+ /**
+ * 检查屏幕是否保持开启
+ */
+ public boolean isScreenOn() {
+ if (powerManager != null) {
+ return powerManager.isInteractive();
+ }
+ return false;
+ }
+
+ /**
+ * 获取电源管理信息
+ */
+ public String getPowerInfo() {
+ StringBuilder info = new StringBuilder();
+
+ try {
+ if (powerManager != null) {
+ info.append("屏幕状态: ").append(isScreenOn() ? "开启" : "关闭").append("\n");
+ info.append("唤醒锁状态: ").append(isWakeLockHeld() ? "持有" : "未持有").append("\n");
+ info.append("保持活跃状态: ").append(isKeepingAlive ? "是" : "否").append("\n");
+
+ // 检查是否处于省电模式
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
+ boolean isPowerSaveMode = powerManager.isPowerSaveMode();
+ info.append("省电模式: ").append(isPowerSaveMode ? "开启" : "关闭").append("\n");
+ }
+
+ // 检查是否忽略电池优化
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
+ boolean isIgnoringBatteryOptimizations =
+ powerManager.isIgnoringBatteryOptimizations(context.getPackageName());
+ info.append("忽略电池优化: ").append(isIgnoringBatteryOptimizations ? "是" : "否").append("\n");
+ }
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "获取电源信息失败", e);
+ info.append("获取电源信息失败: ").append(e.getMessage());
+ }
+
+ return info.toString();
+ }
+
+ /**
+ * 请求忽略电池优化(需要用户手动操作)
+ */
+ public boolean requestIgnoreBatteryOptimizations(Activity activity) {
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
+ try {
+ if (powerManager != null &&
+ !powerManager.isIgnoringBatteryOptimizations(context.getPackageName())) {
+
+ android.content.Intent intent = new android.content.Intent();
+ intent.setAction(android.provider.Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
+ intent.setData(android.net.Uri.parse("package:" + context.getPackageName()));
+
+ if (intent.resolveActivity(context.getPackageManager()) != null) {
+ activity.startActivity(intent);
+ Log.i(TAG, "已请求忽略电池优化");
+ LogManager.logOperation("KeepAlive", "请求忽略电池优化");
+ return true;
+ }
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "请求忽略电池优化失败", e);
+ LogManager.logError(TAG, "请求忽略电池优化失败", e);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 强制保持屏幕开启(用于关键操作期间)
+ */
+ public void forceKeepScreenOn(Activity activity, long durationMillis) {
+ if (activity == null) {
+ return;
+ }
+
+ Log.i(TAG, "强制保持屏幕开启 " + durationMillis + "ms");
+
+ activity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+
+ // 延时后清除标志
+ activity.getWindow().getDecorView().postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ if (!isKeepingAlive) { // 如果没有全局保持活跃,才清除标志
+ activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ Log.i(TAG, "临时屏幕保持已结束");
+ }
+ }
+ }, durationMillis);
+ }
+ });
+ }
+
+ /**
+ * 记录电源状态到日志
+ */
+ public void logPowerStatus() {
+ String powerInfo = getPowerInfo();
+ Log.i(TAG, "电源状态:\n" + powerInfo);
+ LogManager.logInfo(TAG, "电源状态: " + powerInfo.replace("\n", ", "));
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ouxuan/oxface/utils/LogManager.java b/app/src/main/java/com/ouxuan/oxface/utils/LogManager.java
new file mode 100644
index 0000000..486270b
--- /dev/null
+++ b/app/src/main/java/com/ouxuan/oxface/utils/LogManager.java
@@ -0,0 +1,375 @@
+package com.ouxuan.oxface.utils;
+
+import android.content.Context;
+import android.util.Log;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+/**
+ * 日志管理器
+ * 用于24小时无人值守环境下的日志记录和管理
+ */
+public class LogManager {
+
+ private static final String TAG = "LogManager";
+ private static final String LOG_DIR = "operation_logs";
+ private static final String LOG_FILE_NAME = "oxface_operation.log";
+ private static final long MAX_LOG_SIZE = 10 * 1024 * 1024; // 10MB
+ private static final int MAX_LOG_FILES = 5; // 最多保留5个日志文件
+ private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS";
+
+ private static LogManager instance;
+ private Context context;
+ private File logDir;
+ private File currentLogFile;
+ private BlockingQueue logQueue;
+ private Thread logWriterThread;
+ private volatile boolean isRunning = false;
+ private SimpleDateFormat dateFormat;
+
+ private static class LogEntry {
+ final long timestamp;
+ final String level;
+ final String tag;
+ final String message;
+ final Throwable throwable;
+
+ LogEntry(String level, String tag, String message, Throwable throwable) {
+ this.timestamp = System.currentTimeMillis();
+ this.level = level;
+ this.tag = tag;
+ this.message = message;
+ this.throwable = throwable;
+ }
+ }
+
+ private LogManager(Context context) {
+ this.context = context.getApplicationContext();
+ this.dateFormat = new SimpleDateFormat(DATE_FORMAT, Locale.getDefault());
+ this.logQueue = new LinkedBlockingQueue<>();
+
+ // 创建日志目录
+ this.logDir = new File(context.getFilesDir(), LOG_DIR);
+ if (!logDir.exists()) {
+ logDir.mkdirs();
+ }
+
+ // 设置当前日志文件
+ this.currentLogFile = new File(logDir, LOG_FILE_NAME);
+ }
+
+ public static synchronized LogManager getInstance(Context context) {
+ if (instance == null) {
+ instance = new LogManager(context);
+ }
+ return instance;
+ }
+
+ /**
+ * 启动日志管理器
+ */
+ public void start() {
+ if (isRunning) {
+ return;
+ }
+
+ isRunning = true;
+ logWriterThread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ runLogWriter();
+ }
+ });
+ logWriterThread.setName("LogWriter");
+ logWriterThread.setDaemon(true);
+ logWriterThread.start();
+
+ Log.i(TAG, "日志管理器已启动");
+ logInfo(TAG, "日志管理器启动");
+ }
+
+ /**
+ * 停止日志管理器
+ */
+ public void stop() {
+ if (!isRunning) {
+ return;
+ }
+
+ isRunning = false;
+
+ if (logWriterThread != null) {
+ logWriterThread.interrupt();
+ try {
+ logWriterThread.join(5000); // 等待最多5秒
+ } catch (InterruptedException e) {
+ Log.w(TAG, "等待日志写入线程结束被中断");
+ }
+ }
+
+ // 处理队列中剩余的日志
+ processRemainingLogs();
+
+ Log.i(TAG, "日志管理器已停止");
+ }
+
+ /**
+ * 记录调试日志
+ */
+ public static void logDebug(String tag, String message) {
+ if (instance != null) {
+ instance.addLogEntry("DEBUG", tag, message, null);
+ }
+ }
+
+ /**
+ * 记录信息日志
+ */
+ public static void logInfo(String tag, String message) {
+ if (instance != null) {
+ instance.addLogEntry("INFO", tag, message, null);
+ }
+ }
+
+ /**
+ * 记录警告日志
+ */
+ public static void logWarning(String tag, String message) {
+ if (instance != null) {
+ instance.addLogEntry("WARN", tag, message, null);
+ }
+ }
+
+ /**
+ * 记录错误日志
+ */
+ public static void logError(String tag, String message) {
+ if (instance != null) {
+ instance.addLogEntry("ERROR", tag, message, null);
+ }
+ }
+
+ /**
+ * 记录错误日志(带异常)
+ */
+ public static void logError(String tag, String message, Throwable throwable) {
+ if (instance != null) {
+ instance.addLogEntry("ERROR", tag, message, throwable);
+ }
+ }
+
+ /**
+ * 记录操作日志
+ */
+ public static void logOperation(String operation, String details) {
+ if (instance != null) {
+ instance.addLogEntry("OPERATION", "App", operation + ": " + details, null);
+ }
+ }
+
+ /**
+ * 记录性能日志
+ */
+ public static void logPerformance(String operation, long duration) {
+ if (instance != null) {
+ String message = String.format("%s 耗时: %dms", operation, duration);
+ instance.addLogEntry("PERFORMANCE", "App", message, null);
+ }
+ }
+
+ /**
+ * 添加日志条目到队列
+ */
+ private void addLogEntry(String level, String tag, String message, Throwable throwable) {
+ try {
+ LogEntry entry = new LogEntry(level, tag, message, throwable);
+ if (!logQueue.offer(entry)) {
+ Log.w(TAG, "日志队列已满,丢弃日志: " + message);
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "添加日志条目失败", e);
+ }
+ }
+
+ /**
+ * 运行日志写入器
+ */
+ private void runLogWriter() {
+ BufferedWriter writer = null;
+
+ try {
+ while (isRunning || !logQueue.isEmpty()) {
+ try {
+ LogEntry entry = logQueue.take(); // 阻塞等待日志条目
+
+ // 检查是否需要轮转日志文件
+ checkLogRotation();
+
+ // 打开或重新打开文件
+ if (writer == null) {
+ writer = new BufferedWriter(new FileWriter(currentLogFile, true));
+ }
+
+ // 写入日志
+ writeLogEntry(writer, entry);
+
+ // 定期刷新缓冲区
+ writer.flush();
+
+ } catch (InterruptedException e) {
+ if (!isRunning) {
+ break;
+ }
+ } catch (IOException e) {
+ Log.e(TAG, "写入日志失败", e);
+
+ // 重新打开文件
+ if (writer != null) {
+ try {
+ writer.close();
+ } catch (IOException ignored) {
+ }
+ writer = null;
+ }
+ }
+ }
+ } finally {
+ if (writer != null) {
+ try {
+ writer.close();
+ } catch (IOException e) {
+ Log.e(TAG, "关闭日志文件失败", e);
+ }
+ }
+ }
+ }
+
+ /**
+ * 写入日志条目
+ */
+ private void writeLogEntry(BufferedWriter writer, LogEntry entry) throws IOException {
+ String timestamp = dateFormat.format(new Date(entry.timestamp));
+ String logLine = String.format("[%s] %s/%s: %s%n",
+ timestamp, entry.level, entry.tag, entry.message);
+
+ writer.write(logLine);
+
+ // 如果有异常,写入堆栈信息
+ if (entry.throwable != null) {
+ writer.write("Exception: " + entry.throwable.toString() + "\n");
+ StackTraceElement[] stackTrace = entry.throwable.getStackTrace();
+ for (StackTraceElement element : stackTrace) {
+ writer.write(" at " + element.toString() + "\n");
+ }
+ }
+ }
+
+ /**
+ * 检查日志轮转
+ */
+ private void checkLogRotation() {
+ if (currentLogFile.exists() && currentLogFile.length() > MAX_LOG_SIZE) {
+ rotateLogFile();
+ }
+ }
+
+ /**
+ * 轮转日志文件
+ */
+ private void rotateLogFile() {
+ try {
+ String timestamp = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss", Locale.getDefault()).format(new Date());
+ String rotatedFileName = "oxface_operation_" + timestamp + ".log";
+ File rotatedFile = new File(logDir, rotatedFileName);
+
+ if (currentLogFile.renameTo(rotatedFile)) {
+ Log.i(TAG, "日志文件轮转成功: " + rotatedFileName);
+
+ // 清理旧的日志文件
+ cleanupOldLogFiles();
+ } else {
+ Log.w(TAG, "日志文件轮转失败");
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "日志轮转失败", e);
+ }
+ }
+
+ /**
+ * 清理旧的日志文件
+ */
+ private void cleanupOldLogFiles() {
+ try {
+ File[] logFiles = logDir.listFiles();
+ if (logFiles == null || logFiles.length <= MAX_LOG_FILES) {
+ return;
+ }
+
+ // 按修改时间排序
+ java.util.Arrays.sort(logFiles, new java.util.Comparator() {
+ @Override
+ public int compare(File f1, File f2) {
+ return Long.compare(f1.lastModified(), f2.lastModified());
+ }
+ });
+
+ // 删除最旧的文件(保留当前日志文件)
+ int filesToDelete = logFiles.length - MAX_LOG_FILES;
+ for (int i = 0; i < filesToDelete; i++) {
+ if (!logFiles[i].equals(currentLogFile) && logFiles[i].delete()) {
+ Log.d(TAG, "已删除旧日志文件: " + logFiles[i].getName());
+ }
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "清理旧日志文件失败", e);
+ }
+ }
+
+ /**
+ * 处理队列中剩余的日志
+ */
+ private void processRemainingLogs() {
+ if (logQueue.isEmpty()) {
+ return;
+ }
+
+ try (BufferedWriter writer = new BufferedWriter(new FileWriter(currentLogFile, true))) {
+ LogEntry entry;
+ while ((entry = logQueue.poll()) != null) {
+ writeLogEntry(writer, entry);
+ }
+ writer.flush();
+ } catch (IOException e) {
+ Log.e(TAG, "处理剩余日志失败", e);
+ }
+ }
+
+ /**
+ * 获取日志目录
+ */
+ public File getLogDirectory() {
+ return logDir;
+ }
+
+ /**
+ * 获取当前日志文件
+ */
+ public File getCurrentLogFile() {
+ return currentLogFile;
+ }
+
+ /**
+ * 获取日志文件大小
+ */
+ public long getLogFileSize() {
+ return currentLogFile.exists() ? currentLogFile.length() : 0;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ouxuan/oxface/utils/MaintenanceScheduler.java b/app/src/main/java/com/ouxuan/oxface/utils/MaintenanceScheduler.java
new file mode 100644
index 0000000..20123f6
--- /dev/null
+++ b/app/src/main/java/com/ouxuan/oxface/utils/MaintenanceScheduler.java
@@ -0,0 +1,533 @@
+package com.ouxuan.oxface.utils;
+
+import android.content.Context;
+import android.util.Log;
+
+import com.bumptech.glide.Glide;
+import com.ouxuan.oxface.network.NetworkManager;
+import com.ouxuan.oxface.network.NetworkStabilityManager;
+
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 维护任务调度器
+ * 用于24小时无人值守环境下的定时维护任务
+ */
+public class MaintenanceScheduler {
+
+ private static final String TAG = "MaintenanceScheduler";
+
+ // 维护间隔时间(毫秒)
+ private static final long LIGHT_MAINTENANCE_INTERVAL = 30 * 60 * 1000; // 30分钟 - 轻度维护
+ private static final long MEDIUM_MAINTENANCE_INTERVAL = 2 * 60 * 60 * 1000; // 2小时 - 中度维护
+ private static final long HEAVY_MAINTENANCE_INTERVAL = 6 * 60 * 60 * 1000; // 6小时 - 重度维护
+ private static final long DAILY_MAINTENANCE_INTERVAL = 24 * 60 * 60 * 1000; // 24小时 - 每日维护
+
+ private static MaintenanceScheduler instance;
+ private Context context;
+ private ScheduledExecutorService scheduledExecutor;
+ private boolean isRunning = false;
+
+ // 维护任务计数器
+ private int lightMaintenanceCount = 0;
+ private int mediumMaintenanceCount = 0;
+ private int heavyMaintenanceCount = 0;
+ private int dailyMaintenanceCount = 0;
+
+ private MaintenanceScheduler(Context context) {
+ this.context = context.getApplicationContext();
+ this.scheduledExecutor = Executors.newScheduledThreadPool(2);
+ }
+
+ public static synchronized MaintenanceScheduler getInstance(Context context) {
+ if (instance == null) {
+ instance = new MaintenanceScheduler(context);
+ }
+ return instance;
+ }
+
+ /**
+ * 启动维护任务调度
+ */
+ public void startMaintenance() {
+ if (isRunning) {
+ Log.i(TAG, "维护调度器已在运行中");
+ return;
+ }
+
+ isRunning = true;
+
+ // 调度轻度维护任务 - 每30分钟
+ scheduledExecutor.scheduleAtFixedRate(
+ new Runnable() {
+ @Override
+ public void run() {
+ performLightMaintenance();
+ }
+ },
+ LIGHT_MAINTENANCE_INTERVAL,
+ LIGHT_MAINTENANCE_INTERVAL,
+ TimeUnit.MILLISECONDS
+ );
+
+ // 调度中度维护任务 - 每2小时
+ scheduledExecutor.scheduleAtFixedRate(
+ new Runnable() {
+ @Override
+ public void run() {
+ performMediumMaintenance();
+ }
+ },
+ MEDIUM_MAINTENANCE_INTERVAL,
+ MEDIUM_MAINTENANCE_INTERVAL,
+ TimeUnit.MILLISECONDS
+ );
+
+ // 调度重度维护任务 - 每6小时
+ scheduledExecutor.scheduleAtFixedRate(
+ new Runnable() {
+ @Override
+ public void run() {
+ performHeavyMaintenance();
+ }
+ },
+ HEAVY_MAINTENANCE_INTERVAL,
+ HEAVY_MAINTENANCE_INTERVAL,
+ TimeUnit.MILLISECONDS
+ );
+
+ // 调度每日维护任务 - 每24小时
+ scheduledExecutor.scheduleAtFixedRate(
+ new Runnable() {
+ @Override
+ public void run() {
+ performDailyMaintenance();
+ }
+ },
+ DAILY_MAINTENANCE_INTERVAL,
+ DAILY_MAINTENANCE_INTERVAL,
+ TimeUnit.MILLISECONDS
+ );
+
+ Log.i(TAG, "维护任务调度器已启动");
+ LogManager.logOperation("MaintenanceScheduler", "维护任务调度器启动");
+ }
+
+ /**
+ * 停止维护任务调度
+ */
+ public void stopMaintenance() {
+ if (!isRunning) {
+ return;
+ }
+
+ isRunning = false;
+
+ if (scheduledExecutor != null && !scheduledExecutor.isShutdown()) {
+ scheduledExecutor.shutdown();
+ try {
+ if (!scheduledExecutor.awaitTermination(30, TimeUnit.SECONDS)) {
+ scheduledExecutor.shutdownNow();
+ }
+ } catch (InterruptedException e) {
+ scheduledExecutor.shutdownNow();
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ Log.i(TAG, "维护任务调度器已停止");
+ LogManager.logOperation("MaintenanceScheduler", "维护任务调度器停止");
+ }
+
+ /**
+ * 轻度维护任务 - 每30分钟执行
+ */
+ private void performLightMaintenance() {
+ try {
+ lightMaintenanceCount++;
+ Log.d(TAG, "开始轻度维护任务 #" + lightMaintenanceCount);
+
+ long startTime = System.currentTimeMillis();
+
+ // 检查内存状态
+ checkMemoryStatus();
+
+ // 检查网络状态
+ checkNetworkStatus();
+
+ // 轻量级垃圾回收建议
+ System.gc();
+
+ long duration = System.currentTimeMillis() - startTime;
+ Log.d(TAG, "轻度维护任务完成,耗时: " + duration + "ms");
+ LogManager.logPerformance("轻度维护任务", duration);
+
+ } catch (Exception e) {
+ Log.e(TAG, "轻度维护任务失败", e);
+ LogManager.logError(TAG, "轻度维护任务失败", e);
+ }
+ }
+
+ /**
+ * 中度维护任务 - 每2小时执行
+ */
+ private void performMediumMaintenance() {
+ try {
+ mediumMaintenanceCount++;
+ Log.i(TAG, "开始中度维护任务 #" + mediumMaintenanceCount);
+
+ long startTime = System.currentTimeMillis();
+
+ // 执行内存清理
+ performMemoryCleanup();
+
+ // 检查应用保持活跃状态
+ checkKeepAliveStatus();
+
+ // 执行网络连接重置
+ resetNetworkConnections();
+
+ // 更强力的垃圾回收
+ for (int i = 0; i < 3; i++) {
+ System.gc();
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ break;
+ }
+ }
+
+ long duration = System.currentTimeMillis() - startTime;
+ Log.i(TAG, "中度维护任务完成,耗时: " + duration + "ms");
+ LogManager.logPerformance("中度维护任务", duration);
+
+ } catch (Exception e) {
+ Log.e(TAG, "中度维护任务失败", e);
+ LogManager.logError(TAG, "中度维护任务失败", e);
+ }
+ }
+
+ /**
+ * 重度维护任务 - 每6小时执行
+ */
+ private void performHeavyMaintenance() {
+ try {
+ heavyMaintenanceCount++;
+ Log.w(TAG, "开始重度维护任务 #" + heavyMaintenanceCount);
+
+ long startTime = System.currentTimeMillis();
+
+ // 执行深度内存清理
+ performDeepMemoryCleanup();
+
+ // 清理磁盘缓存
+ clearDiskCaches();
+
+ // 重新初始化网络管理器
+ reinitializeNetworkManager();
+
+ // 执行健康检查
+ performSystemHealthCheck();
+
+ // 清理日志文件
+ cleanupLogFiles();
+
+ long duration = System.currentTimeMillis() - startTime;
+ Log.w(TAG, "重度维护任务完成,耗时: " + duration + "ms");
+ LogManager.logPerformance("重度维护任务", duration);
+
+ } catch (Exception e) {
+ Log.e(TAG, "重度维护任务失败", e);
+ LogManager.logError(TAG, "重度维护任务失败", e);
+ }
+ }
+
+ /**
+ * 每日维护任务 - 每24小时执行
+ */
+ private void performDailyMaintenance() {
+ try {
+ dailyMaintenanceCount++;
+ Log.w(TAG, "开始每日维护任务 #" + dailyMaintenanceCount);
+
+ long startTime = System.currentTimeMillis();
+
+ // 生成系统运行报告
+ generateSystemReport();
+
+ // 执行全面系统清理
+ performComprehensiveCleanup();
+
+ // 重置所有计数器和统计数据
+ resetCounters();
+
+ // 验证系统完整性
+ validateSystemIntegrity();
+
+ long duration = System.currentTimeMillis() - startTime;
+ Log.w(TAG, "每日维护任务完成,耗时: " + duration + "ms");
+ LogManager.logPerformance("每日维护任务", duration);
+ LogManager.logOperation("MaintenanceScheduler", "完成第" + dailyMaintenanceCount + "次每日维护");
+
+ } catch (Exception e) {
+ Log.e(TAG, "每日维护任务失败", e);
+ LogManager.logError(TAG, "每日维护任务失败", e);
+ }
+ }
+
+ /**
+ * 检查内存状态
+ */
+ private void checkMemoryStatus() {
+ MemoryManager memoryManager = MemoryManager.getInstance(context);
+ float memoryUsage = memoryManager.getCurrentMemoryUsage();
+
+ if (memoryUsage > 0.80f) {
+ Log.w(TAG, "内存使用率较高: " + String.format("%.1f%%", memoryUsage * 100));
+ memoryManager.performMemoryCleanup();
+ }
+ }
+
+ /**
+ * 检查网络状态
+ */
+ private void checkNetworkStatus() {
+ NetworkStabilityManager networkManager = NetworkStabilityManager.getInstance(context);
+ boolean networkAvailable = networkManager.isNetworkAvailable();
+
+ if (!networkAvailable) {
+ Log.w(TAG, "网络连接不可用");
+ LogManager.logWarning(TAG, "维护检查发现网络连接不可用");
+ }
+ }
+
+ /**
+ * 执行内存清理
+ */
+ private void performMemoryCleanup() {
+ MemoryManager memoryManager = MemoryManager.getInstance(context);
+ memoryManager.performMemoryCleanup();
+
+ // 清理Glide缓存
+ Glide.get(context).clearMemory();
+
+ Log.d(TAG, "内存清理完成");
+ }
+
+ /**
+ * 检查保持活跃状态
+ */
+ private void checkKeepAliveStatus() {
+ KeepAliveManager keepAliveManager = KeepAliveManager.getInstance(context);
+ boolean isKeepingAlive = keepAliveManager.isKeepingAlive();
+
+ if (!isKeepingAlive) {
+ Log.w(TAG, "保持活跃功能未启用");
+ LogManager.logWarning(TAG, "维护检查发现保持活跃功能未启用");
+ }
+
+ // 记录电源状态
+ keepAliveManager.logPowerStatus();
+ }
+
+ /**
+ * 重置网络连接
+ */
+ private void resetNetworkConnections() {
+ try {
+ // 这里可以添加重置网络连接的逻辑
+ // 例如重新初始化HTTP客户端等
+ Log.d(TAG, "网络连接重置完成");
+ } catch (Exception e) {
+ Log.e(TAG, "重置网络连接失败", e);
+ }
+ }
+
+ /**
+ * 执行深度内存清理
+ */
+ private void performDeepMemoryCleanup() {
+ MemoryManager memoryManager = MemoryManager.getInstance(context);
+
+ // 多次执行内存清理
+ for (int i = 0; i < 3; i++) {
+ memoryManager.performMemoryCleanup();
+ try {
+ Thread.sleep(200);
+ } catch (InterruptedException e) {
+ break;
+ }
+ }
+
+ Log.i(TAG, "深度内存清理完成");
+ }
+
+ /**
+ * 清理磁盘缓存
+ */
+ private void clearDiskCaches() {
+ // 在后台线程中清理磁盘缓存
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Glide.get(context).clearDiskCache();
+ Log.i(TAG, "磁盘缓存清理完成");
+ } catch (Exception e) {
+ Log.e(TAG, "磁盘缓存清理失败", e);
+ }
+ }
+ }).start();
+ }
+
+ /**
+ * 重新初始化网络管理器
+ */
+ private void reinitializeNetworkManager() {
+ try {
+ NetworkManager networkManager = NetworkManager.getInstance();
+ // 这里可以添加重新初始化网络管理器的逻辑
+ Log.i(TAG, "网络管理器重新初始化完成");
+ } catch (Exception e) {
+ Log.e(TAG, "重新初始化网络管理器失败", e);
+ }
+ }
+
+ /**
+ * 执行系统健康检查
+ */
+ private void performSystemHealthCheck() {
+ HealthMonitor healthMonitor = HealthMonitor.getInstance(context);
+ healthMonitor.performHealthCheck();
+
+ HealthMonitor.HealthReport report = healthMonitor.getCurrentHealthReport();
+ Log.i(TAG, "系统健康检查完成,状态: " + report.overallStatus);
+ }
+
+ /**
+ * 清理日志文件
+ */
+ private void cleanupLogFiles() {
+ try {
+ // LogManager会自动处理日志轮转和清理
+ LogManager logManager = LogManager.getInstance(context);
+ Log.d(TAG, "日志文件清理检查完成");
+ } catch (Exception e) {
+ Log.e(TAG, "日志文件清理失败", e);
+ }
+ }
+
+ /**
+ * 生成系统运行报告
+ */
+ private void generateSystemReport() {
+ try {
+ HealthMonitor healthMonitor = HealthMonitor.getInstance(context);
+ HealthMonitor.HealthReport report = healthMonitor.getCurrentHealthReport();
+
+ String reportMessage = String.format(
+ "系统运行报告 - 运行时间: %d小时, 内存使用: %.1f%%, 网络: %s, 维护次数: L%d/M%d/H%d/D%d",
+ report.uptime / (1000 * 60 * 60),
+ report.memoryUsage * 100,
+ report.networkAvailable ? "正常" : "异常",
+ lightMaintenanceCount,
+ mediumMaintenanceCount,
+ heavyMaintenanceCount,
+ dailyMaintenanceCount
+ );
+
+ Log.i(TAG, reportMessage);
+ LogManager.logOperation("SystemReport", reportMessage);
+
+ } catch (Exception e) {
+ Log.e(TAG, "生成系统报告失败", e);
+ }
+ }
+
+ /**
+ * 执行全面系统清理
+ */
+ private void performComprehensiveCleanup() {
+ // 执行所有级别的清理任务
+ performDeepMemoryCleanup();
+ clearDiskCaches();
+
+ // 等待一段时间让清理任务完成
+ try {
+ Thread.sleep(2000);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+
+ Log.i(TAG, "全面系统清理完成");
+ }
+
+ /**
+ * 重置计数器
+ */
+ private void resetCounters() {
+ lightMaintenanceCount = 0;
+ mediumMaintenanceCount = 0;
+ heavyMaintenanceCount = 0;
+ // 不重置每日维护计数器,用于跟踪总运行天数
+
+ Log.d(TAG, "维护任务计数器已重置");
+ }
+
+ /**
+ * 验证系统完整性
+ */
+ private void validateSystemIntegrity() {
+ try {
+ // 检查关键组件是否正常运行
+ boolean memoryManagerOk = MemoryManager.getInstance(context).isMemoryHealthy();
+ boolean networkManagerOk = NetworkStabilityManager.getInstance(context).isNetworkAvailable();
+ boolean keepAliveOk = KeepAliveManager.getInstance(context).isKeepingAlive();
+
+ String integrityReport = String.format(
+ "系统完整性检查 - 内存管理: %s, 网络管理: %s, 保持活跃: %s",
+ memoryManagerOk ? "正常" : "异常",
+ networkManagerOk ? "正常" : "异常",
+ keepAliveOk ? "正常" : "异常"
+ );
+
+ Log.i(TAG, integrityReport);
+ LogManager.logOperation("SystemIntegrity", integrityReport);
+
+ } catch (Exception e) {
+ Log.e(TAG, "系统完整性验证失败", e);
+ LogManager.logError(TAG, "系统完整性验证失败", e);
+ }
+ }
+
+ /**
+ * 获取维护统计信息
+ */
+ public String getMaintenanceStats() {
+ return String.format(
+ "维护统计 - 轻度: %d次, 中度: %d次, 重度: %d次, 每日: %d次",
+ lightMaintenanceCount,
+ mediumMaintenanceCount,
+ heavyMaintenanceCount,
+ dailyMaintenanceCount
+ );
+ }
+
+ /**
+ * 立即执行维护任务
+ */
+ public void performImmediateMaintenance() {
+ Log.i(TAG, "立即执行维护任务");
+
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ performMediumMaintenance();
+ }
+ }).start();
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ouxuan/oxface/utils/MemoryManager.java b/app/src/main/java/com/ouxuan/oxface/utils/MemoryManager.java
new file mode 100644
index 0000000..9b710a6
--- /dev/null
+++ b/app/src/main/java/com/ouxuan/oxface/utils/MemoryManager.java
@@ -0,0 +1,245 @@
+package com.ouxuan.oxface.utils;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.util.Log;
+
+import com.bumptech.glide.Glide;
+
+/**
+ * 内存管理器
+ * 用于24小时无人值守环境下的内存监控和优化
+ */
+public class MemoryManager {
+
+ private static final String TAG = "MemoryManager";
+ private static final float MEMORY_THRESHOLD = 0.85f; // 85%内存使用率阈值
+ private static final float CRITICAL_MEMORY_THRESHOLD = 0.95f; // 95%临界阈值
+ private static final long MEMORY_CHECK_INTERVAL = 30 * 1000; // 30秒检查间隔
+
+ private static MemoryManager instance;
+ private Context context;
+ private boolean isMonitoring = false;
+
+ private MemoryManager(Context context) {
+ this.context = context.getApplicationContext();
+ }
+
+ public static synchronized MemoryManager getInstance(Context context) {
+ if (instance == null) {
+ instance = new MemoryManager(context);
+ }
+ return instance;
+ }
+
+ /**
+ * 开始内存监控
+ */
+ public void startMemoryMonitoring() {
+ if (isMonitoring) {
+ return;
+ }
+
+ isMonitoring = true;
+ Log.i(TAG, "开始内存监控");
+
+ Thread monitorThread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ while (isMonitoring) {
+ try {
+ monitorMemory();
+ Thread.sleep(MEMORY_CHECK_INTERVAL);
+ } catch (InterruptedException e) {
+ Log.w(TAG, "内存监控线程被中断");
+ break;
+ } catch (Exception e) {
+ Log.e(TAG, "内存监控异常", e);
+ }
+ }
+ }
+ });
+ monitorThread.setName("MemoryMonitor");
+ monitorThread.setDaemon(true);
+ monitorThread.start();
+ }
+
+ /**
+ * 停止内存监控
+ */
+ public void stopMemoryMonitoring() {
+ isMonitoring = false;
+ Log.i(TAG, "停止内存监控");
+ }
+
+ /**
+ * 监控内存使用情况
+ */
+ public void monitorMemory() {
+ try {
+ Runtime runtime = Runtime.getRuntime();
+ long maxMemory = runtime.maxMemory();
+ long totalMemory = runtime.totalMemory();
+ long freeMemory = runtime.freeMemory();
+ long usedMemory = totalMemory - freeMemory;
+ float memoryUsage = (float) usedMemory / maxMemory;
+
+ // 记录详细内存信息
+ Log.d(TAG, String.format("内存使用情况 - 使用率: %.1f%%, 已用: %dMB, 最大: %dMB",
+ memoryUsage * 100, usedMemory / (1024 * 1024), maxMemory / (1024 * 1024)));
+
+ // 检查内存使用率
+ if (memoryUsage > CRITICAL_MEMORY_THRESHOLD) {
+ // 临界状态,强制清理
+ Log.w(TAG, "内存使用率达到临界状态: " + String.format("%.1f%%", memoryUsage * 100));
+ performCriticalMemoryCleanup();
+ } else if (memoryUsage > MEMORY_THRESHOLD) {
+ // 超过阈值,执行清理
+ Log.w(TAG, "内存使用率过高: " + String.format("%.1f%%", memoryUsage * 100));
+ performMemoryCleanup();
+ }
+
+ // 检查系统内存情况
+ checkSystemMemory();
+
+ } catch (Exception e) {
+ Log.e(TAG, "内存监控失败", e);
+ }
+ }
+
+ /**
+ * 执行内存清理
+ */
+ public void performMemoryCleanup() {
+ try {
+ Log.i(TAG, "开始内存清理");
+
+ // 清理Glide图片缓存
+ if (context != null) {
+ Glide.get(context).clearMemory();
+ Log.d(TAG, "已清理Glide内存缓存");
+ }
+
+ // 建议垃圾回收
+ System.gc();
+ Log.d(TAG, "已触发垃圾回收");
+
+ // 记录清理后的内存状态
+ logMemoryStatus("清理后");
+
+ } catch (Exception e) {
+ Log.e(TAG, "内存清理失败", e);
+ }
+ }
+
+ /**
+ * 执行临界内存清理
+ */
+ private void performCriticalMemoryCleanup() {
+ try {
+ Log.w(TAG, "执行临界内存清理");
+
+ // 清理所有可能的缓存
+ if (context != null) {
+ Glide.get(context).clearMemory();
+ // 强制清理磁盘缓存(在后台线程中)
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ Glide.get(context).clearDiskCache();
+ }
+ }).start();
+ }
+
+ // 多次触发垃圾回收
+ for (int i = 0; i < 3; i++) {
+ System.gc();
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ break;
+ }
+ }
+
+ Log.w(TAG, "临界内存清理完成");
+
+ } catch (Exception e) {
+ Log.e(TAG, "临界内存清理失败", e);
+ }
+ }
+
+ /**
+ * 检查系统内存情况
+ */
+ private void checkSystemMemory() {
+ try {
+ ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+ if (activityManager != null) {
+ ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
+ activityManager.getMemoryInfo(memoryInfo);
+
+ float availableMemoryPercentage = (float) memoryInfo.availMem / memoryInfo.totalMem;
+
+ Log.d(TAG, String.format("系统内存 - 可用: %dMB, 总计: %dMB, 可用率: %.1f%%",
+ memoryInfo.availMem / (1024 * 1024),
+ memoryInfo.totalMem / (1024 * 1024),
+ availableMemoryPercentage * 100));
+
+ // 如果系统内存不足,记录警告
+ if (memoryInfo.lowMemory) {
+ Log.w(TAG, "系统内存不足警告");
+ }
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "检查系统内存失败", e);
+ }
+ }
+
+ /**
+ * 记录内存状态
+ */
+ private void logMemoryStatus(String prefix) {
+ try {
+ Runtime runtime = Runtime.getRuntime();
+ long maxMemory = runtime.maxMemory();
+ long totalMemory = runtime.totalMemory();
+ long freeMemory = runtime.freeMemory();
+ long usedMemory = totalMemory - freeMemory;
+ float memoryUsage = (float) usedMemory / maxMemory;
+
+ Log.i(TAG, String.format("%s内存状态 - 使用率: %.1f%%, 已用: %dMB, 空闲: %dMB, 最大: %dMB",
+ prefix,
+ memoryUsage * 100,
+ usedMemory / (1024 * 1024),
+ freeMemory / (1024 * 1024),
+ maxMemory / (1024 * 1024)));
+
+ } catch (Exception e) {
+ Log.e(TAG, "记录内存状态失败", e);
+ }
+ }
+
+ /**
+ * 获取当前内存使用率
+ */
+ public float getCurrentMemoryUsage() {
+ try {
+ Runtime runtime = Runtime.getRuntime();
+ long maxMemory = runtime.maxMemory();
+ long totalMemory = runtime.totalMemory();
+ long freeMemory = runtime.freeMemory();
+ long usedMemory = totalMemory - freeMemory;
+ return (float) usedMemory / maxMemory;
+ } catch (Exception e) {
+ Log.e(TAG, "获取内存使用率失败", e);
+ return 0f;
+ }
+ }
+
+ /**
+ * 检查内存是否健康
+ */
+ public boolean isMemoryHealthy() {
+ return getCurrentMemoryUsage() < MEMORY_THRESHOLD;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ouxuan/oxface/utils/UtilCodeHelper.java b/app/src/main/java/com/ouxuan/oxface/utils/UtilCodeHelper.java
new file mode 100644
index 0000000..a236734
--- /dev/null
+++ b/app/src/main/java/com/ouxuan/oxface/utils/UtilCodeHelper.java
@@ -0,0 +1,382 @@
+package com.ouxuan.oxface.utils;
+
+import android.content.Context;
+
+import com.blankj.utilcode.util.AppUtils;
+import com.blankj.utilcode.util.DeviceUtils;
+import com.blankj.utilcode.util.FileUtils;
+import com.blankj.utilcode.util.NetworkUtils;
+import com.blankj.utilcode.util.PathUtils;
+import com.blankj.utilcode.util.PhoneUtils;
+import com.blankj.utilcode.util.ScreenUtils;
+import com.blankj.utilcode.util.TimeUtils;
+import com.blankj.utilcode.util.ToastUtils;
+
+/**
+ * UtilCode工具库使用示例类
+ * 提供常用的Android开发工具方法封装
+ */
+public class UtilCodeHelper {
+
+ private static final String TAG = "UtilCodeHelper";
+
+ /**
+ * 应用信息相关工具方法
+ */
+ public static class App {
+ /**
+ * 获取应用版本名称
+ */
+ public static String getAppVersionName() {
+ return AppUtils.getAppVersionName();
+ }
+
+ /**
+ * 获取应用版本号
+ */
+ public static int getAppVersionCode() {
+ return AppUtils.getAppVersionCode();
+ }
+
+ /**
+ * 获取应用包名
+ */
+ public static String getAppPackageName() {
+ return AppUtils.getAppPackageName();
+ }
+
+ /**
+ * 判断应用是否在前台
+ */
+ public static boolean isAppForeground() {
+ return AppUtils.isAppForeground();
+ }
+
+ /**
+ * 获取应用信息摘要
+ */
+ public static String getAppInfoSummary() {
+ return String.format("应用信息 - 包名: %s, 版本: %s(%d)",
+ getAppPackageName(), getAppVersionName(), getAppVersionCode());
+ }
+ }
+
+ /**
+ * 设备信息相关工具方法
+ */
+ public static class Device {
+ /**
+ * 获取设备型号
+ */
+ public static String getModel() {
+ return DeviceUtils.getModel();
+ }
+
+ /**
+ * 获取设备制造商
+ */
+ public static String getManufacturer() {
+ return DeviceUtils.getManufacturer();
+ }
+
+ /**
+ * 获取Android版本
+ */
+ public static String getSDKVersionName() {
+ return DeviceUtils.getSDKVersionName();
+ }
+
+ /**
+ * 获取Android API级别
+ */
+ public static int getSDKVersionCode() {
+ return DeviceUtils.getSDKVersionCode();
+ }
+
+ /**
+ * 判断设备是否为平板
+ */
+ public static boolean isTablet() {
+ return DeviceUtils.isTablet();
+ }
+
+ /**
+ * 获取设备信息摘要
+ */
+ public static String getDeviceInfoSummary() {
+ return String.format("设备信息 - 型号: %s, 制造商: %s, Android: %s(API %d), 平板: %s",
+ getModel(), getManufacturer(), getSDKVersionName(),
+ getSDKVersionCode(), isTablet() ? "是" : "否");
+ }
+ }
+
+ /**
+ * 屏幕信息相关工具方法
+ */
+ public static class Screen {
+ /**
+ * 获取屏幕宽度(像素)
+ */
+ public static int getScreenWidth() {
+ return ScreenUtils.getScreenWidth();
+ }
+
+ /**
+ * 获取屏幕高度(像素)
+ */
+ public static int getScreenHeight() {
+ return ScreenUtils.getScreenHeight();
+ }
+
+ /**
+ * 获取屏幕密度
+ */
+ public static float getScreenDensity() {
+ return ScreenUtils.getScreenDensity();
+ }
+
+ /**
+ * dp转px
+ */
+ public static int dp2px(float dpValue) {
+ return com.blankj.utilcode.util.SizeUtils.dp2px(dpValue);
+ }
+
+ /**
+ * px转dp
+ */
+ public static int px2dp(float pxValue) {
+ return com.blankj.utilcode.util.SizeUtils.px2dp(pxValue);
+ }
+
+ /**
+ * 获取屏幕信息摘要
+ */
+ public static String getScreenInfoSummary() {
+ return String.format("屏幕信息 - 尺寸: %dx%d, 密度: %.2f",
+ getScreenWidth(), getScreenHeight(), getScreenDensity());
+ }
+ }
+
+ /**
+ * 网络相关工具方法
+ */
+ public static class Network {
+ /**
+ * 判断网络是否连接
+ */
+ public static boolean isConnected() {
+ return NetworkUtils.isConnected();
+ }
+
+ /**
+ * 判断是否为WiFi连接
+ */
+ public static boolean isWifiConnected() {
+ return NetworkUtils.isWifiConnected();
+ }
+
+ /**
+ * 判断是否为移动数据连接
+ */
+ public static boolean isMobileData() {
+ return NetworkUtils.isMobileData();
+ }
+
+ /**
+ * 获取网络类型
+ */
+ public static NetworkUtils.NetworkType getNetworkType() {
+ return NetworkUtils.getNetworkType();
+ }
+
+ /**
+ * 获取网络状态摘要
+ */
+ public static String getNetworkStatusSummary() {
+ if (!isConnected()) {
+ return "网络状态 - 未连接";
+ }
+
+ String connectionType = "未知";
+ if (isWifiConnected()) {
+ connectionType = "WiFi";
+ } else if (isMobileData()) {
+ connectionType = "移动数据";
+ }
+
+ return String.format("网络状态 - 已连接(%s), 类型: %s",
+ connectionType, getNetworkType());
+ }
+ }
+
+ /**
+ * 文件操作相关工具方法
+ */
+ public static class File {
+ /**
+ * 获取应用外部存储目录
+ */
+ public static String getAppExternalPath() {
+ return PathUtils.getExternalAppDataPath();
+ }
+
+ /**
+ * 获取应用内部存储目录
+ */
+ public static String getAppInternalPath() {
+ return PathUtils.getInternalAppDataPath();
+ }
+
+ /**
+ * 创建目录
+ */
+ public static boolean createDir(String dirPath) {
+ return FileUtils.createOrExistsDir(dirPath);
+ }
+
+ /**
+ * 判断文件是否存在
+ */
+ public static boolean isFileExists(String filePath) {
+ return FileUtils.isFileExists(filePath);
+ }
+
+ /**
+ * 获取文件大小(字节)
+ */
+ public static long getFileSize(String filePath) {
+ return FileUtils.getFileLength(filePath);
+ }
+
+ /**
+ * 删除文件或目录
+ */
+ public static boolean delete(String path) {
+ return FileUtils.delete(path);
+ }
+ }
+
+ /**
+ * 时间相关工具方法
+ */
+ public static class Time {
+ /**
+ * 获取当前时间戳(毫秒)
+ */
+ public static long getCurrentTimeMillis() {
+ return System.currentTimeMillis();
+ }
+
+ /**
+ * 时间戳转字符串(默认格式: yyyy-MM-dd HH:mm:ss)
+ */
+ public static String millis2String(long millis) {
+ return TimeUtils.millis2String(millis);
+ }
+
+ /**
+ * 时间戳转字符串(自定义格式)
+ */
+ public static String millis2String(long millis, String pattern) {
+ return TimeUtils.millis2String(millis, pattern);
+ }
+
+ /**
+ * 字符串转时间戳
+ */
+ public static long string2Millis(String time, String pattern) {
+ return TimeUtils.string2Millis(time, pattern);
+ }
+
+ /**
+ * 获取友好的时间描述
+ */
+ public static String getFriendlyTimeSpanByNow(long millis) {
+ return TimeUtils.getFriendlyTimeSpanByNow(millis);
+ }
+ }
+
+ /**
+ * Toast相关工具方法
+ */
+ public static class Toast {
+ /**
+ * 显示短时间Toast
+ */
+ public static void showShort(String message) {
+ ToastUtils.showShort(message);
+ }
+
+ /**
+ * 显示长时间Toast
+ */
+ public static void showLong(String message) {
+ ToastUtils.showLong(message);
+ }
+
+ /**
+ * 取消Toast显示
+ */
+ public static void cancel() {
+ ToastUtils.cancel();
+ }
+ }
+
+ /**
+ * 手机相关工具方法
+ */
+ public static class Phone {
+ /**
+ * 判断设备是否为手机
+ */
+ public static boolean isPhone() {
+ return PhoneUtils.isPhone();
+ }
+
+ /**
+ * 获取IMEI(需要权限)
+ */
+ public static String getIMEI() {
+ try {
+ return PhoneUtils.getIMEI();
+ } catch (Exception e) {
+ LogManager.logWarning(TAG, "获取IMEI失败: " + e.getMessage());
+ return "";
+ }
+ }
+
+ /**
+ * 获取手机型号
+ */
+ public static String getPhoneType() {
+ return PhoneUtils.getPhoneType() + "";
+ }
+ }
+
+ /**
+ * 系统信息汇总
+ * 用于24小时无人值守应用的系统状态记录
+ */
+ public static String getSystemInfoSummary() {
+ StringBuilder summary = new StringBuilder();
+ summary.append("=== 系统信息汇总 ===\n");
+ summary.append(App.getAppInfoSummary()).append("\n");
+ summary.append(Device.getDeviceInfoSummary()).append("\n");
+ summary.append(Screen.getScreenInfoSummary()).append("\n");
+ summary.append(Network.getNetworkStatusSummary()).append("\n");
+ summary.append("当前时间: ").append(Time.millis2String(Time.getCurrentTimeMillis())).append("\n");
+ summary.append("应用前台状态: ").append(App.isAppForeground() ? "是" : "否").append("\n");
+ summary.append("==================");
+
+ return summary.toString();
+ }
+
+ /**
+ * 记录系统信息到日志
+ */
+ public static void logSystemInfo() {
+ String systemInfo = getSystemInfoSummary();
+ LogManager.logOperation(TAG, systemInfo);
+ }
+}
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
index 35efae4..8e2e39b 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -25,4 +25,20 @@ android.nonTransitiveRClass=true
# Disable offline mode for build
org.gradle.offline=false
# Android SDK path
-android.sdk.path=/Users/zmt/Library/Android/sdk
\ No newline at end of file
+android.sdk.path=/Users/zmt/Library/Android/sdk
+
+# 24小时运行优化配置
+# 增大Gradle内存分配
+org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8
+# 并行构建优化
+org.gradle.parallel=true
+# 启用守护进程
+org.gradle.daemon=true
+# 配置缓存
+org.gradle.caching=true
+
+# Java版本兼容性配置
+# 抑制不兼容警告
+android.javaCompile.suppressSourceTargetDeprecationWarning=true
+# 启用R8优化
+android.enableR8.fullMode=false
\ No newline at end of file