电量提醒消息,通路架构基本完成。

This commit is contained in:
2025-12-19 18:48:47 +08:00
parent 9bc71bb3f6
commit bc6a82af41
5 changed files with 447 additions and 645 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -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<ControlCenterService> 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;
}
}

View File

@@ -21,148 +21,145 @@ import java.io.Serializable;
import java.util.List;
/**
* 电池提醒核心服务
* 功能:管理前台服务生命周期、控制提醒线程启停、处理配置更新
* 适配Java7 | API30 | 前台服务超时防护 | 电池优化忽略引导
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
* @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;
}
// ================================== 核心业务逻辑(抽取独立方法,统一管理=================================
// ================================== 核心业务逻辑(独立抽取,统一调用=================================
/**
* 抽取的服务核心运行逻辑,统一在onCreateonStartCommand
* 复用 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<ActivityManager.RunningAppProcessInfo> 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<ActivityManager.RunningServiceInfo> runningServices = am.getRunningServices(100);
if (runningServices != null) {
String serviceClassName = serviceClass.getName();
for (ActivityManager.RunningServiceInfo info : runningServices) {
// API30- 通过服务列表判断
List<ActivityManager.RunningServiceInfo> 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;
}

View File

@@ -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<ControlCenterServiceHandler> 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<RemindThread> 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{" +