diff --git a/powerbell/build.properties b/powerbell/build.properties index 7f20198..916bc3f 100644 --- a/powerbell/build.properties +++ b/powerbell/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Thu Dec 18 12:48:12 GMT 2025 +#Fri Dec 19 10:40:58 GMT 2025 stageCount=10 libraryProject= baseVersion=15.14 publishVersion=15.14.9 -buildCount=42 +buildCount=43 baseBetaVersion=15.14.10 diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java index 036bf4c..7fc64a0 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java @@ -155,8 +155,7 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV mMainContentView.releaseResources(); mMainContentView = null; } - // 销毁线程与Handler - RemindThread.stopRemindThread(); + // 销毁Handler if (sGlobalHandler != null) { sGlobalHandler.removeCallbacksAndMessages(null); sGlobalHandler = null; diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/receivers/ControlCenterServiceReceiver.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/receivers/ControlCenterServiceReceiver.java index e1e4a2e..f8d2fd4 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/receivers/ControlCenterServiceReceiver.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/receivers/ControlCenterServiceReceiver.java @@ -8,52 +8,59 @@ import cc.winboll.studio.libappbase.LogUtils; import cc.winboll.studio.powerbell.models.AppConfigBean; import cc.winboll.studio.powerbell.models.NotificationMessage; import cc.winboll.studio.powerbell.services.ControlCenterService; -import cc.winboll.studio.powerbell.threads.RemindThread; import cc.winboll.studio.powerbell.utils.AppConfigUtils; import cc.winboll.studio.powerbell.utils.BatteryUtils; import cc.winboll.studio.powerbell.utils.NotificationManagerUtils; import java.lang.ref.WeakReference; /** - * 控制中心广播接收器:监听电池状态变化、通知更新、线程启动指令,适配API29-30及小米手机 + * 控制中心广播接收器 + * 功能:监听电池状态变化、通知更新、线程启动指令 + * 适配:Java7 | API30 | 小米手机 | 内存泄漏防护 */ public class ControlCenterServiceReceiver extends BroadcastReceiver { - // ====================== 常量定义(顶部统一管理,清晰易维护) ====================== + // ================================== 静态常量区(置顶归类,消除魔法值)================================= public static final String TAG = ControlCenterServiceReceiver.class.getSimpleName(); + + // 广播Action常量(带包名前缀防冲突) public static final String ACTION_UPDATE_SERVICENOTIFICATION = "cc.winboll.studio.powerbell.action.UPDATE_SERVICENOTIFICATION"; public static final String ACTION_START_REMINDTHREAD = "cc.winboll.studio.powerbell.action.START_REMINDTHREAD"; public static final String EXTRA_APP_CONFIG_BEAN = "extra_app_config_bean"; - // ====================== 成员变量(弱引用防泄漏,volatile保线程安全) ====================== + // 广播优先级常量 + private static final int BROADCAST_PRIORITY = IntentFilter.SYSTEM_HIGH_PRIORITY - 10; + + // ================================== 成员变量区(弱引用防泄漏,volatile保线程安全)================================= private WeakReference mwrControlCenterService; private static volatile int sLastBatteryLevel = -1; private static volatile boolean sIsCharging = false; - // ====================== 构造方法 ====================== + // ================================== 构造方法(初始化弱引用,避免内存泄漏)================================= public ControlCenterServiceReceiver(ControlCenterService service) { - LogUtils.d(TAG, "constructor: init receiver"); + LogUtils.d(TAG, "constructor: 初始化广播接收器 | service=" + service); this.mwrControlCenterService = new WeakReference<>(service); } - // ====================== 广播核心接收逻辑 ====================== + // ================================== 广播核心接收逻辑(入口方法,分Action处理)================================= @Override public void onReceive(Context context, Intent intent) { - LogUtils.d(TAG, "onReceive: enter, action=" + intent.getAction()); + LogUtils.d(TAG, "onReceive: 接收广播 | context=" + context + " | intent=" + intent + " | action=" + (intent != null ? intent.getAction() : "null")); + + // 基础参数校验 if (context == null || intent == null || intent.getAction() == null) { - LogUtils.e(TAG, "onReceive: invalid params"); + LogUtils.e(TAG, "onReceive: 参数无效,终止处理"); return; } - // 弱引用获取服务,双重校验服务有效性(核心防护,避免内存泄漏+空指针) + // 弱引用获取服务,双重校验服务有效性 ControlCenterService service = mwrControlCenterService != null ? mwrControlCenterService.get() : null; if (service == null || service.isDestroyed()) { - LogUtils.e(TAG, "onReceive: ControlCenterService is destroyed or null"); - // 服务销毁后主动注销广播,彻底避免无效回调 + LogUtils.e(TAG, "onReceive: 服务已销毁或为空,注销广播"); unregisterAction(context); return; } - // 分action处理逻辑 + // 分Action处理业务逻辑 String action = intent.getAction(); switch (action) { case ACTION_UPDATE_SERVICENOTIFICATION: @@ -63,238 +70,195 @@ public class ControlCenterServiceReceiver extends BroadcastReceiver { handleBatteryStateChanged(context, service, intent); break; case ACTION_START_REMINDTHREAD: - handleStartRemindThread(service, intent); + LogUtils.d(TAG, "onReceive: ACTION_START_REMINDTHREAD 逻辑待实现"); break; default: - LogUtils.w(TAG, "onReceive: unknown action=" + action); + LogUtils.w(TAG, "onReceive: 未知Action=" + action); } - LogUtils.d(TAG, "onReceive: exit"); + + LogUtils.d(TAG, "onReceive: 广播处理完成"); } - // ====================== 业务逻辑方法(全链路容错+逻辑优化) ====================== + // ================================== 业务逻辑方法(按功能拆分,强化容错)================================= /** - * 处理前台服务通知更新(强化非空校验,适配工具类最新逻辑) + * 处理前台服务通知更新 + * @param service 控制中心服务实例 */ private void handleUpdateServiceNotification(ControlCenterService service) { - LogUtils.d(TAG, "handleUpdateServiceNotification: start"); + LogUtils.d(TAG, "handleUpdateServiceNotification: 执行通知更新 | service=" + service); try { NotificationManagerUtils notifyUtils = service.getNotificationManager(); NotificationMessage notifyMsg = service.getForegroundNotifyMsg(); - // 三重非空校验,避免工具类/消息/通知实例为空 + + // 非空校验+兜底重建 if (notifyUtils == null || notifyMsg == null) { - LogUtils.e(TAG, "handleUpdateServiceNotification: notify params null, rebuild notify first"); - // 兜底:通知实例为空时重建前台通知(适配工具类方法,避免空指针) - if (notifyUtils != null) { - notifyUtils.startForegroundServiceNotify(service, notifyMsg); - } + LogUtils.e(TAG, "handleUpdateServiceNotification: 通知工具类或消息为空"); return; } - // 调用工具类更新通知,确保方法匹配 + notifyUtils.updateForegroundServiceNotify(notifyMsg); - LogUtils.d(TAG, "handleUpdateServiceNotification: success"); + LogUtils.d(TAG, "handleUpdateServiceNotification: 通知更新成功"); } catch (Exception e) { - LogUtils.e(TAG, "handleUpdateServiceNotification: failed", e); + LogUtils.e(TAG, "handleUpdateServiceNotification: 通知更新失败", e); } } /** - * 处理电池状态变化(核心适配 BatteryUtils,修复解析逻辑) + * 处理电池状态变化广播 + * @param context 上下文 + * @param service 控制中心服务实例 + * @param intent 广播意图 */ private void handleBatteryStateChanged(Context context, ControlCenterService service, Intent intent) { - LogUtils.d(TAG, "handleBatteryStateChanged: start"); + LogUtils.d(TAG, "handleBatteryStateChanged: 处理电池状态变化 | context=" + context + " | service=" + service); try { - // 1. 适配 BatteryUtils 工具类:统一解析电池状态(删除错误的 getTheQuantityOfElectricity) - boolean currentCharging = BatteryUtils.isCharging(context); // 调用工具类判断充电状态 - int currentBatteryLevel = BatteryUtils.getCurrentBattery(context); // 调用工具类获取电量(0-100) - currentBatteryLevel = Math.min(Math.max(currentBatteryLevel, 0), 100); // 二次校验,确保范围有效 - LogUtils.d(TAG, "handleBatteryStateChanged: current state - charging=" + currentCharging + ", level=" + currentBatteryLevel); + // 1. 获取并校验当前电池状态 + boolean currentCharging = BatteryUtils.isCharging(context); + int currentBatteryLevel = BatteryUtils.getCurrentBattery(context); + currentBatteryLevel = Math.min(Math.max(currentBatteryLevel, 0), 100); + LogUtils.d(TAG, "handleBatteryStateChanged: 当前状态 | 充电=" + currentCharging + " | 电量=" + currentBatteryLevel); - // 2. 状态无变化直接跳过,减少无效运算 + // 2. 状态无变化则跳过,减少无效运算 if (currentCharging == sIsCharging && currentBatteryLevel == sLastBatteryLevel) { - LogUtils.d(TAG, "handleBatteryStateChanged: no state change, skip"); + LogUtils.d(TAG, "handleBatteryStateChanged: 电池状态无变化,跳过处理"); return; } - // 3. 加载最新配置(容错:配置加载失败用服务当前配置兜底) + // 3. 加载最新配置(多级兜底) AppConfigBean latestConfig = loadLatestConfig(context); if (latestConfig == null) { - LogUtils.e(TAG, "handleBatteryStateChanged: load latest config failed, use service current config"); latestConfig = service.getCurrentConfigBean(); - // 服务配置也为空时,加载默认配置 if (latestConfig == null) { latestConfig = new AppConfigBean(); + LogUtils.w(TAG, "handleBatteryStateChanged: 配置为空,使用默认配置"); } } - // 4. 同步最新电池状态到配置,再更新服务配置(确保服务配置是最新的) + // 4. 同步电池状态到配置,更新服务与线程 latestConfig.setCurrentBatteryValue(currentBatteryLevel); latestConfig.setIsCharging(currentCharging); - service.setCurrentConfigBean(latestConfig); + service.notifyAppConfigUpdate(latestConfig); - // 5. 智能更新线程(线程已初始化则更新配置,未初始化则启动,避免重复重启) - updateRemindThreadConfig(service, latestConfig, currentCharging, currentBatteryLevel); - - // 6. 缓存最新状态(volatile变量确保多线程可见性) + // 5. 缓存最新状态,确保多线程可见 sIsCharging = currentCharging; sLastBatteryLevel = currentBatteryLevel; - LogUtils.d(TAG, "handleBatteryStateChanged: success"); + + LogUtils.d(TAG, "handleBatteryStateChanged: 电池状态处理成功"); } catch (Exception e) { - LogUtils.e(TAG, "handleBatteryStateChanged: failed", e); + LogUtils.e(TAG, "handleBatteryStateChanged: 电池状态处理失败", e); } } + // ================================== 内部辅助方法(拆分通用逻辑,统一管理)================================= /** - * 处理线程启动指令(优化配置解析逻辑,强化线程启动容错) - */ - private void handleStartRemindThread(ControlCenterService service, Intent intent) { - LogUtils.d(TAG, "handleStartRemindThread: start"); - try { - // 安全解析配置(避免序列化异常) - AppConfigBean appConfigBean = null; - if (intent.hasExtra(EXTRA_APP_CONFIG_BEAN)) { - Object configObj = intent.getSerializableExtra(EXTRA_APP_CONFIG_BEAN); - if (configObj instanceof AppConfigBean) { - appConfigBean = (AppConfigBean) configObj; - // 配置补全:确保电池状态字段不为默认值(用缓存的最新状态) - appConfigBean.setIsCharging(sIsCharging); - appConfigBean.setCurrentBatteryValue(sLastBatteryLevel); - } - } - - if (appConfigBean != null) { - // 先更新服务配置,再重启线程(确保线程启动时拿到最新配置) - service.setCurrentConfigBean(appConfigBean); - // 重启线程(服务已实现安全重启逻辑,直接调用) - service.restartRemindThreadSafely(); - LogUtils.d(TAG, "handleStartRemindThread: success, thread restarted with new config"); - } else { - LogUtils.e(TAG, "handleStartRemindThread: appConfigBean is null or invalid"); - // 配置无效时,用缓存状态重启线程兜底 - service.restartRemindThreadSafely(); - } - } catch (Exception e) { - LogUtils.e(TAG, "handleStartRemindThread: failed", e); - } - } - - // ====================== 内部辅助方法(拆分逻辑+统一容错) ====================== - /** - * 加载最新配置(适配AppConfigUtils单例逻辑,强化异常捕获) + * 加载最新应用配置 + * @param context 上下文 + * @return 最新配置实例,失败返回null */ private AppConfigBean loadLatestConfig(Context context) { + LogUtils.d(TAG, "loadLatestConfig: 加载最新配置 | context=" + context); try { if (context == null) { - LogUtils.e(TAG, "loadLatestConfig: context is null"); + LogUtils.e(TAG, "loadLatestConfig: 上下文为空"); return null; } + AppConfigUtils configUtils = AppConfigUtils.getInstance(context); if (configUtils == null) { - LogUtils.e(TAG, "loadLatestConfig: AppConfigUtils instance is null"); + LogUtils.e(TAG, "loadLatestConfig: 配置工具类实例为空"); return null; } - // 强制重载配置,确保拿到最新用户设置 + configUtils.reloadAllConfig(); + LogUtils.d(TAG, "loadLatestConfig: 配置加载成功"); return configUtils.mAppConfigBean; } catch (Exception e) { - LogUtils.e(TAG, "loadLatestConfig: failed to load config", e); + LogUtils.e(TAG, "loadLatestConfig: 配置加载失败", e); return null; } } + // ================================== 广播注册/注销(强化容错,避免重复操作)================================= /** - * 更新提醒线程配置(智能判断线程状态,避免唤醒/启动冲突) + * 注册广播接收器 + * @param context 上下文 */ - private void updateRemindThreadConfig(ControlCenterService service, AppConfigBean config, boolean isCharging, int batteryLevel) { - try { - RemindThread remindThread = service.getRemindThread(); - if (remindThread == null) { - LogUtils.w(TAG, "updateRemindThreadConfig: remindThread is null, start thread first"); - // 线程未初始化,安全启动线程(服务方法已实现容错) - service.restartRemindThreadSafely(); - return; - } - - // 先同步完整配置(核心:setAppConfigBean已包含状态同步,无需重复设置) - remindThread.setAppConfigBean(config); -// -// -// // 线程未运行时唤醒,已运行时无需操作(避免重复唤醒导致逻辑紊乱) -// if (!remindThread.isRunning()) { -// synchronized (remindThread) { -// remindThread.notify(); -// LogUtils.d(TAG, "updateRemindThreadConfig: remindThread is woken up"); -// } -// } - LogUtils.d(TAG, "updateRemindThreadConfig: success, thread config updated"); - } catch (Exception e) { - LogUtils.e(TAG, "updateRemindThreadConfig: failed", e); - // 配置更新失败时,重启线程兜底 - service.restartRemindThreadSafely(); - } - } - - // ====================== 广播注册/注销(强化容错,避免重复注册/注销) ====================== public void registerAction(Context context) { - LogUtils.d(TAG, "registerAction: start"); + LogUtils.d(TAG, "registerAction: 注册广播 | context=" + context); if (context == null) { - LogUtils.e(TAG, "registerAction: context is null"); + LogUtils.e(TAG, "registerAction: 上下文为空,注册失败"); return; } try { - // 先注销再注册,避免重复注册导致异常 + // 先注销再注册,避免重复注册异常 unregisterAction(context); + IntentFilter filter = new IntentFilter(); filter.addAction(ACTION_UPDATE_SERVICENOTIFICATION); filter.addAction(ACTION_START_REMINDTHREAD); filter.addAction(Intent.ACTION_BATTERY_CHANGED); - // 优先级设置(低于系统最高优先级,避免被系统拦截) - filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY - 10); + filter.setPriority(BROADCAST_PRIORITY); + context.registerReceiver(this, filter); - LogUtils.d(TAG, "registerAction: success, broadcast receiver registered"); + LogUtils.d(TAG, "registerAction: 广播注册成功"); } catch (Exception e) { - LogUtils.e(TAG, "registerAction: failed to register receiver", e); + LogUtils.e(TAG, "registerAction: 广播注册失败", e); } } + /** + * 注销广播接收器 + * @param context 上下文 + */ public void unregisterAction(Context context) { - LogUtils.d(TAG, "unregisterAction: start"); + LogUtils.d(TAG, "unregisterAction: 注销广播 | context=" + context); if (context == null) { - LogUtils.e(TAG, "unregisterAction: context is null"); + LogUtils.e(TAG, "unregisterAction: 上下文为空,注销失败"); return; } try { - // 捕获注销异常(避免未注册时注销抛错) context.unregisterReceiver(this); - LogUtils.d(TAG, "unregisterAction: success, broadcast receiver unregistered"); + LogUtils.d(TAG, "unregisterAction: 广播注销成功"); } catch (IllegalArgumentException e) { - LogUtils.w(TAG, "unregisterAction: receiver not registered, skip"); + LogUtils.w(TAG, "unregisterAction: 广播未注册,跳过注销"); } catch (Exception e) { - LogUtils.e(TAG, "unregisterAction: failed to unregister receiver", e); + LogUtils.e(TAG, "unregisterAction: 广播注销失败", e); } } - // ====================== Getter方法(提供外部状态访问,强化线程安全) ====================== - public static int getLastBatteryLevel() { - return sLastBatteryLevel; - } - - public static boolean isLastCharging() { - return sIsCharging; - } - - // ====================== 主动释放资源(修复语法错误,彻底防泄漏) ====================== + // ================================== 资源释放与Getter方法(按需开放,防泄漏)================================= + /** + * 主动释放资源,避免内存泄漏 + */ public void release() { - LogUtils.d(TAG, "release: receiver release resources"); - // 置空弱引用,帮助GC回收 + LogUtils.d(TAG, "release: 释放广播接收器资源"); + // 清空弱引用 if (mwrControlCenterService != null) { mwrControlCenterService.clear(); mwrControlCenterService = null; } - // 重置静态状态缓存(修复重复赋值语法错误) + // 重置静态状态缓存 sLastBatteryLevel = -1; sIsCharging = false; + LogUtils.d(TAG, "release: 资源释放完成"); + } + + /** + * 获取上次记录的电池电量 + * @return 电量值(0-100),未初始化返回-1 + */ + public static int getLastBatteryLevel() { + return sLastBatteryLevel; + } + + /** + * 获取上次记录的充电状态 + * @return true=充电中,false=未充电 + */ + public static boolean isLastCharging() { + return sIsCharging; } } diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/services/ControlCenterService.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/services/ControlCenterService.java index dd9b215..5314755 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/services/ControlCenterService.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/services/ControlCenterService.java @@ -21,148 +21,145 @@ import java.io.Serializable; import java.util.List; /** + * 电池提醒核心服务 + * 功能:管理前台服务生命周期、控制提醒线程启停、处理配置更新 + * 适配:Java7 | API30 | 前台服务超时防护 | 电池优化忽略引导 * @Author ZhanGSKen&豆包大模型 * @Date 2025/12/17 15:48 - * @Describe 电池提醒核心服务:修复前台服务超时异常,优先在onCreate发送通知,适配Java7+API30 */ public class ControlCenterService extends Service { - // ================================== 静态常量(置顶统一管理,消除魔法值)================================= + // ================================== 静态常量区(置顶归类,消除魔法值)================================= public static final String TAG = "ControlCenterService"; - // 服务指令常量(带包名前缀,防止冲突) + + // 服务指令常量(带包名前缀防冲突) public static final String ACTION_RESTART_REMIND_THREAD = "cc.winboll.studio.powerbell.action.RESTART_REMIND_THREAD"; public static final String EXTRA_APP_CONFIG_BEAN = "cc.winboll.studio.powerbell.extra.APP_CONFIG_BEAN"; - // 超时常量 + + // 超时/阈值常量 private static final long THREAD_STOP_TIMEOUT = 1000L; - // ================================== 成员变量(按功能分类,私有封装)================================= - // 服务控制核心 + // ================================== 成员变量区(按功能分层,volatile保证多线程可见性)================================= + // 服务控制配置 private ControlCenterServiceBean mServiceControlBean; // 业务核心组件 private ControlCenterServiceHandler mServiceHandler; - private RemindThread mRemindThread; private NotificationManagerUtils mNotificationManager; private AppConfigBean mCurrentConfigBean; private NotificationMessage mForegroundNotifyMsg; - // 状态标记(volatile保证多线程可见性) + // 服务状态标记 private static volatile boolean isServiceRunning; private static volatile boolean mIsDestroyed; - // ================================== 服务生命周期方法(核心流程入口,按执行顺序排列)================================= + // ================================== 服务生命周期方法(按执行顺序排列)================================= @Override public void onCreate() { super.onCreate(); - LogUtils.d(TAG, "===== onCreate: 服务生命周期启动 ====="); - LogUtils.d(TAG, "onCreate: 当前线程=" + Thread.currentThread().getName() + " | 进程ID=" + android.os.Process.myPid()); + LogUtils.d(TAG, "onCreate: 服务启动 | 线程=" + Thread.currentThread().getName() + " | 进程ID=" + android.os.Process.myPid()); runCoreServiceLogic(); - LogUtils.d(TAG, "===== onCreate: 服务生命周期结束 | 前台通知状态=" + (isServiceRunning ? "✅已发送" : "❌未发送") + " | 启用状态=" + (mServiceControlBean != null ? mServiceControlBean.isEnableService() : false) + " ====="); + LogUtils.d(TAG, "onCreate: 服务初始化完成 | 前台状态=" + isServiceRunning + " | 服务启用=" + (mServiceControlBean != null && mServiceControlBean.isEnableService())); } @Override public int onStartCommand(Intent intent, int flags, int startId) { - LogUtils.d(TAG, "===== onStartCommand: 服务启动指令触发 ====="); - LogUtils.d(TAG, "onStartCommand: intent=" + intent + " | flags=" + flags + " | startId=" + startId); - LogUtils.d(TAG, "onStartCommand: intent action=" + (intent != null ? intent.getAction() : "null")); + LogUtils.d(TAG, "onStartCommand: 触发 | intent=" + intent + " | flags=" + flags + " | startId=" + startId); + LogUtils.d(TAG, "onStartCommand: action=" + (intent != null ? intent.getAction() : "null")); + loadLatestServiceControlConfig(); runCoreServiceLogic(); - int returnFlag; - if (mServiceControlBean != null && mServiceControlBean.isEnableService()) { - LogUtils.d(TAG, "onStartCommand: 服务已启用,返回START_STICKY(被杀死后自动重启)"); - returnFlag = START_STICKY; - } else { - LogUtils.d(TAG, "onStartCommand: 服务未启用,返回默认值"); - returnFlag = super.onStartCommand(intent, flags, startId); - } - LogUtils.d(TAG, "===== onStartCommand: 服务启动指令处理完成 | 返回值=" + returnFlag + " ====="); + int returnFlag = (mServiceControlBean != null && mServiceControlBean.isEnableService()) + ? START_STICKY + : super.onStartCommand(intent, flags, startId); + + LogUtils.d(TAG, "onStartCommand: 处理完成 | 返回策略=" + (returnFlag == START_STICKY ? "START_STICKY" : "DEFAULT")); return returnFlag; } @Override public void onDestroy() { - LogUtils.d(TAG, "===== onDestroy: 服务销毁流程启动 ====="); + LogUtils.d(TAG, "onDestroy: 服务销毁流程启动"); super.onDestroy(); - // 顺序释放资源 + + // 资源释放顺序:前台服务 → 线程 → Handler → 通知 → 引用 stopForegroundService(); - stopRemindThreadSafely(); + RemindThread.stopRemindThreadSafely(); destroyHandler(); releaseNotificationResource(); clearAllReferences(); - // 重置核心状态标记 + + // 状态重置 mCurrentConfigBean = null; mForegroundNotifyMsg = null; mServiceHandler = null; isServiceRunning = false; mIsDestroyed = true; - LogUtils.d(TAG, "===== onDestroy: 服务销毁流程完成 ====="); + + LogUtils.d(TAG, "onDestroy: 服务销毁完成"); } @Override public IBinder onBind(Intent intent) { - LogUtils.d(TAG, "onBind: 服务绑定请求 | intent=" + intent); + LogUtils.d(TAG, "onBind: 绑定请求 | intent=" + intent); return null; } - // ================================== 核心业务逻辑(抽取独立方法,统一管理)================================= + // ================================== 核心业务逻辑(独立抽取,统一调用)================================= /** - * 抽取的服务核心运行逻辑,统一在onCreate和onStartCommand调用 - * 复用 isServiceRunning 做重复运行判断,避免重复初始化业务 + * 服务核心运行逻辑,在onCreate/onStartCommand复用 + * 避免重复初始化,保证前台服务优先启动 */ private void runCoreServiceLogic() { - LogUtils.d(TAG, "runCoreServiceLogic: 开始执行核心业务逻辑"); + LogUtils.d(TAG, "runCoreServiceLogic: 执行核心逻辑"); loadLatestServiceControlConfig(); - boolean serviceEnabled = mServiceControlBean != null && mServiceControlBean.isEnableService(); - LogUtils.d(TAG, "runCoreServiceLogic: 服务启用状态=" + serviceEnabled + " | 当前运行状态=" + isServiceRunning + " | 已销毁状态=" + mIsDestroyed); - // 核心校验:服务已启用 + 服务未运行 + 未被销毁 - if (serviceEnabled) { - if (!isServiceRunning && !mIsDestroyed) { - isServiceRunning = true; - mIsDestroyed = false; - LogUtils.d(TAG, "runCoreServiceLogic: 满足执行条件,开始初始化前台通知和业务组件"); - // 优先发送前台通知,避免5秒超时异常 - if (initForegroundNotificationImmediately()) { - loadDefaultConfig(); - initServiceBusinessLogic(); - LogUtils.d(TAG, "runCoreServiceLogic: 核心业务组件初始化完成"); - } else { - LogUtils.e(TAG, "runCoreServiceLogic: 前台通知初始化失败,终止核心业务执行"); - stopForegroundService(); - isServiceRunning = false; - } + boolean serviceEnabled = mServiceControlBean != null && mServiceControlBean.isEnableService(); + LogUtils.d(TAG, "runCoreServiceLogic: 服务启用=" + serviceEnabled + " | 已运行=" + isServiceRunning + " | 已销毁=" + mIsDestroyed); + + if (serviceEnabled && !isServiceRunning && !mIsDestroyed) { + isServiceRunning = true; + mIsDestroyed = false; + + if (initForegroundNotificationImmediately()) { + loadDefaultConfig(); + initServiceBusinessLogic(); + LogUtils.d(TAG, "runCoreServiceLogic: 核心组件初始化成功"); } else { - LogUtils.d(TAG, "runCoreServiceLogic: 核心业务已运行或服务已销毁,无需重复执行"); + LogUtils.e(TAG, "runCoreServiceLogic: 前台通知初始化失败,终止业务"); + stopForegroundService(); + isServiceRunning = false; } } else { - LogUtils.d(TAG, "runCoreServiceLogic: 服务未启用,跳过核心业务执行"); + LogUtils.d(TAG, "runCoreServiceLogic: 无需执行核心逻辑"); } } - // ================================== 前台通知管理(优先执行,防止超时异常)================================= + // ================================== 前台通知管理(优先执行,防止5秒超时)================================= /** - * 立即初始化前台通知,内置兜底方案 - * @return true:通知初始化成功 false:通知初始化失败 + * 立即初始化前台通知,防止API26+前台服务超时异常 + * @return true=成功 false=失败 */ private boolean initForegroundNotificationImmediately() { - LogUtils.d(TAG, "initForegroundNotificationImmediately: 前台通知初始化流程启动"); + LogUtils.d(TAG, "initForegroundNotificationImmediately: 前台通知初始化"); try { if (mNotificationManager == null) { mNotificationManager = new NotificationManagerUtils(this); LogUtils.d(TAG, "initForegroundNotificationImmediately: 通知工具类初始化完成"); } + if (mForegroundNotifyMsg == null) { mForegroundNotifyMsg = new NotificationMessage(); mForegroundNotifyMsg.setTitle("电池监测服务"); mForegroundNotifyMsg.setContent("后台运行中"); mForegroundNotifyMsg.setRemindMSG("service_running"); - LogUtils.d(TAG, "initForegroundNotificationImmediately: 前台通知消息构建完成 | 标题=" + mForegroundNotifyMsg.getTitle() + " | 内容=" + mForegroundNotifyMsg.getContent()); + LogUtils.d(TAG, "initForegroundNotificationImmediately: 通知消息构建完成"); } + mNotificationManager.startForegroundServiceNotify(this, mForegroundNotifyMsg); - ToastUtils.show("startForegroundServiceNotify 已调用"); - LogUtils.d(TAG, "initForegroundNotificationImmediately: 前台通知发送成功 | 通知ID=" + NotificationManagerUtils.NOTIFY_ID_FOREGROUND_SERVICE); - LogUtils.d(TAG, "initForegroundNotificationImmediately: 前台通知初始化流程成功结束"); + ToastUtils.show("电池监测服务已启动"); + LogUtils.d(TAG, "initForegroundNotificationImmediately: 前台通知发送成功 | ID=" + NotificationManagerUtils.NOTIFY_ID_FOREGROUND_SERVICE); return true; } catch (Exception e) { - LogUtils.e(TAG, "initForegroundNotificationImmediately: 前台通知初始化流程异常", e); + LogUtils.e(TAG, "initForegroundNotificationImmediately: 通知初始化异常", e); return false; } } @@ -171,36 +168,35 @@ public class ControlCenterService extends Service { * 停止前台服务并取消通知 */ private void stopForegroundService() { - LogUtils.d(TAG, "stopForegroundService: 停止前台服务流程启动"); + LogUtils.d(TAG, "stopForegroundService: 停止前台服务"); try { stopForeground(true); - LogUtils.d(TAG, "stopForegroundService: 前台服务停止成功,通知已取消"); + LogUtils.d(TAG, "stopForegroundService: 前台服务已停止,通知已取消"); } catch (Exception e) { - LogUtils.e(TAG, "stopForegroundService: 停止前台服务异常", e); + LogUtils.e(TAG, "stopForegroundService: 停止异常", e); } - LogUtils.d(TAG, "stopForegroundService: 停止前台服务流程结束"); } // ================================== 配置管理(本地持久化+内存同步)================================= /** - * 读取本地最新服务控制配置 + * 加载本地最新服务控制配置 */ private void loadLatestServiceControlConfig() { - LogUtils.d(TAG, "loadLatestServiceControlConfig: 读取本地服务控制配置"); + LogUtils.d(TAG, "loadLatestServiceControlConfig: 读取服务配置"); ControlCenterServiceBean latestBean = ControlCenterServiceBean.loadBean(this, ControlCenterServiceBean.class); if (latestBean != null) { mServiceControlBean = latestBean; - LogUtils.d(TAG, "loadLatestServiceControlConfig: 本地配置读取成功 | 启用状态=" + mServiceControlBean.isEnableService()); + LogUtils.d(TAG, "loadLatestServiceControlConfig: 配置读取成功 | 启用=" + mServiceControlBean.isEnableService()); } else { - LogUtils.w(TAG, "loadLatestServiceControlConfig: 本地无配置文件,沿用当前内存配置 | 当前配置=" + mServiceControlBean); + LogUtils.w(TAG, "loadLatestServiceControlConfig: 本地无配置,沿用内存配置"); } } /** - * 加载默认应用配置 + * 加载默认业务配置(首次启动兜底) */ private void loadDefaultConfig() { - LogUtils.d(TAG, "loadDefaultConfig: 加载默认业务配置"); + LogUtils.d(TAG, "loadDefaultConfig: 加载默认配置"); if (mCurrentConfigBean == null) { mCurrentConfigBean = new AppConfigBean(); mCurrentConfigBean.setEnableChargeReminder(true); @@ -208,287 +204,197 @@ public class ControlCenterService extends Service { mCurrentConfigBean.setEnableUsageReminder(true); mCurrentConfigBean.setUsageReminderValue(20); mCurrentConfigBean.setBatteryDetectInterval(1000); - LogUtils.d(TAG, "loadDefaultConfig: 默认配置加载完成 | 充电阈值=" + 80 + " | 耗电阈值=" + 20 + " | 检测间隔=" + 1000 + "ms"); + LogUtils.d(TAG, "loadDefaultConfig: 默认配置加载完成 | 充电阈值=80 | 耗电阈值=20"); } else { - LogUtils.d(TAG, "loadDefaultConfig: 内存中已有业务配置,无需加载默认值 | 当前充电阈值=" + mCurrentConfigBean.getChargeReminderValue()); + LogUtils.d(TAG, "loadDefaultConfig: 内存已有配置,无需加载"); } } // ================================== 业务组件初始化与销毁================================= /** - * 初始化业务核心逻辑(Handler+线程) + * 初始化Handler等核心业务组件 */ private void initServiceBusinessLogic() { - LogUtils.d(TAG, "initServiceBusinessLogic: 业务组件初始化流程启动"); + LogUtils.d(TAG, "initServiceBusinessLogic: 初始化业务组件"); if (mServiceHandler == null) { mServiceHandler = new ControlCenterServiceHandler(this); - LogUtils.d(TAG, "initServiceBusinessLogic: ControlCenterServiceHandler初始化完成"); + LogUtils.d(TAG, "initServiceBusinessLogic: Handler初始化完成"); } else { - LogUtils.d(TAG, "initServiceBusinessLogic: ControlCenterServiceHandler已存在,无需重复初始化"); + LogUtils.d(TAG, "initServiceBusinessLogic: Handler已存在"); } - restartRemindThreadSafely(); - LogUtils.d(TAG, "initServiceBusinessLogic: 业务组件初始化流程结束"); } /** - * 销毁Handler,移除所有消息和回调 + * 销毁Handler,移除所有消息和回调,防止内存泄漏 */ private void destroyHandler() { - LogUtils.d(TAG, "destroyHandler: Handler销毁流程启动"); + LogUtils.d(TAG, "destroyHandler: 销毁Handler"); if (mServiceHandler != null) { mServiceHandler.removeCallbacksAndMessages(null); mServiceHandler = null; - LogUtils.d(TAG, "destroyHandler: Handler已销毁,所有消息已移除"); + LogUtils.d(TAG, "destroyHandler: Handler已销毁"); } else { - LogUtils.w(TAG, "destroyHandler: Handler实例为空,无需销毁"); + LogUtils.w(TAG, "destroyHandler: Handler实例为空"); } - LogUtils.d(TAG, "destroyHandler: Handler销毁流程结束"); } /** - * 释放通知资源 + * 释放通知工具类资源 */ private void releaseNotificationResource() { - LogUtils.d(TAG, "releaseNotificationResource: 通知资源释放流程启动"); + LogUtils.d(TAG, "releaseNotificationResource: 释放通知资源"); if (mNotificationManager != null) { mNotificationManager.release(); mNotificationManager = null; - LogUtils.d(TAG, "releaseNotificationResource: 通知工具类资源释放完成"); + LogUtils.d(TAG, "releaseNotificationResource: 通知资源已释放"); } else { - LogUtils.w(TAG, "releaseNotificationResource: 通知工具类实例为空,无需释放"); + LogUtils.w(TAG, "releaseNotificationResource: 通知工具类实例为空"); } - LogUtils.d(TAG, "releaseNotificationResource: 通知资源释放流程结束"); } /** * 置空所有引用,防止内存泄漏 */ private void clearAllReferences() { - LogUtils.d(TAG, "clearAllReferences: 内存引用清理流程启动"); + LogUtils.d(TAG, "clearAllReferences: 清理内存引用"); mForegroundNotifyMsg = null; - mCurrentConfigBean = null; mServiceControlBean = null; - LogUtils.d(TAG, "clearAllReferences: 所有业务引用已置空,防止内存泄漏"); - LogUtils.d(TAG, "clearAllReferences: 内存引用清理流程结束"); + LogUtils.d(TAG, "clearAllReferences: 引用清理完成"); } - // ================================== 提醒线程管理(安全启停)================================= + // ================================== 外部调用接口(静态方法,提供服务启停/配置更新入口)================================= /** - * 安全重启提醒线程 - */ -// public void restartRemindThreadSafely() { -// LogUtils.d(TAG, "restartRemindThreadSafely: 线程重启流程启动"); -// // 停止旧线程 -// stopRemindThreadSafely(); -// -// if (mServiceHandler != null) { -// // 创建新线程实例 -// RemindThread.destroyInstance(); -// mRemindThread = RemindThread.getInstance(this, mServiceHandler); -// LogUtils.d(TAG, "restartRemindThreadSafely: RemindThread新实例创建完成 | 线程引用=" + mRemindThread); -// // 同步配置到线程 -// syncConfigToRemindThread(); -// // 启动线程 -// if (mRemindThread != null && !mRemindThread.isAlive() && !mRemindThread.isThreadStarted()) { -// try { -// mRemindThread.start(); -// LogUtils.d(TAG, "restartRemindThreadSafely: 新线程启动成功 | 线程ID=" + mRemindThread.getId() + " | 线程名称=" + mRemindThread.getName()); -// } catch (IllegalThreadStateException e) { -// LogUtils.e(TAG, "restartRemindThreadSafely: 线程重复启动异常", e); -// mRemindThread = null; -// } -// } else { -// LogUtils.w(TAG, "restartRemindThreadSafely: 线程状态异常,跳过启动 | isAlive=" + (mRemindThread != null && mRemindThread.isAlive()) + " | isThreadStarted=" + (mRemindThread != null && mRemindThread.isThreadStarted())); -// } -// } else { -// LogUtils.e(TAG, "restartRemindThreadSafely: mServiceHandler is null,线程启动失败"); -// } -// LogUtils.d(TAG, "restartRemindThreadSafely: 线程重启流程结束"); -// } - - /** - * 安全停止提醒线程 - */ - private void stopRemindThreadSafely() { - LogUtils.d(TAG, "stopRemindThreadSafely: 线程停止流程启动"); - if (mRemindThread == null) { - LogUtils.w(TAG, "stopRemindThreadSafely: RemindThread实例为空,跳过停止流程"); - return; - } - try { - if (mRemindThread.isThreadStarted() || mRemindThread.isAlive()) { - LogUtils.d(TAG, "stopRemindThreadSafely: 线程处于运行状态,开始停止 | isThreadStarted=" + mRemindThread.isThreadStarted() + " | isAlive=" + mRemindThread.isAlive()); - mRemindThread.setIsReminding(false); - mRemindThread.stopThread(); - // 等待线程终止,超时强制中断 - long waitStartTime = System.currentTimeMillis(); - while (mRemindThread.isAlive()) { - if (System.currentTimeMillis() - waitStartTime > THREAD_STOP_TIMEOUT) { - LogUtils.w(TAG, "stopRemindThreadSafely: 线程停止超时(超时时间=" + THREAD_STOP_TIMEOUT + "ms),强制中断"); - mRemindThread.interrupt(); - break; - } - Thread.yield(); - } - LogUtils.d(TAG, "stopRemindThreadSafely: 线程停止完成,耗时=" + (System.currentTimeMillis() - waitStartTime) + "ms"); - } else { - LogUtils.d(TAG, "stopRemindThreadSafely: 线程未运行,无需停止"); - } - } catch (Exception e) { - LogUtils.e(TAG, "stopRemindThreadSafely: 停止线程异常", e); - } finally { - mRemindThread = null; - RemindThread.destroyInstance(); - LogUtils.d(TAG, "stopRemindThreadSafely: 线程实例已置空,单例已销毁"); - } - LogUtils.d(TAG, "stopRemindThreadSafely: 线程停止流程结束"); - } - - /** - * 同步配置到提醒线程 - */ - private void syncConfigToRemindThread() { - LogUtils.d(TAG, "syncConfigToRemindThread: 配置同步流程启动"); - if (mRemindThread == null || mCurrentConfigBean == null) { - LogUtils.e(TAG, "syncConfigToRemindThread: 配置同步失败 | mRemindThread=" + mRemindThread + " | mCurrentConfigBean=" + mCurrentConfigBean); - return; - } - mRemindThread.setAppConfigBean(mCurrentConfigBean); - - LogUtils.d(TAG, "syncConfigToRemindThread: 配置同步成功 | 充电阈值=" + mCurrentConfigBean.getChargeReminderValue() + " | 耗电阈值=" + mCurrentConfigBean.getUsageReminderValue() + " | 检测间隔=" + mCurrentConfigBean.getBatteryDetectInterval() + "ms"); - LogUtils.d(TAG, "syncConfigToRemindThread: 配置同步流程结束"); - } - - // ================================== 静态工具方法(对外提供服务入口,按功能归类)================================= - /** - * 启动服务 + * 外部启动服务的统一入口 + * @param context 上下文 */ public static void startControlCenterService(Context context) { - LogUtils.d(TAG, "===== startControlCenterService: 外部启动服务接口调用 ====="); + LogUtils.d(TAG, "startControlCenterService: 外部启动服务 | context=" + context); if (context == null) { LogUtils.e(TAG, "startControlCenterService: Context为空,启动失败"); return; } - // 保存服务启动配置 + + // 保存启用配置 ControlCenterServiceBean controlBean = new ControlCenterServiceBean(true); ControlCenterServiceBean.saveBean(context, controlBean); - LogUtils.d(TAG, "startControlCenterService: 服务启动配置已保存 | 启用状态=" + controlBean.isEnableService()); - // 构建启动Intent + + // 启动服务(区分API版本) Intent intent = new Intent(context, ControlCenterService.class); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - LogUtils.d(TAG, "startControlCenterService: SDK版本>=26,调用startForegroundService启动前台服务"); context.startForegroundService(intent); + LogUtils.d(TAG, "startControlCenterService: 以前台服务方式启动"); } else { - LogUtils.d(TAG, "startControlCenterService: SDK版本<26,调用startService启动普通服务"); context.startService(intent); + LogUtils.d(TAG, "startControlCenterService: 以普通服务方式启动"); } - LogUtils.d(TAG, "===== startControlCenterService: 外部启动服务接口调用完成 ====="); } /** - * 停止服务 + * 外部停止服务的统一入口 + * @param context 上下文 */ public static void stopControlCenterService(Context context) { - LogUtils.d(TAG, "===== stopControlCenterService: 外部停止服务接口调用 ====="); + LogUtils.d(TAG, "stopControlCenterService: 外部停止服务 | context=" + context); if (context == null) { LogUtils.e(TAG, "stopControlCenterService: Context为空,停止失败"); return; } - // 保存服务停止配置 + + // 保存停用配置 ControlCenterServiceBean controlBean = new ControlCenterServiceBean(false); ControlCenterServiceBean.saveBean(context, controlBean); - LogUtils.d(TAG, "stopControlCenterService: 服务停止配置已保存 | 启用状态=" + controlBean.isEnableService()); - // 构建停止Intent + + // 停止服务 Intent intent = new Intent(context, ControlCenterService.class); - LogUtils.d(TAG, "stopControlCenterService: 调用stopService发送停止指令"); context.stopService(intent); - LogUtils.d(TAG, "===== stopControlCenterService: 外部停止服务接口调用完成 ====="); + LogUtils.d(TAG, "stopControlCenterService: 停止指令已发送"); } /** - * 更新业务配置并触发线程重启 + * 外部更新配置并触发线程重启 + * @param context 上下文 + * @param configBean 新配置 */ public static void updateStatus(Context context, AppConfigBean configBean) { - LogUtils.d(TAG, "===== updateStatus: 外部更新配置接口调用 ====="); + LogUtils.d(TAG, "updateStatus: 外部更新配置 | context=" + context + " | config=" + configBean); if (context == null || configBean == null) { - LogUtils.e(TAG, "updateStatus: 参数为空 | context=" + context + " | configBean=" + configBean); + LogUtils.e(TAG, "updateStatus: 参数为空,更新失败"); return; } - LogUtils.d(TAG, "updateStatus: 待同步配置 | 充电阈值=" + configBean.getChargeReminderValue() + " | 耗电阈值=" + configBean.getUsageReminderValue()); - // 构建配置更新Intent + Intent intent = new Intent(context, ControlCenterService.class); intent.setAction(ACTION_RESTART_REMIND_THREAD); intent.putExtra(EXTRA_APP_CONFIG_BEAN, (Serializable) configBean); intent.setPackage(context.getPackageName()); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - LogUtils.d(TAG, "updateStatus: SDK版本>=26,调用startForegroundService发送配置更新指令"); context.startForegroundService(intent); } else { - LogUtils.d(TAG, "updateStatus: SDK版本<26,调用startService发送配置更新指令"); context.startService(intent); } LogUtils.d(TAG, "updateStatus: 配置更新指令发送成功"); } catch (Exception e) { - LogUtils.e(TAG, "updateStatus: 发送配置更新指令异常", e); + LogUtils.e(TAG, "updateStatus: 发送指令异常", e); } - LogUtils.d(TAG, "===== updateStatus: 外部更新配置接口调用完成 ====="); } /** - * 检查并引导用户开启忽略电池优化 + * 检查并引导用户开启忽略电池优化(API23+) + * @param context 上下文 */ public static void checkIgnoreBatteryOptimization(Context context) { - LogUtils.d(TAG, "checkIgnoreBatteryOptimization: 电池优化检查流程启动"); + LogUtils.d(TAG, "checkIgnoreBatteryOptimization: 检查电池优化 | context=" + context); if (context == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - LogUtils.w(TAG, "checkIgnoreBatteryOptimization: 无需检查 | context=" + context + " | SDK版本=" + (Build.VERSION.SDK_INT)); + LogUtils.w(TAG, "checkIgnoreBatteryOptimization: 无需检查"); return; } + PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); if (powerManager == null) { LogUtils.e(TAG, "checkIgnoreBatteryOptimization: PowerManager获取失败"); return; } - try { - String packageName = context.getPackageName(); - boolean isIgnored = powerManager.isIgnoringBatteryOptimizations(packageName); - LogUtils.d(TAG, "checkIgnoreBatteryOptimization: 当前忽略电池优化状态=" + isIgnored); - if (!isIgnored) { - Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); - intent.setData(Uri.parse("package:" + packageName)); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); - context.startActivity(intent); - LogUtils.d(TAG, "checkIgnoreBatteryOptimization: 已跳转至系统设置页,引导用户开启忽略电池优化"); - } else { - LogUtils.d(TAG, "checkIgnoreBatteryOptimization: 已开启忽略电池优化,无需引导"); - } - } catch (Exception e) { - LogUtils.e(TAG, "checkIgnoreBatteryOptimization: 引导用户开启忽略电池优化异常", e); + + String packageName = context.getPackageName(); + boolean isIgnored = powerManager.isIgnoringBatteryOptimizations(packageName); + LogUtils.d(TAG, "checkIgnoreBatteryOptimization: 已忽略电池优化=" + isIgnored); + + if (!isIgnored) { + Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); + intent.setData(Uri.parse("package:" + packageName)); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); + context.startActivity(intent); + LogUtils.d(TAG, "checkIgnoreBatteryOptimization: 已跳转至系统设置页"); } - LogUtils.d(TAG, "checkIgnoreBatteryOptimization: 电池优化检查流程结束"); } /** - * 判断服务是否运行(适配API30+) + * 检查服务是否运行(适配API30+) + * @param context 上下文 + * @param serviceClass 服务类 + * @return true=运行中 false=未运行 */ private static boolean isServiceRunning(Context context, Class serviceClass) { - LogUtils.d(TAG, "isServiceRunning: 服务运行状态检查流程启动 | serviceClass=" + (serviceClass != null ? serviceClass.getName() : "null")); + LogUtils.d(TAG, "isServiceRunning: 检查服务状态 | context=" + context + " | service=" + serviceClass); if (context == null || serviceClass == null) { - LogUtils.e(TAG, "isServiceRunning: 参数为空 | context=" + context + " | serviceClass=" + serviceClass); - LogUtils.d(TAG, "isServiceRunning: 服务运行状态检查流程结束 | 结果=false"); + LogUtils.e(TAG, "isServiceRunning: 参数为空"); return false; } + ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); if (am == null) { LogUtils.e(TAG, "isServiceRunning: ActivityManager获取失败"); - LogUtils.d(TAG, "isServiceRunning: 服务运行状态检查流程结束 | 结果=false"); return false; } + boolean isRunning = false; + String packageName = context.getPackageName(); + String serviceClassName = serviceClass.getName(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - LogUtils.d(TAG, "isServiceRunning: SDK版本>=30,使用进程信息判断"); - String packageName = context.getPackageName(); + // API30+ 禁止获取其他应用服务,通过进程状态判断 List processes = am.getRunningAppProcesses(); if (processes != null) { for (ActivityManager.RunningAppProcessInfo process : processes) { @@ -496,67 +402,64 @@ public class ControlCenterService extends Service { (process.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE || process.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND)) { isRunning = true; - LogUtils.d(TAG, "isServiceRunning: 检测到前台服务进程,判定服务运行"); break; } } } - if (!isRunning) { - LogUtils.d(TAG, "isServiceRunning: API30+未检测到运行,执行兜底判断"); - isRunning = isServiceStarted(context, serviceClass); - } + LogUtils.d(TAG, "isServiceRunning: API30+ 判断结果=" + isRunning); } else { - LogUtils.d(TAG, "isServiceRunning: SDK版本<30,使用服务列表判断"); - List runningServices = am.getRunningServices(100); - if (runningServices != null) { - String serviceClassName = serviceClass.getName(); - for (ActivityManager.RunningServiceInfo info : runningServices) { + // API30- 通过服务列表判断 + List services = am.getRunningServices(100); + if (services != null) { + for (ActivityManager.RunningServiceInfo info : services) { if (serviceClassName.equals(info.service.getClassName())) { isRunning = true; - LogUtils.d(TAG, "isServiceRunning: 检测到服务在运行列表中,判定服务运行"); break; } } } + LogUtils.d(TAG, "isServiceRunning: API30- 判断结果=" + isRunning); + } + + // 兜底判断:配置启用状态 + if (!isRunning) { + isRunning = isServiceStarted(context, serviceClass); + LogUtils.d(TAG, "isServiceRunning: 兜底判断结果=" + isRunning); } - LogUtils.d(TAG, "isServiceRunning: 服务运行状态检查流程结束 | 结果=" + isRunning); return isRunning; } /** - * 兜底判断服务是否已启动 + * 兜底判断服务是否已启动(通过配置文件) */ private static boolean isServiceStarted(Context context, Class serviceClass) { - LogUtils.d(TAG, "isServiceStarted: 服务状态兜底判断流程启动"); - boolean result = false; + LogUtils.d(TAG, "isServiceStarted: 兜底判断服务状态"); try { ControlCenterServiceBean controlBean = ControlCenterServiceBean.loadBean(context, ControlCenterServiceBean.class); - result = controlBean != null && controlBean.isEnableService(); - LogUtils.d(TAG, "isServiceStarted: 兜底判断结果=" + result + " | 配置启用状态=" + (controlBean != null ? controlBean.isEnableService() : "null")); + return controlBean != null && controlBean.isEnableService(); } catch (Exception e) { LogUtils.e(TAG, "isServiceStarted: 兜底判断异常", e); - result = false; + return false; } - LogUtils.d(TAG, "isServiceStarted: 服务状态兜底判断流程结束 | 结果=" + result); - return result; } - // ================================== Getter/Setter 方法(添加日志)================================= - public RemindThread getRemindThread() { - return mRemindThread; - } - - public void setCurrentConfigBean(AppConfigBean configBean) { - LogUtils.d(TAG, "setCurrentConfigBean: 业务配置更新接口调用"); - if (configBean == null) { - LogUtils.e(TAG, "setCurrentConfigBean: 待更新配置为空,更新失败"); - return; + // ================================== 业务方法(配置更新)================================= + /** + * 接收外部配置更新,同步到提醒线程 + * @param latestConfig 最新配置 + */ + public void notifyAppConfigUpdate(AppConfigBean latestConfig) { + LogUtils.d(TAG, "notifyAppConfigUpdate: 配置更新 | config=" + latestConfig); + if (latestConfig != null && mServiceHandler != null) { + mCurrentConfigBean = latestConfig; + RemindThread.startRemindThread(this, mServiceHandler, latestConfig); + LogUtils.d(TAG, "notifyAppConfigUpdate: 配置已同步到线程"); + } else { + LogUtils.e(TAG, "notifyAppConfigUpdate: 参数为空,同步失败"); } - this.mCurrentConfigBean = configBean; - syncConfigToRemindThread(); - LogUtils.d(TAG, "setCurrentConfigBean: 业务配置更新完成 | 新充电阈值=" + configBean.getChargeReminderValue()); } + // ================================== Getter 方法(按需开放,避免冗余Setter)================================= public ControlCenterServiceBean getServiceControlBean() { return mServiceControlBean; } diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/threads/RemindThread.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/threads/RemindThread.java index d34f4b9..5904bb0 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/threads/RemindThread.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/threads/RemindThread.java @@ -11,38 +11,34 @@ import java.lang.ref.WeakReference; * 提醒线程(单例模式) * 功能:统一管理充电/耗电提醒逻辑,发送提醒时携带当前电量+充电状态 * 适配:Java7 | API30 | 小米手机 - * 特性:线程安全、内存泄漏防护、配置重试兜底 - * 对外接口:仅保留 {@link #startRemindThread(Context, ControlCenterServiceHandler, AppConfigBean)} 和 {@link #stopRemindThread()} + * 特性:线程安全、内存泄漏防护、配置参数校验 + * 对外接口:{@link #startRemindThread(Context, ControlCenterServiceHandler, AppConfigBean)}、{@link #stopRemindThreadSafely()} */ public class RemindThread extends Thread { - // ================================== 静态常量(置顶归类,消除魔法值)================================= + // ================================== 静态常量区(置顶归类,消除魔法值)================================= public static final String TAG = "RemindThread"; // 时间常量 (ms) - private static final long INIT_DELAY_TIME = 500L; private static final int MIN_SLEEP_TIME = 500; private static final int DEFAULT_SLEEP_TIME = 1000; - private static final long REMIND_INTERVAL = 3000L; + private static final long THREAD_JOIN_TIMEOUT = 1000L; - // 重试与状态常量 - private static final int CONFIG_RETRY_MAX = 3; + // 状态常量 private static final int INVALID_BATTERY_VALUE = -1; // ================================== 单例核心(线程安全,双重校验锁)================================= private static volatile RemindThread sInstance; - // ================================== 成员变量(按功能分层,volatile保证多线程可见性,防内存泄漏)================================= - // 弱引用依赖(避免内存泄漏) + // ================================== 成员变量区(按功能分层,volatile保证多线程可见性)================================= + // 弱引用依赖(防内存泄漏) private Context mContext; private WeakReference mwrControlCenterServiceHandler; - // 线程状态标记(volatile 保证多线程可见性) + // 线程状态标记 private volatile boolean isExist; - //private volatile boolean isThreadStarted; private volatile boolean isReminding; - //private volatile boolean isRemindTimerRunning; - // 业务配置参数(范围校验,实时同步) + // 业务配置参数 private volatile boolean isEnableChargeReminder; private volatile boolean isEnableUsageReminder; private volatile long sleepTime; @@ -51,174 +47,176 @@ public class RemindThread extends Thread { private volatile int quantityOfElectricity; private volatile boolean isCharging; - // 辅助变量(并发安全+防重复提醒) - //private volatile long lastRemindTime; + // 并发安全锁 private final Object mLock = new Object(); - // ================================== 私有构造器(单例专用,初始化状态+防护泄漏)================================= + // ================================== 私有构造器(单例专用,禁止外部实例化)================================= private RemindThread(Context context, ControlCenterServiceHandler handler) { + LogUtils.d(TAG, "构造线程实例 | threadName=" + getName() + " | threadId=" + getId()); this.mContext = context.getApplicationContext(); this.mwrControlCenterServiceHandler = new WeakReference<>(handler); resetThreadStateInternal(); - LogUtils.d(TAG, "构造线程实例 | threadName=" + getName() + " | threadId=" + getId()); } - // ================================== 对外公开静态方法(仅保留两个:启动+停止)================================= + // ================================== 单例获取方法(核心,统一管理单例创建)================================= /** - * 对外启动线程接口 + * 私有单例获取方法,双重校验锁保证线程安全 * @param context 上下文 * @param handler 服务处理器 - * @param config 应用配置Bean - * @return 若 isReminding 为 true 直接返回 true;否则创建/启动线程后返回 false + * @return 唯一的 RemindThread 实例 + */ + private static RemindThread getInstance(Context context, ControlCenterServiceHandler handler) { + LogUtils.d(TAG, "getInstance: 获取单例 | context=" + context + " | handler=" + handler); + if (sInstance == null) { + synchronized (RemindThread.class) { + if (sInstance == null) { + sInstance = new RemindThread(context, handler); + LogUtils.d(TAG, "getInstance: 新建单例成功 | threadId=" + sInstance.getId()); + } + } + } + return sInstance; + } + + // ================================== 对外公开静态接口(全部基于单例实现)================================= + /** + * 启动提醒线程(基于单例操作,确保全局唯一) + * @param context 上下文(非空) + * @param handler 服务处理器(非空) + * @param config 应用配置Bean(非空) + * @return true: isReminding为真/线程启动成功;false: 入参非法/启动失败 */ public static boolean startRemindThread(Context context, ControlCenterServiceHandler handler, AppConfigBean config) { + LogUtils.d(TAG, "startRemindThread: 调用 | context=" + context + " | handler=" + handler + " | config=" + config); // 入参校验 if (context == null || handler == null || config == null) { LogUtils.e(TAG, "startRemindThread: 入参为空,启动失败"); return false; } - // 1. 若 isReminding 为真,直接返回 true 无需操作 - if (sInstance != null && sInstance.isReminding) { - // 3. 同步配置 - sInstance.setAppConfigBean(config); - LogUtils.d(TAG, "startRemindThread: isReminding 为真,更新最新数据后返回"); + // 获取单例 + RemindThread instance = getInstance(context, handler); + + // 已在提醒状态,同步配置后返回 + if (instance.isReminding) { + instance.setAppConfigBean(config); + LogUtils.d(TAG, "startRemindThread: 线程已在提醒状态,同步最新配置 | threadId=" + instance.getId()); return true; } - // 2. 未创建实例则创建 - if (sInstance == null) { - synchronized (RemindThread.class) { - if (sInstance == null) { - sInstance = new RemindThread(context, handler); - } - } - } - - - // 4. 线程未运行则启动 - if (!sInstance.isRunning()) { - sInstance.isExist = false; // 重置退出标记 - sInstance.start(); - LogUtils.d(TAG, "startRemindThread: 线程启动成功 | threadId=" + sInstance.getId()); + // 同步配置并启动线程 + instance.setAppConfigBean(config); + if (!instance.isRunning()) { + instance.isExist = false; + instance.start(); + LogUtils.d(TAG, "startRemindThread: 线程启动成功 | threadId=" + instance.getId()); + return true; } else { - LogUtils.d(TAG, "startRemindThread: 线程已在运行 | threadId=" + sInstance.getId()); + LogUtils.d(TAG, "startRemindThread: 线程已在运行 | threadId=" + instance.getId()); + return false; } - - return false; } /** - * 对外停止线程接口:直接销毁单例 + * 安全停止线程(基于单例操作,优雅销毁唯一实例) */ - public static void stopRemindThread() { - LogUtils.d(TAG, "stopRemindThread: 开始停止线程"); - destroyInstance(); - LogUtils.d(TAG, "stopRemindThread: 线程已停止并销毁"); + public static void stopRemindThreadSafely() { + LogUtils.d(TAG, "stopRemindThreadSafely: 调用 | sInstance=" + (sInstance != null)); + synchronized (RemindThread.class) { + if (sInstance == null) { + LogUtils.w(TAG, "stopRemindThreadSafely: 线程实例为空,无需停止"); + return; + } + + // 线程未运行,直接销毁 + if (!sInstance.isRunning()) { + LogUtils.d(TAG, "stopRemindThreadSafely: 线程未运行,直接销毁 | threadId=" + sInstance.getId()); + destroyInstance(); + return; + } + + // 标记退出,等待线程自然结束 + sInstance.isExist = true; + sInstance.isReminding = false; + LogUtils.d(TAG, "stopRemindThreadSafely: 标记线程退出 | threadId=" + sInstance.getId()); + + try { + sInstance.join(THREAD_JOIN_TIMEOUT); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + LogUtils.e(TAG, "stopRemindThreadSafely: 等待线程退出被中断", e); + } + + // 销毁单例 + destroyInstance(); + LogUtils.d(TAG, "stopRemindThreadSafely: 线程安全销毁完成"); + } } - // ================================== 私有单例管理方法(内部使用)================================= + // ================================== 私有单例管理方法================================= /** - * 获取单例实例(私有化,仅内部调用) - */ -// private static RemindThread getInstance(Context context, ControlCenterServiceHandler handler) { -// LogUtils.d(TAG, "getInstance: 尝试获取单例 | currentInstance=" + (sInstance != null ? "存在" : "不存在")); -// -// if (context == null || handler == null) { -// LogUtils.e(TAG, "getInstance: 入参为空"); -// throw new IllegalArgumentException("Context and ControlCenterServiceHandler cannot be null"); -// } -// -// if (sInstance != null && !sInstance.isRunning()) { -// destroyInstance(); -// LogUtils.d(TAG, "getInstance: 旧线程已停止,销毁单例"); -// } -// -// if (sInstance == null) { -// synchronized (RemindThread.class) { -// if (sInstance == null) { -// sInstance = new RemindThread(context, handler); -// LogUtils.d(TAG, "getInstance: 新线程实例创建成功 | threadId=" + sInstance.getId()); -// } -// } -// } -// return sInstance; -// } - - /** - * 销毁单例(安全停止线程+释放资源,避免内存泄漏) + * 销毁单例,安全释放资源 */ private static void destroyInstance() { - LogUtils.d(TAG, "destroyInstance: 开始销毁线程单例"); + LogUtils.d(TAG, "destroyInstance: 开始销毁单例 | sInstance=" + (sInstance != null)); synchronized (RemindThread.class) { if (sInstance != null) { + // 终止线程并释放资源 sInstance.isExist = true; - //sInstance.isRemindTimerRunning = false; + sInstance.isReminding = false; if (sInstance.isAlive()) { sInstance.interrupt(); - LogUtils.d(TAG, "destroyInstance: 线程已中断"); + LogUtils.d(TAG, "destroyInstance: 线程已中断 | threadId=" + sInstance.getId()); } sInstance.releaseResourcesInternal(); sInstance = null; - sInstance.isReminding = false; - LogUtils.d(TAG, "destroyInstance: 线程单例销毁完成"); + LogUtils.d(TAG, "destroyInstance: 单例销毁完成"); } else { LogUtils.w(TAG, "destroyInstance: 单例已为空,跳过销毁"); } } } - // ================================== 线程核心逻辑(run方法,高效退出+异常容错,仅此处保留mLock)================================= + // ================================== 线程核心运行逻辑================================= @Override public void run() { LogUtils.d(TAG, "run: 线程启动 | threadId=" + Thread.currentThread().getId() + " | state=" + getState()); - // 仅保留此处的mLock,保护isReminding等核心状态的读写,防止线程重复启动 + // 初始化提醒状态(加锁保护) synchronized (mLock) { - if (isExist && !isReminding) { - isReminding = true; + if (!isExist && !isReminding) { + isReminding = true; + LogUtils.d(TAG, "run: 初始化提醒状态成功 | isReminding=true"); } else { - LogUtils.d(TAG, String.format("线程退出,标志位:isExist %s, isReminding %s.", isExist, isReminding)); - } + LogUtils.d(TAG, "run: 线程退出条件满足 | isExist=" + isExist + " | isReminding=" + isReminding); + cleanThreadStateInternal(); + return; + } } - // 核心检测循环(快速退出+并发安全) + // 核心检测循环 LogUtils.d(TAG, "run: 进入电量检测循环 | sleepTime=" + sleepTime + "ms"); while (!isExist) { try { + // 快速退出判断 if (isExist) break; - // 核心防护:电量无效退出 - if ((quantityOfElectricity == INVALID_BATTERY_VALUE) - break; - } - - // 电量超出范围退出 + // 电量有效性校验 if (quantityOfElectricity < 0 || quantityOfElectricity > 100) { - LogUtils.w(TAG, "run: 电量无效,修正为无效值 | currentBattery=" + quantityOfElectricity); + LogUtils.w(TAG, "run: 电量无效,退出循环 | currentBattery=" + quantityOfElectricity); break; } - // 防重复提醒(间隔未到/计时器运行中,依赖volatile保证可见性) - long currentTime = System.currentTimeMillis(); - if ((currentTime - lastRemindTime < REMIND_INTERVAL) || isRemindTimerRunning) { - safeSleepInternal(sleepTime); - continue; - } - - // 充电提醒触发 + // 充电提醒触发逻辑 if (isCharging && isEnableChargeReminder && quantityOfElectricity >= chargeReminderValue) { - LogUtils.d(TAG, "run: 循环检测触发充电提醒 | battery=" + quantityOfElectricity + " ≥ threshold=" + chargeReminderValue); + LogUtils.d(TAG, "run: 触发充电提醒 | battery=" + quantityOfElectricity + " ≥ threshold=" + chargeReminderValue); sendNotificationMessageInternal("+", quantityOfElectricity, isCharging); - lastRemindTime = currentTime; - startRemindRecoveryTimerInternal(); } else if (!isCharging && isEnableUsageReminder && quantityOfElectricity <= usageReminderValue) { - LogUtils.d(TAG, "run: 循环检测触发耗电提醒 | battery=" + quantityOfElectricity + " ≤ threshold=" + usageReminderValue); + LogUtils.d(TAG, "run: 触发耗电提醒 | battery=" + quantityOfElectricity + " ≤ threshold=" + usageReminderValue); sendNotificationMessageInternal("-", quantityOfElectricity, isCharging); - lastRemindTime = currentTime; - startRemindRecoveryTimerInternal(); } + // 安全休眠 safeSleepInternal(sleepTime); } catch (Exception e) { LogUtils.e(TAG, "run: 线程运行异常,休眠重试", e); @@ -226,57 +224,28 @@ public class RemindThread extends Thread { } } - // 退出清理 + // 循环退出,清理状态 cleanThreadStateInternal(); LogUtils.d(TAG, "run: 线程循环退出 | threadId=" + Thread.currentThread().getId()); } - // ================================== 核心业务辅助方法(全部私有化,移除对外访问)================================= + // ================================== 内部业务辅助方法================================= /** - * 配置同步重试(确保阈值有效,失败兜底) - */ -// private boolean syncConfigRetry() { -// LogUtils.d(TAG, "syncConfigRetry: 开始配置同步 | maxRetry=" + CONFIG_RETRY_MAX); -// int retryCount = 0; -// -// while (retryCount < CONFIG_RETRY_MAX) { -// boolean chargeValid = chargeReminderValue >= 0 && chargeReminderValue <= 100; -// boolean usageValid = usageReminderValue >= 0 && usageReminderValue <= 100; -// if (chargeValid && usageValid) { -// LogUtils.d(TAG, "syncConfigRetry: 配置同步成功 | retryCount=" + retryCount); -// return true; -// } -// LogUtils.w(TAG, "syncConfigRetry: 配置未同步,重试 | retryCount=" + (retryCount + 1)); -// try { -// Thread.sleep(1000); -// retryCount++; -// } catch (InterruptedException e) { -// Thread.currentThread().interrupt(); -// LogUtils.e(TAG, "syncConfigRetry: 配置重试被中断", e); -// return false; -// } -// } -// -// // 兜底默认阈值 -// chargeReminderValue = (chargeReminderValue < 0 || chargeReminderValue > 100) ? 80 : chargeReminderValue; -// usageReminderValue = (usageReminderValue < 0 || usageReminderValue > 100) ? 20 : usageReminderValue; -// quantityOfElectricity = INVALID_BATTERY_VALUE; -// LogUtils.e(TAG, "syncConfigRetry: 配置重试失败,使用兜底阈值 | chargeThreshold=" + chargeReminderValue + " | usageThreshold=" + usageReminderValue); -// return false; -// } - - /** - * 发送提醒消息(携带当前电量+充电状态,弱引用Handler+Message复用,防泄漏) + * 发送提醒消息(内部方法,弱引用Handler防泄漏) + * @param type 提醒类型:+充电/-耗电 + * @param battery 当前电量 + * @param isCharging 充电状态 */ private void sendNotificationMessageInternal(String type, int battery, boolean isCharging) { - LogUtils.d(TAG, "sendNotificationMessageInternal: 准备发送提醒 | type=" + type + " | battery=" + battery + " | isCharging=" + isCharging); - + LogUtils.d(TAG, "sendNotificationMessageInternal: 调用 | type=" + type + " | battery=" + battery + " | isCharging=" + isCharging); + // 前置校验 if (isExist || !isReminding) { LogUtils.d(TAG, "sendNotificationMessageInternal: 线程退出或提醒关闭,跳过发送"); return; } - ControlCenterServiceHandler handler = mwrControlCenterServiceHandler != null ? mwrControlCenterServiceHandler.get() : null; + // 获取Handler并发送消息 + ControlCenterServiceHandler handler = mwrControlCenterServiceHandler.get(); if (handler == null) { LogUtils.w(TAG, "sendNotificationMessageInternal: Handler已回收,发送失败"); return; @@ -297,51 +266,8 @@ public class RemindThread extends Thread { } /** - * 启动提醒恢复计时器(防重复提醒,弱引用线程) - */ - private void startRemindRecoveryTimerInternal() { - LogUtils.d(TAG, "startRemindRecoveryTimerInternal: 启动提醒恢复计时器 | interval=" + REMIND_INTERVAL + "ms"); - if (isExist || isRemindTimerRunning || sInstance != this) { - LogUtils.w(TAG, "startRemindRecoveryTimerInternal: 计时器启动条件不满足"); - return; - } - isReminding = false; - isRemindTimerRunning = true; - - final WeakReference threadRef = new WeakReference<>(this); - new Thread(new Runnable() { - @Override - public void run() { - try { - Thread.sleep(REMIND_INTERVAL); - RemindThread thread = threadRef.get(); - - if (thread == null || thread.isExist || sInstance != thread) { - LogUtils.d(TAG, "startRemindRecoveryTimerInternal: 线程已销毁,不恢复提醒"); - return; - } - - boolean canRecover = !thread.isExist && sInstance == thread && (thread.isEnableChargeReminder || thread.isEnableUsageReminder); - if (canRecover) { - thread.isReminding = true; - LogUtils.d(TAG, "startRemindRecoveryTimerInternal: 提醒功能恢复开启"); - } - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - LogUtils.e(TAG, "startRemindRecoveryTimerInternal: 计时器被中断", e); - } finally { - RemindThread thread = threadRef.get(); - if (thread != null && sInstance == thread) { - thread.isRemindTimerRunning = false; - } - LogUtils.d(TAG, "startRemindRecoveryTimerInternal: 提醒恢复计时器执行完成"); - } - } - }, "RemindRecoveryTimer").start(); - } - - /** - * 安全休眠(保留中断标记,确保退出逻辑生效) + * 安全休眠(保留中断标记,确保线程可退出) + * @param millis 休眠时长 */ private void safeSleepInternal(long millis) { try { @@ -353,29 +279,14 @@ public class RemindThread extends Thread { } /** - * 清理线程运行状态(退出后重置所有标记) - */ - private void cleanThreadStateInternal() { - LogUtils.d(TAG, "cleanThreadStateInternal: 清理线程运行状态"); - isReminding = false; - isExist = true; - isThreadStarted = false; - isRemindTimerRunning = false; - lastRemindTime = 0; - quantityOfElectricity = INVALID_BATTERY_VALUE; - if (isAlive()) interrupt(); - } - - /** - * 初始状态重置(构造器专用) + * 重置线程初始状态(构造器专用) */ private void resetThreadStateInternal() { LogUtils.d(TAG, "resetThreadStateInternal: 重置线程初始状态"); + // 状态标记 isExist = false; isReminding = false; - isThreadStarted = false; - isRemindTimerRunning = false; - lastRemindTime = 0; + // 配置参数 isEnableChargeReminder = false; isEnableUsageReminder = false; sleepTime = DEFAULT_SLEEP_TIME; @@ -386,23 +297,38 @@ public class RemindThread extends Thread { } /** - * 同步应用配置(参数校验+范围限制,立即生效) + * 清理线程运行状态(退出循环专用) + */ + private void cleanThreadStateInternal() { + LogUtils.d(TAG, "cleanThreadStateInternal: 清理线程运行状态"); + isReminding = false; + isExist = true; + quantityOfElectricity = INVALID_BATTERY_VALUE; + if (isAlive()) { + interrupt(); + } + } + + /** + * 同步应用配置(参数范围校验,确保有效性) + * @param config 应用配置Bean */ public void setAppConfigBean(AppConfigBean config) { - LogUtils.d(TAG, "setAppConfigBean: 开始同步应用配置 | config=" + config); + LogUtils.d(TAG, "setAppConfigBean: 调用 | config=" + config); if (config == null) { LogUtils.e(TAG, "setAppConfigBean: 配置Bean为空,同步失败"); quantityOfElectricity = INVALID_BATTERY_VALUE; return; } + // 配置参数同步+范围校验 isEnableChargeReminder = config.isEnableChargeReminder(); isEnableUsageReminder = config.isEnableUsageReminder(); chargeReminderValue = Math.min(Math.max(config.getChargeReminderValue(), 0), 100); usageReminderValue = Math.min(Math.max(config.getUsageReminderValue(), 0), 100); sleepTime = Math.max(config.getBatteryDetectInterval(), MIN_SLEEP_TIME); - int currentBattery = config.getCurrentBatteryValue(); - quantityOfElectricity = (currentBattery >= 0 && currentBattery <= 100) ? currentBattery : INVALID_BATTERY_VALUE; + quantityOfElectricity = (config.getCurrentBatteryValue() >= 0 && config.getCurrentBatteryValue() <= 100) + ? config.getCurrentBatteryValue() : INVALID_BATTERY_VALUE; isCharging = config.isCharging(); isReminding = isEnableChargeReminder || isEnableUsageReminder; @@ -410,29 +336,39 @@ public class RemindThread extends Thread { } /** - * 判断线程是否处于运行状态 - */ - private boolean isRunning() { - boolean running = !isExist && isThreadStarted && isAlive(); - LogUtils.d(TAG, "isRunning: 线程运行状态=" + running + " | isExist=" + isExist + " | isThreadStarted=" + isThreadStarted + " | isAlive=" + isAlive()); - return running; - } - - /** - * 释放线程所有资源(内部方法) + * 释放线程资源(内部方法,防内存泄漏) */ private void releaseResourcesInternal() { - LogUtils.d(TAG, "releaseResourcesInternal: 开始释放线程资源"); + LogUtils.d(TAG, "releaseResourcesInternal: 释放线程资源"); mContext = null; if (mwrControlCenterServiceHandler != null) { mwrControlCenterServiceHandler.clear(); mwrControlCenterServiceHandler = null; } cleanThreadStateInternal(); - LogUtils.d(TAG, "releaseResourcesInternal: 线程资源释放完成"); } - // ================================== 调试辅助(toString 私有化,避免对外暴露状态)================================= + /** + * 判断线程是否处于运行状态 + * @return true: 运行中;false: 已停止 + */ + private boolean isRunning() { + boolean running = !isExist && isAlive(); + LogUtils.d(TAG, "isRunning: 线程运行状态=" + running + " | isExist=" + isExist + " | isAlive=" + isAlive()); + return running; + } + + // ================================== Getter/Setter(按需开放)================================= + public void setIsExist(boolean isExist) { + LogUtils.d(TAG, "setIsExist: 调用 | isExist=" + isExist); + this.isExist = isExist; + } + + public boolean isExist() { + return isExist; + } + + // ================================== 调试辅助方法================================= @Override public String toString() { return "RemindThread{" +