mirror of
https://gitea.winboll.cc/Studio/OriginMaster.git
synced 2026-02-06 12:51:33 +08:00
源码整理。
This commit is contained in:
@@ -26,7 +26,7 @@ import java.util.List;
|
||||
/**
|
||||
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
|
||||
* @Date 2025/12/17 15:48
|
||||
* @Describe 电池提醒核心服务:修复前台服务超时异常,优先在onCreate发送通知,适配Java7+API36
|
||||
* @Describe 电池提醒核心服务:修复前台服务超时异常,优先在onCreate发送通知,适配Java7+API30
|
||||
*/
|
||||
public class ControlCenterService extends Service {
|
||||
// ================================== 静态常量(置顶统一管理,避免魔法值)=================================
|
||||
@@ -34,28 +34,22 @@ public class ControlCenterService extends Service {
|
||||
// 服务指令常量(带包名前缀,防止冲突)
|
||||
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";
|
||||
// 新增:应用前台/后台状态同步指令(用于MainActivity与服务联动)
|
||||
// public static final String ACTION_SYNC_APP_FOREGROUND_STATE = "cc.winboll.studio.powerbell.action.SYNC_APP_FOREGROUND_STATE";
|
||||
// public static final String EXTRA_APP_FOREGROUND_STATE = "cc.winboll.studio.powerbell.extra.APP_FOREGROUND_STATE";
|
||||
|
||||
// ================================== 核心成员变量(按依赖优先级排序,私有封装)=================================
|
||||
// 服务控制核心(本地持久化管理,替代Intent传递)
|
||||
// ================================== 成员变量(按功能分类,私有封装+并发锁保护)=================================
|
||||
// 服务控制核心
|
||||
private ControlCenterServiceBean mServiceControlBean;
|
||||
// 业务核心组件
|
||||
private ControlCenterServiceHandler mServiceHandler; // 服务通信Handler
|
||||
private RemindThread mRemindThread; // 电量提醒线程
|
||||
private NotificationManagerUtils mNotificationManager; // 通知管理工具类
|
||||
private AppConfigBean mCurrentConfigBean; // 当前应用配置
|
||||
// 前台服务相关
|
||||
private NotificationMessage mForegroundNotifyMsg; // 前台保活通知模型
|
||||
// 新增:应用前台状态标记(内存缓存,同步MainActivity状态)
|
||||
private boolean mIsAppForeground = false;
|
||||
// 状态标记(并发安全)
|
||||
private boolean isServiceRunning = false; // 服务运行状态
|
||||
private boolean mIsDestroyed = false; // 服务销毁标记
|
||||
private final Object mServiceLock = new Object(); // 全局并发锁
|
||||
private ControlCenterServiceHandler mServiceHandler;
|
||||
private RemindThread mRemindThread;
|
||||
private NotificationManagerUtils mNotificationManager;
|
||||
private AppConfigBean mCurrentConfigBean;
|
||||
private NotificationMessage mForegroundNotifyMsg;
|
||||
// 状态标记
|
||||
private boolean isServiceRunning;
|
||||
private boolean mIsDestroyed;
|
||||
private final Object mServiceLock = new Object();
|
||||
|
||||
// ================================== 服务生命周期方法(核心修复:onCreate优先发送通知)=================================
|
||||
// ================================== 服务生命周期方法(核心流程入口)=================================
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
@@ -63,45 +57,33 @@ public class ControlCenterService extends Service {
|
||||
synchronized (mServiceLock) {
|
||||
isServiceRunning = true;
|
||||
mIsDestroyed = false;
|
||||
|
||||
// ================================== 【修复点1:最优先执行前台通知发送】=================================
|
||||
// 优先发送前台通知,避免5秒超时异常
|
||||
initForegroundNotificationImmediately();
|
||||
|
||||
// 原有逻辑:读取本地服务控制配置
|
||||
// 加载本地服务控制配置
|
||||
mServiceControlBean = ControlCenterServiceBean.loadBean(this, ControlCenterServiceBean.class);
|
||||
if (mServiceControlBean == null) {
|
||||
mServiceControlBean = new ControlCenterServiceBean(false);
|
||||
ControlCenterServiceBean.saveBean(this, mServiceControlBean); // 持久化默认配置
|
||||
LogUtils.d(TAG, "onCreate: 本地无控制配置,创建默认禁用配置并持久化");
|
||||
} else {
|
||||
LogUtils.d(TAG, "onCreate: 从本地读取服务控制配置,启用状态=" + mServiceControlBean.isEnableService());
|
||||
ControlCenterServiceBean.saveBean(this, mServiceControlBean);
|
||||
LogUtils.d(TAG, "onCreate: 本地无配置,创建默认禁用配置并持久化");
|
||||
}
|
||||
}
|
||||
LogUtils.d(TAG, "onCreate: 服务创建完成,前台通知已发送,当前服务控制状态:" + (mServiceControlBean.isEnableService() ? "启用" : "禁用"));
|
||||
LogUtils.d(TAG, "onCreate: 服务创建完成,前台通知已发送,启用状态=" + mServiceControlBean.isEnableService());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
LogUtils.d(TAG, "onStartCommand: 服务启动指令触发,flags=" + flags);
|
||||
// 第一步:读取本地最新控制配置(优先级最高,实时同步用户设置)
|
||||
LogUtils.d(TAG, "onStartCommand: 服务启动指令触发");
|
||||
// 读取最新控制配置
|
||||
loadLatestServiceControlConfig();
|
||||
// 第二步:根据控制状态,分支执行逻辑
|
||||
synchronized (mServiceLock) {
|
||||
if (mServiceControlBean.isEnableService()) {
|
||||
LogUtils.d(TAG, "onStartCommand: 服务已启用,执行核心逻辑");
|
||||
// 启用状态:处理指令+启动业务,返回START_STICKY(回收后重启)
|
||||
LogUtils.d(TAG, "onStartCommand: 服务已启用,处理外部指令并初始化业务");
|
||||
handleExternalCommand(intent);
|
||||
// ================================== 【修复点2:删除rebindForegroundNotify(),避免重复调用】=================================
|
||||
initServiceBusinessIfNeed(); // 按需初始化业务(避免重复初始化)
|
||||
// // 新增:业务初始化完成后,同步应用前台状态到线程(防止状态丢失)
|
||||
// syncAppForegroundStateToThread();
|
||||
LogUtils.d(TAG, "onStartCommand: 核心逻辑执行完成,返回START_STICKY");
|
||||
initServiceBusinessIfNeed();
|
||||
return START_STICKY;
|
||||
} else {
|
||||
LogUtils.d(TAG, "onStartCommand: 服务已禁用,不执行核心逻辑");
|
||||
// 禁用状态:停止所有业务+释放资源,返回父类默认值(回收后不主动重启)
|
||||
LogUtils.d(TAG, "onStartCommand: 服务已禁用,停止所有业务");
|
||||
stopAllBusinessSafely();
|
||||
LogUtils.d(TAG, "onStartCommand: 已停止所有业务,返回父类默认onStartCommand结果");
|
||||
return super.onStartCommand(intent, flags, startId);
|
||||
}
|
||||
}
|
||||
@@ -110,13 +92,12 @@ public class ControlCenterService extends Service {
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
LogUtils.d(TAG, "onDestroy: 服务开始销毁,释放所有资源");
|
||||
LogUtils.d(TAG, "onDestroy: 服务开始销毁");
|
||||
synchronized (mServiceLock) {
|
||||
isServiceRunning = false;
|
||||
mIsDestroyed = true;
|
||||
mIsAppForeground = false; // 新增:重置前台状态
|
||||
}
|
||||
// 顺序释放资源(前台服务→线程→Handler→通知→配置→控制Bean)
|
||||
// 顺序释放资源
|
||||
stopForegroundService();
|
||||
stopRemindThreadSafely();
|
||||
destroyHandler();
|
||||
@@ -127,109 +108,95 @@ public class ControlCenterService extends Service {
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null; // 无需绑定服务,返回null
|
||||
return null;
|
||||
}
|
||||
|
||||
// ================================== 【新增核心方法:优先发送前台通知,带兜底方案】=================================
|
||||
// ================================== 前台通知核心方法(优先执行,防止超时)=================================
|
||||
/**
|
||||
* 独立初始化前台通知并立即发送,不依赖任何业务逻辑,确保5秒内完成startForeground()
|
||||
* 防止工具类异常导致超时,内置兜底方案
|
||||
* 立即初始化前台通知,内置兜底方案
|
||||
*/
|
||||
private void initForegroundNotificationImmediately() {
|
||||
LogUtils.d(TAG, "initForegroundNotificationImmediately: 强制初始化前台通知");
|
||||
LogUtils.d(TAG, "initForegroundNotificationImmediately: 初始化前台通知");
|
||||
try {
|
||||
// 1. 初始化通知工具类
|
||||
if (mNotificationManager == null) {
|
||||
mNotificationManager = new NotificationManagerUtils(this);
|
||||
}
|
||||
// 2. 构建极简前台通知模型(不依赖业务配置,确保最快速度发送)
|
||||
if (mForegroundNotifyMsg == null) {
|
||||
mForegroundNotifyMsg = new NotificationMessage();
|
||||
mForegroundNotifyMsg.setTitle("电池监测服务");
|
||||
mForegroundNotifyMsg.setContent("后台运行中");
|
||||
mForegroundNotifyMsg.setRemindMSG("service_running");
|
||||
}
|
||||
// 3. 立即调用工具类发送前台通知
|
||||
mNotificationManager.startForegroundServiceNotify(this, mForegroundNotifyMsg);
|
||||
LogUtils.d(TAG, "initForegroundNotificationImmediately: 前台通知发送成功,ID=" + NotificationManagerUtils.NOTIFY_ID_FOREGROUND_SERVICE);
|
||||
} catch (Exception e) {
|
||||
LogUtils.e(TAG, "initForegroundNotificationImmediately: 工具类发送失败,执行兜底方案", e);
|
||||
// 兜底方案:绕过工具类,直接构建Notification调用startForeground
|
||||
fallbackStartForeground();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 前台通知兜底方案:当工具类异常时,直接创建通知,确保不触发超时异常
|
||||
* 前台通知兜底方案,直接构建Notification
|
||||
*/
|
||||
private void fallbackStartForeground() {
|
||||
try {
|
||||
Notification notification = new NotificationCompat.Builder(this, NotificationManagerUtils.CHANNEL_ID_FOREGROUND)
|
||||
.setContentTitle("电池监测服务")
|
||||
.setContentText("后台运行中")
|
||||
.setSmallIcon(R.drawable.ic_launcher) // 必须设置小图标,否则通知不显示
|
||||
.setSmallIcon(R.drawable.ic_launcher)
|
||||
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||
.build();
|
||||
// 直接调用startForeground,不依赖任何外部工具
|
||||
startForeground(NotificationManagerUtils.NOTIFY_ID_FOREGROUND_SERVICE, notification);
|
||||
LogUtils.d(TAG, "fallbackStartForeground: 兜底前台通知发送成功");
|
||||
} catch (Exception e) {
|
||||
LogUtils.e(TAG, "fallbackStartForeground: 兜底发送失败,服务会被系统强制杀死", e);
|
||||
LogUtils.e(TAG, "fallbackStartForeground: 兜底发送失败,服务会被系统杀死", e);
|
||||
}
|
||||
}
|
||||
|
||||
// ================================== 核心:服务控制配置(本地持久化读写,替代Intent传递)=================================
|
||||
// ================================== 服务控制配置管理(本地持久化+内存同步)=================================
|
||||
/**
|
||||
* 读取本地最新服务控制配置(实时同步,确保与用户设置一致)
|
||||
* 读取本地最新服务控制配置
|
||||
*/
|
||||
private void loadLatestServiceControlConfig() {
|
||||
LogUtils.d(TAG, "loadLatestServiceControlConfig: 读取本地最新服务控制配置");
|
||||
LogUtils.d(TAG, "loadLatestServiceControlConfig: 读取本地配置");
|
||||
synchronized (mServiceLock) {
|
||||
ControlCenterServiceBean latestControlBean = ControlCenterServiceBean.loadBean(this, ControlCenterServiceBean.class);
|
||||
if (latestControlBean != null) {
|
||||
boolean oldState = mServiceControlBean.isEnableService();
|
||||
boolean newState = latestControlBean.isEnableService();
|
||||
mServiceControlBean = latestControlBean;
|
||||
LogUtils.d(TAG, "loadLatestServiceControlConfig: 控制配置更新完成,旧状态=" + oldState + ",新状态=" + newState);
|
||||
ControlCenterServiceBean latestBean = ControlCenterServiceBean.loadBean(this, ControlCenterServiceBean.class);
|
||||
if (latestBean != null) {
|
||||
mServiceControlBean = latestBean;
|
||||
LogUtils.d(TAG, "loadLatestServiceControlConfig: 配置更新完成,启用状态=" + mServiceControlBean.isEnableService());
|
||||
} else {
|
||||
LogUtils.w(TAG, "loadLatestServiceControlConfig: 本地无控制配置,沿用当前状态=" + mServiceControlBean.isEnableService());
|
||||
LogUtils.w(TAG, "loadLatestServiceControlConfig: 本地无配置,沿用当前状态");
|
||||
}
|
||||
}
|
||||
LogUtils.d(TAG, "loadLatestServiceControlConfig: 控制配置读取完成,当前服务启用状态=" + mServiceControlBean.isEnableService());
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新服务控制配置(本地持久化+内存同步,对外提供统一入口)
|
||||
* 更新并持久化服务控制配置
|
||||
*/
|
||||
private void updateAndSaveServiceControlConfig(ControlCenterServiceBean newControlBean) {
|
||||
LogUtils.d(TAG, "updateAndSaveServiceControlConfig: 更新服务控制配置,新状态=" + newControlBean.isEnableService());
|
||||
if (newControlBean == null) {
|
||||
LogUtils.e(TAG, "updateAndSaveServiceControlConfig: 新控制配置为空,更新失败");
|
||||
LogUtils.e(TAG, "updateAndSaveServiceControlConfig: 配置为空,更新失败");
|
||||
return;
|
||||
}
|
||||
|
||||
LogUtils.d(TAG, "updateAndSaveServiceControlConfig: 更新配置,启用状态=" + newControlBean.isEnableService());
|
||||
synchronized (mServiceLock) {
|
||||
// 内存同步+本地持久化(原子操作,确保一致性)
|
||||
mServiceControlBean = newControlBean;
|
||||
ControlCenterServiceBean.saveBean(this, mServiceControlBean);
|
||||
LogUtils.d(TAG, "updateAndSaveServiceControlConfig: 控制配置更新并持久化完成");
|
||||
}
|
||||
}
|
||||
|
||||
// ================================== 业务按需初始化/停止方法(适配启用/禁用状态切换)=================================
|
||||
// ================================== 业务初始化与停止(按需加载,避免重复)=================================
|
||||
/**
|
||||
* 按需初始化核心业务(仅服务启用且未初始化时执行,避免重复创建)
|
||||
* 按需初始化核心业务
|
||||
*/
|
||||
private void initServiceBusinessIfNeed() {
|
||||
LogUtils.d(TAG, "initServiceBusinessIfNeed: 按需初始化业务");
|
||||
LogUtils.d(TAG, "initServiceBusinessIfNeed: 校验业务初始化条件");
|
||||
synchronized (mServiceLock) {
|
||||
// 校验:服务启用+未初始化+服务运行中
|
||||
if (!mServiceControlBean.isEnableService() || mServiceHandler != null || !isServiceRunning || mIsDestroyed) {
|
||||
LogUtils.w(TAG, "initServiceBusinessIfNeed: 无需初始化业务(禁用/已初始化/服务未运行)");
|
||||
LogUtils.w(TAG, "initServiceBusinessIfNeed: 无需初始化业务");
|
||||
return;
|
||||
}
|
||||
|
||||
// 初始化通知+配置+业务逻辑(完整启动核心流程)
|
||||
// 初始化通知+配置+业务逻辑
|
||||
initNotificationManager();
|
||||
loadDefaultConfig();
|
||||
initServiceBusinessLogic();
|
||||
@@ -238,85 +205,38 @@ public class ControlCenterService extends Service {
|
||||
}
|
||||
|
||||
/**
|
||||
* 安全停止所有核心业务(服务禁用时执行,释放所有业务资源)
|
||||
* 安全停止所有核心业务
|
||||
*/
|
||||
private void stopAllBusinessSafely() {
|
||||
LogUtils.d(TAG, "stopAllBusinessSafely: 停止所有核心业务");
|
||||
LogUtils.d(TAG, "stopAllBusinessSafely: 停止所有业务");
|
||||
synchronized (mServiceLock) {
|
||||
// 停止线程+销毁Handler+释放通知+置空业务引用
|
||||
stopRemindThreadSafely();
|
||||
destroyHandler();
|
||||
stopForegroundService();
|
||||
releaseNotificationResource();
|
||||
mCurrentConfigBean = null;
|
||||
mForegroundNotifyMsg = null;
|
||||
mIsAppForeground = false; // 新增:重置前台状态
|
||||
LogUtils.d(TAG, "stopAllBusinessSafely: 所有核心业务已停止");
|
||||
}
|
||||
}
|
||||
|
||||
// ================================== 核心业务初始化方法(按依赖顺序排列)=================================
|
||||
/**
|
||||
* 初始化通知管理工具类,构建前台保活通知模型
|
||||
* 【修复点3:移除内部的startForegroundNotifyImmediately()调用,避免重复发送】
|
||||
* 初始化通知管理工具类
|
||||
*/
|
||||
private void initNotificationManager() {
|
||||
LogUtils.d(TAG, "initNotificationManager: 初始化通知工具类");
|
||||
try {
|
||||
if (mNotificationManager == null) {
|
||||
mNotificationManager = new NotificationManagerUtils(this);
|
||||
}
|
||||
if (mForegroundNotifyMsg == null) {
|
||||
mForegroundNotifyMsg = new NotificationMessage();
|
||||
mForegroundNotifyMsg.setTitle("电池提醒服务运行中");
|
||||
mForegroundNotifyMsg.setContent("后台持续监测电池状态,确保提醒及时");
|
||||
mForegroundNotifyMsg.setRemindMSG("service_running");
|
||||
// 移除:此处不再发送通知,通知已在onCreate中发送
|
||||
}
|
||||
LogUtils.d(TAG, "initNotificationManager: 通知工具类初始化完成");
|
||||
} catch (Exception e) {
|
||||
LogUtils.e(TAG, "initNotificationManager: 初始化失败", e);
|
||||
LogUtils.d(TAG, "initNotificationManager: 初始化通知工具");
|
||||
if (mNotificationManager == null) {
|
||||
mNotificationManager = new NotificationManagerUtils(this);
|
||||
}
|
||||
if (mForegroundNotifyMsg == null) {
|
||||
mForegroundNotifyMsg = new NotificationMessage();
|
||||
mForegroundNotifyMsg.setTitle("电池提醒服务运行中");
|
||||
mForegroundNotifyMsg.setContent("后台持续监测电池状态");
|
||||
mForegroundNotifyMsg.setRemindMSG("service_running");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 立即启动前台保活通知(API26+ 前台服务必需)
|
||||
* 注:当前仅作为备用方法,实际已在initForegroundNotificationImmediately中调用
|
||||
*/
|
||||
private void startForegroundNotifyImmediately() {
|
||||
LogUtils.d(TAG, "startForegroundNotifyImmediately: 启动前台保活通知");
|
||||
if (mNotificationManager == null || mForegroundNotifyMsg == null) {
|
||||
LogUtils.e(TAG, "startForegroundNotifyImmediately: 通知工具类/模型为空,启动失败");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
mNotificationManager.startForegroundServiceNotify(this, mForegroundNotifyMsg);
|
||||
LogUtils.d(TAG, "startForegroundNotifyImmediately: 前台通知启动成功,ID=" + NotificationManagerUtils.NOTIFY_ID_FOREGROUND_SERVICE);
|
||||
} catch (Exception e) {
|
||||
LogUtils.e(TAG, "startForegroundNotifyImmediately: 前台通知启动异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新绑定前台通知(已删除调用,防止重复执行startForeground)
|
||||
*/
|
||||
private void rebindForegroundNotify() {
|
||||
if (mNotificationManager == null || mNotificationManager.getForegroundServiceNotify() == null) {
|
||||
LogUtils.w(TAG, "rebindForegroundNotify: 通知工具类/前台通知为空,跳过绑定");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
startForeground(NotificationManagerUtils.NOTIFY_ID_FOREGROUND_SERVICE, mNotificationManager.getForegroundServiceNotify());
|
||||
LogUtils.d(TAG, "rebindForegroundNotify: 前台通知重新绑定成功");
|
||||
} catch (Exception e) {
|
||||
LogUtils.e(TAG, "rebindForegroundNotify: 重新绑定前台通知异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载默认应用配置(服务启动时兜底)
|
||||
* 加载默认应用配置
|
||||
*/
|
||||
private void loadDefaultConfig() {
|
||||
LogUtils.d(TAG, "loadDefaultConfig: 加载默认配置");
|
||||
@@ -327,93 +247,71 @@ public class ControlCenterService extends Service {
|
||||
mCurrentConfigBean.setEnableUsageReminder(true);
|
||||
mCurrentConfigBean.setUsageReminderValue(20);
|
||||
mCurrentConfigBean.setBatteryDetectInterval(1000);
|
||||
LogUtils.d(TAG, "loadDefaultConfig: 默认配置加载完成,充电阈值80%,耗电阈值20%");
|
||||
} else {
|
||||
LogUtils.d(TAG, "loadDefaultConfig: 配置已存在,无需重复加载");
|
||||
LogUtils.d(TAG, "loadDefaultConfig: 默认配置加载完成");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化业务核心逻辑(Handler+提醒线程)
|
||||
* 初始化业务核心逻辑(Handler+线程)
|
||||
*/
|
||||
private void initServiceBusinessLogic() {
|
||||
LogUtils.d(TAG, "initServiceBusinessLogic: 初始化业务逻辑");
|
||||
LogUtils.d(TAG, "initServiceBusinessLogic: 初始化Handler与线程");
|
||||
if (mServiceHandler == null) {
|
||||
mServiceHandler = new ControlCenterServiceHandler(this);
|
||||
}
|
||||
// 复用线程重启方法,统一启动逻辑
|
||||
restartRemindThreadSafely();
|
||||
LogUtils.d(TAG, "initServiceBusinessLogic: 业务逻辑初始化完成");
|
||||
}
|
||||
|
||||
// ================================== 线程管理方法(安全启动/停止/重启,保障并发安全)=================================
|
||||
// ================================== 提醒线程管理(安全启停,并发保护)=================================
|
||||
/**
|
||||
* 安全重启提醒线程(彻底销毁旧线程,创建全新实例,避免重复启动)
|
||||
* 安全重启提醒线程
|
||||
*/
|
||||
public void restartRemindThreadSafely() {
|
||||
LogUtils.d(TAG, "restartRemindThreadSafely: 开始重启提醒线程");
|
||||
LogUtils.d(TAG, "restartRemindThreadSafely: 开始重启线程");
|
||||
synchronized (mServiceLock) {
|
||||
// 服务禁用/已销毁,直接返回
|
||||
if (!isServiceRunning || mIsDestroyed || !mServiceControlBean.isEnableService()) {
|
||||
LogUtils.e(TAG, "restartRemindThreadSafely: 服务未运行/已销毁/已禁用,启动失败");
|
||||
LogUtils.e(TAG, "restartRemindThreadSafely: 服务状态异常,启动失败");
|
||||
return;
|
||||
}
|
||||
|
||||
// 先停止旧线程
|
||||
// 停止旧线程
|
||||
stopRemindThreadSafely();
|
||||
|
||||
// 校验Handler,避免无效启动
|
||||
if (mServiceHandler == null) {
|
||||
LogUtils.e(TAG, "restartRemindThreadSafely: Handler为空,启动失败");
|
||||
return;
|
||||
}
|
||||
|
||||
// 销毁旧单例,创建新线程实例
|
||||
// 创建新线程实例
|
||||
RemindThread.destroyInstance();
|
||||
mRemindThread = RemindThread.getInstance(this, mServiceHandler);
|
||||
// 同步配置并开启提醒
|
||||
syncConfigToRemindThread();
|
||||
// // 新增:同步应用前台状态(确保新线程启动时状态正确)
|
||||
// syncAppForegroundStateToThread();
|
||||
|
||||
// 双重校验,避免线程重复启动
|
||||
// 启动线程
|
||||
if (mRemindThread != null && !mRemindThread.isAlive() && !mRemindThread.isThreadStarted()) {
|
||||
try {
|
||||
mRemindThread.start();
|
||||
LogUtils.d(TAG, "restartRemindThreadSafely: 新线程启动成功,ID=" + mRemindThread.getId() + ",前台状态=" + mIsAppForeground);
|
||||
LogUtils.d(TAG, "restartRemindThreadSafely: 新线程启动成功,ID=" + mRemindThread.getId());
|
||||
} catch (IllegalThreadStateException e) {
|
||||
LogUtils.e(TAG, "restartRemindThreadSafely: 线程重复启动异常", e);
|
||||
mRemindThread = null;
|
||||
} catch (Exception e) {
|
||||
LogUtils.e(TAG, "restartRemindThreadSafely: 启动线程异常", e);
|
||||
mRemindThread = null;
|
||||
}
|
||||
} else {
|
||||
LogUtils.w(TAG, "restartRemindThreadSafely: 线程已启动/实例异常,跳过启动");
|
||||
mRemindThread = null;
|
||||
LogUtils.w(TAG, "restartRemindThreadSafely: 线程状态异常,跳过启动");
|
||||
}
|
||||
}
|
||||
LogUtils.d(TAG, "restartRemindThreadSafely: 线程重启流程结束");
|
||||
}
|
||||
|
||||
/**
|
||||
* 安全停止提醒线程(中断休眠+等待终止+释放资源,无残留)
|
||||
* 安全停止提醒线程
|
||||
*/
|
||||
private void stopRemindThreadSafely() {
|
||||
LogUtils.d(TAG, "stopRemindThreadSafely: 开始停止提醒线程");
|
||||
LogUtils.d(TAG, "stopRemindThreadSafely: 停止提醒线程");
|
||||
if (mRemindThread == null) {
|
||||
LogUtils.w(TAG, "stopRemindThreadSafely: 线程实例为空,跳过停止");
|
||||
LogUtils.w(TAG, "stopRemindThreadSafely: 线程实例为空");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 触发线程内部停止逻辑
|
||||
if (mRemindThread.isThreadStarted() || mRemindThread.isAlive()) {
|
||||
mRemindThread.setIsReminding(false);
|
||||
mRemindThread.stopThread();
|
||||
LogUtils.d(TAG, "stopRemindThreadSafely: 触发线程内部停止");
|
||||
|
||||
// 等待线程终止(超时1秒,避免阻塞服务)
|
||||
// 等待线程终止,超时1秒强制中断
|
||||
long waitStartTime = System.currentTimeMillis();
|
||||
while (mRemindThread.isAlive()) {
|
||||
if (System.currentTimeMillis() - waitStartTime > 1000) {
|
||||
@@ -427,140 +325,95 @@ public class ControlCenterService extends Service {
|
||||
} catch (Exception e) {
|
||||
LogUtils.e(TAG, "stopRemindThreadSafely: 停止线程异常", e);
|
||||
} finally {
|
||||
// 彻底释放资源
|
||||
mRemindThread = null;
|
||||
RemindThread.destroyInstance();
|
||||
LogUtils.d(TAG, "stopRemindThreadSafely: 线程停止完成,资源已释放");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步配置到提醒线程(原子操作,避免并发修改)
|
||||
* 同步配置到提醒线程
|
||||
*/
|
||||
private void syncConfigToRemindThread() {
|
||||
LogUtils.d(TAG, "syncConfigToRemindThread: 同步配置到线程");
|
||||
LogUtils.d(TAG, "syncConfigToRemindThread: 同步配置");
|
||||
synchronized (mServiceLock) {
|
||||
if (mRemindThread == null || mCurrentConfigBean == null) {
|
||||
LogUtils.e(TAG, "syncConfigToRemindThread: 线程/配置为空,同步失败");
|
||||
LogUtils.e(TAG, "syncConfigToRemindThread: 线程或配置为空,同步失败");
|
||||
return;
|
||||
}
|
||||
mRemindThread.setAppConfigBean(mCurrentConfigBean);
|
||||
mRemindThread.setIsReminding(true);
|
||||
LogUtils.d(TAG, "syncConfigToRemindThread: 配置同步完成");
|
||||
}
|
||||
}
|
||||
|
||||
// ================================== 外部指令处理(接收Intent指令)=================================
|
||||
/**
|
||||
* 新增:同步应用前台状态到RemindThread(核心联动逻辑)
|
||||
* 确保线程实时感知应用前台/后台状态,控制提醒开关
|
||||
*/
|
||||
// private void syncAppForegroundStateToThread() {
|
||||
// LogUtils.d(TAG, "syncAppForegroundStateToThread: 同步前台状态,当前状态=" + mIsAppForeground);
|
||||
// synchronized (mServiceLock) {
|
||||
// if (mRemindThread == null || mIsDestroyed || !isServiceRunning) {
|
||||
// LogUtils.w(TAG, "syncAppForegroundStateToThread: 线程未启动/服务已销毁,同步失败");
|
||||
// return;
|
||||
// }
|
||||
// // 调用RemindThread新增方法,同步前台状态(线程安全)
|
||||
// mRemindThread.setAppForeground(mIsAppForeground);
|
||||
// LogUtils.d(TAG, "syncAppForegroundStateToThread: 前台状态同步完成");
|
||||
// }
|
||||
// }
|
||||
|
||||
// ================================== 外部指令处理方法(新增前台状态同步指令,完善链路)=================================
|
||||
/**
|
||||
* 处理外部发送的服务指令(如重启线程、更新配置、同步前台状态)
|
||||
* 处理外部发送的服务指令
|
||||
*/
|
||||
private void handleExternalCommand(Intent intent) {
|
||||
LogUtils.d(TAG, "handleExternalCommand: 开始处理外部指令");
|
||||
if (intent == null) {
|
||||
LogUtils.e(TAG, "handleExternalCommand: Intent为空,跳过处理");
|
||||
LogUtils.d(TAG, "handleExternalCommand: 处理外部指令");
|
||||
if (intent == null || TextUtils.isEmpty(intent.getAction())) {
|
||||
LogUtils.e(TAG, "handleExternalCommand: Intent或Action为空");
|
||||
return;
|
||||
}
|
||||
|
||||
String action = intent.getAction();
|
||||
if (TextUtils.isEmpty(action)) {
|
||||
LogUtils.e(TAG, "handleExternalCommand: 指令Action为空,跳过处理");
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. 处理线程重启指令(仅同步业务配置,服务控制配置从本地读取)
|
||||
if (ACTION_RESTART_REMIND_THREAD.equals(action)) {
|
||||
// 读取本地最新控制配置,确保状态同步
|
||||
loadLatestServiceControlConfig();
|
||||
// 仅启用状态下,更新业务配置并重启线程
|
||||
synchronized (mServiceLock) {
|
||||
if (mServiceControlBean.isEnableService()) {
|
||||
AppConfigBean newConfig = (AppConfigBean) intent.getSerializableExtra(EXTRA_APP_CONFIG_BEAN);
|
||||
if (newConfig != null) {
|
||||
mCurrentConfigBean = newConfig;
|
||||
LogUtils.d(TAG, "handleExternalCommand: 收到线程重启指令,已更新业务配置");
|
||||
LogUtils.d(TAG, "handleExternalCommand: 收到配置更新,重启线程");
|
||||
restartRemindThreadSafely();
|
||||
} else {
|
||||
LogUtils.e(TAG, "handleExternalCommand: 新业务配置为空,重启线程失败");
|
||||
LogUtils.e(TAG, "handleExternalCommand: 配置为空,重启失败");
|
||||
}
|
||||
} else {
|
||||
LogUtils.w(TAG, "handleExternalCommand: 服务已禁用,忽略线程重启指令");
|
||||
LogUtils.w(TAG, "handleExternalCommand: 服务已禁用,忽略指令");
|
||||
}
|
||||
}
|
||||
}
|
||||
// else if (ACTION_SYNC_APP_FOREGROUND_STATE.equals(action)) {
|
||||
// boolean isForeground = intent.getBooleanExtra(EXTRA_APP_FOREGROUND_STATE, false);
|
||||
// synchronized (mServiceLock) {
|
||||
// mIsAppForeground = isForeground;
|
||||
// LogUtils.d(TAG, "handleExternalCommand: 收到前台状态同步指令,更新状态=" + isForeground);
|
||||
// // 同步状态到线程(实时生效)
|
||||
// syncAppForegroundStateToThread();
|
||||
// }
|
||||
// }
|
||||
LogUtils.d(TAG, "handleExternalCommand: 外部指令处理完成");
|
||||
}
|
||||
}
|
||||
|
||||
// ================================== 服务资源释放方法(顺序化释放,防内存泄漏)=================================
|
||||
// ================================== 资源释放方法(防止内存泄漏)=================================
|
||||
/**
|
||||
* 停止前台服务(取消通知+移除前台状态)
|
||||
* 停止前台服务
|
||||
*/
|
||||
private void stopForegroundService() {
|
||||
LogUtils.d(TAG, "stopForegroundService: 停止前台服务");
|
||||
// 取消前台通知
|
||||
if (mNotificationManager != null) {
|
||||
mNotificationManager.cancelForegroundServiceNotify();
|
||||
}
|
||||
// 移除前台服务状态
|
||||
try {
|
||||
stopForeground(STOP_FOREGROUND_REMOVE);
|
||||
LogUtils.d(TAG, "stopForegroundService: 前台服务状态移除成功");
|
||||
} catch (Exception e) {
|
||||
LogUtils.e(TAG, "stopForegroundService: 移除前台状态异常", e);
|
||||
LogUtils.e(TAG, "stopForegroundService: 停止前台状态异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 销毁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销毁完成");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放通知资源(调用工具类释放方法)
|
||||
* 释放通知资源
|
||||
*/
|
||||
private void releaseNotificationResource() {
|
||||
LogUtils.d(TAG, "releaseNotificationResource: 释放通知资源");
|
||||
if (mNotificationManager != null) {
|
||||
mNotificationManager.release();
|
||||
mNotificationManager = null;
|
||||
LogUtils.d(TAG, "releaseNotificationResource: 通知资源释放完成");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 置空所有引用,帮助GC回收
|
||||
* 置空所有引用
|
||||
*/
|
||||
private void clearAllReferences() {
|
||||
mForegroundNotifyMsg = null;
|
||||
@@ -569,142 +422,135 @@ public class ControlCenterService extends Service {
|
||||
LogUtils.d(TAG, "clearAllReferences: 所有引用已置空");
|
||||
}
|
||||
|
||||
// ================================== 静态工具方法(修复启停逻辑颠倒问题)=================================
|
||||
// ================================== 静态工具方法(对外提供服务入口)=================================
|
||||
/**
|
||||
* 启动服务(静态入口,从本地读取控制配置,显式绑定包名,适配API30+)
|
||||
* 【修复点4:统一使用startForegroundService,适配API26+】
|
||||
* 启动服务
|
||||
*/
|
||||
public static void startControlCenterService(Context context) {
|
||||
LogUtils.d(TAG, "startControlCenterService: 启动服务入口");
|
||||
LogUtils.d(TAG, "startControlCenterService: 启动服务");
|
||||
if (context == null) {
|
||||
LogUtils.e(TAG, "startControlCenterService: Context为空,启动失败");
|
||||
LogUtils.e(TAG, "startControlCenterService: Context为空");
|
||||
return;
|
||||
}
|
||||
Intent intent = new Intent(context, ControlCenterService.class);
|
||||
// 修复:API26+必须调用startForegroundService,避免系统异常
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
context.startForegroundService(intent);
|
||||
} else {
|
||||
context.startService(intent);
|
||||
}
|
||||
LogUtils.d(TAG, "startControlCenterService: 服务启动指令发送成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止服务(静态入口,显式绑定包名)
|
||||
* 停止服务
|
||||
*/
|
||||
public static void stopControlCenterService(Context context) {
|
||||
LogUtils.d(TAG, "stopControlCenterService: 停止服务入口");
|
||||
LogUtils.d(TAG, "stopControlCenterService: 停止服务");
|
||||
if (context == null) {
|
||||
LogUtils.e(TAG, "stopControlCenterService: Context为空,停止失败");
|
||||
LogUtils.e(TAG, "stopControlCenterService: Context为空");
|
||||
return;
|
||||
}
|
||||
Intent intent = new Intent(context, ControlCenterService.class);
|
||||
context.stopService(intent);
|
||||
LogUtils.d(TAG, "stopControlCenterService: 服务停止指令发送成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增:更新服务控制配置(本地持久化,动态切换服务启用/禁用状态)
|
||||
* 【修复点5:修复启停逻辑颠倒问题】
|
||||
* 更新服务控制配置并启停服务
|
||||
*/
|
||||
public static void updateServiceControlConfig(Context context, ControlCenterServiceBean controlBean) {
|
||||
LogUtils.d(TAG, "updateServiceControlConfig: 更新服务控制配置,新状态=" + controlBean.isEnableService());
|
||||
LogUtils.d(TAG, "updateServiceControlConfig: 更新控制配置,启用状态=" + controlBean.isEnableService());
|
||||
if (context == null || controlBean == null) {
|
||||
LogUtils.e(TAG, "updateServiceControlConfig: Context/控制配置为空,更新失败");
|
||||
LogUtils.e(TAG, "updateServiceControlConfig: 参数为空");
|
||||
return;
|
||||
}
|
||||
|
||||
// 第一步:本地持久化配置
|
||||
ControlCenterServiceBean.saveBean(context, controlBean);
|
||||
LogUtils.d(TAG, "updateServiceControlConfig: 控制配置已持久化");
|
||||
|
||||
// 第二步:启停服务(修复:启用则启动,禁用则停止)
|
||||
if (controlBean.isEnableService()) {
|
||||
stopControlCenterService(context);
|
||||
stopControlCenterService(context);
|
||||
startControlCenterService(context);
|
||||
LogUtils.d(TAG, "updateServiceControlConfig: 服务已设置启动");
|
||||
} else {
|
||||
stopControlCenterService(context);
|
||||
LogUtils.d(TAG, "updateServiceControlConfig: 服务已设置停止");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增:同步应用前台/后台状态到服务(MainActivity专用入口)
|
||||
* @param context 上下文
|
||||
* @param isForeground true=前台,false=后台
|
||||
* 更新业务配置并触发线程重启
|
||||
*/
|
||||
// public static void syncAppForegroundState(Context context, boolean isForeground) {
|
||||
// LogUtils.d(TAG, "syncAppForegroundState: 发送前台状态同步指令,状态=" + isForeground);
|
||||
// if (context == null) {
|
||||
// LogUtils.e(TAG, "syncAppForegroundState: Context为空,同步失败");
|
||||
// return;
|
||||
// }
|
||||
// if (!isServiceRunning(context, ControlCenterService.class)) {
|
||||
// LogUtils.w(TAG, "syncAppForegroundState: 服务未运行,跳过同步");
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// Intent intent = new Intent(context, ControlCenterService.class);
|
||||
// intent.setAction(ACTION_SYNC_APP_FOREGROUND_STATE);
|
||||
// intent.putExtra(EXTRA_APP_FOREGROUND_STATE, isForeground);
|
||||
// intent.setPackage(context.getPackageName());
|
||||
// intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
|
||||
//
|
||||
// try {
|
||||
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
// context.startForegroundService(intent);
|
||||
// } else {
|
||||
// context.startService(intent);
|
||||
// }
|
||||
// LogUtils.d(TAG, "syncAppForegroundState: 前台状态同步指令发送成功");
|
||||
// } catch (Exception e) {
|
||||
// LogUtils.e(TAG, "syncAppForegroundState: 发送同步指令异常", e);
|
||||
// }
|
||||
// }
|
||||
public static void updateStatus(Context context, AppConfigBean configBean) {
|
||||
LogUtils.d(TAG, "updateStatus: 发送配置更新指令");
|
||||
if (context == null || configBean == null) {
|
||||
LogUtils.e(TAG, "updateStatus: 参数为空");
|
||||
return;
|
||||
}
|
||||
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) {
|
||||
context.startForegroundService(intent);
|
||||
} else {
|
||||
context.startService(intent);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LogUtils.e(TAG, "updateStatus: 发送指令异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断服务是否运行(适配API30+ ActivityManager限制,优化判断逻辑)
|
||||
* 检查并引导用户开启忽略电池优化
|
||||
*/
|
||||
public static void checkIgnoreBatteryOptimization(Context context) {
|
||||
LogUtils.d(TAG, "checkIgnoreBatteryOptimization: 检查电池优化状态");
|
||||
if (context == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
||||
return;
|
||||
}
|
||||
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
||||
if (powerManager == null) {
|
||||
LogUtils.e(TAG, "checkIgnoreBatteryOptimization: PowerManager获取失败");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
boolean isIgnored = powerManager.isIgnoringBatteryOptimizations(context.getPackageName());
|
||||
if (!isIgnored) {
|
||||
Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
|
||||
intent.setData(Uri.parse("package:" + context.getPackageName()));
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
context.startActivity(intent);
|
||||
LogUtils.d(TAG, "checkIgnoreBatteryOptimization: 引导用户开启忽略电池优化");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LogUtils.e(TAG, "checkIgnoreBatteryOptimization: 引导异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断服务是否运行(适配API30+)
|
||||
*/
|
||||
private static boolean isServiceRunning(Context context, Class<?> serviceClass) {
|
||||
if (context == null || serviceClass == null) {
|
||||
LogUtils.w(TAG, "isServiceRunning: Context/服务类为空,返回false");
|
||||
return false;
|
||||
}
|
||||
|
||||
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
if (am == null) {
|
||||
LogUtils.e(TAG, "isServiceRunning: ActivityManager获取失败,返回false");
|
||||
LogUtils.e(TAG, "isServiceRunning: ActivityManager获取失败");
|
||||
return false;
|
||||
}
|
||||
|
||||
// API30+ 兼容:getRunningServices失效,通过进程状态判断(优化兜底逻辑)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
try {
|
||||
String packageName = context.getPackageName();
|
||||
List<ActivityManager.RunningAppProcessInfo> processes = am.getRunningAppProcesses();
|
||||
if (processes != null && !processes.isEmpty()) {
|
||||
for (ActivityManager.RunningAppProcessInfo process : processes) {
|
||||
if (packageName.equals(process.processName)) {
|
||||
// 前台服务/前台进程均视为服务运行(适配部分机型保活机制)
|
||||
if (process.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE
|
||||
|| process.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
String packageName = context.getPackageName();
|
||||
List<ActivityManager.RunningAppProcessInfo> processes = am.getRunningAppProcesses();
|
||||
if (processes != null) {
|
||||
for (ActivityManager.RunningAppProcessInfo process : processes) {
|
||||
if (packageName.equals(process.processName) &&
|
||||
(process.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE ||
|
||||
process.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// 兜底:检查服务是否已启动(避免进程后台时误判)
|
||||
return isServiceStarted(context, serviceClass);
|
||||
} catch (Exception e) {
|
||||
LogUtils.e(TAG, "isServiceRunning: API30+ 判断服务状态异常", e);
|
||||
return false;
|
||||
}
|
||||
return isServiceStarted(context, serviceClass);
|
||||
} else {
|
||||
// API30-:通过RunningServiceInfo判断
|
||||
List<ActivityManager.RunningServiceInfo> runningServices = am.getRunningServices(100);
|
||||
if (runningServices != null && !runningServices.isEmpty()) {
|
||||
if (runningServices != null) {
|
||||
String serviceClassName = serviceClass.getName();
|
||||
for (ActivityManager.RunningServiceInfo info : runningServices) {
|
||||
if (serviceClassName.equals(info.service.getClassName())) {
|
||||
@@ -717,87 +563,19 @@ public class ControlCenterService extends Service {
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增:辅助判断服务是否已启动(API30+ 兜底,避免进程后台误判)
|
||||
* 兜底判断服务是否已启动
|
||||
*/
|
||||
private static boolean isServiceStarted(Context context, Class<?> serviceClass) {
|
||||
try {
|
||||
// 通过ServiceControlBean状态兜底(服务启动时会初始化配置)
|
||||
ControlCenterServiceBean controlBean = ControlCenterServiceBean.loadBean(context, ControlCenterServiceBean.class);
|
||||
return controlBean != null && controlBean.isEnableService();
|
||||
} catch (Exception e) {
|
||||
LogUtils.e(TAG, "isServiceStarted: 兜底判断服务状态异常", e);
|
||||
LogUtils.e(TAG, "isServiceStarted: 兜底判断异常", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 引导用户开启忽略电池优化(避免服务被后台杀死,适配API23+,优化机型兼容)
|
||||
*/
|
||||
public static void checkIgnoreBatteryOptimization(Context context) {
|
||||
LogUtils.d(TAG, "checkIgnoreBatteryOptimization: 检查电池优化状态");
|
||||
if (context == null) {
|
||||
LogUtils.e(TAG, "checkIgnoreBatteryOptimization: Context为空,跳过检查");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
||||
if (powerManager == null) {
|
||||
LogUtils.e(TAG, "checkIgnoreBatteryOptimization: PowerManager获取失败,跳过检查");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
boolean isIgnored = powerManager.isIgnoringBatteryOptimizations(context.getPackageName());
|
||||
if (!isIgnored) {
|
||||
Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
|
||||
intent.setData(Uri.parse("package:" + context.getPackageName()));
|
||||
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 (SecurityException e) {
|
||||
LogUtils.e(TAG, "checkIgnoreBatteryOptimization: 机型限制,无法引导电池优化(系统权限管控)", e);
|
||||
} catch (Exception e) {
|
||||
LogUtils.e(TAG, "checkIgnoreBatteryOptimization: 引导优化异常(部分机型限制)", e);
|
||||
}
|
||||
} else {
|
||||
LogUtils.d(TAG, "checkIgnoreBatteryOptimization: API<23,无需检查电池优化");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新服务配置(对外静态入口,触发线程重启,控制配置从本地读取)
|
||||
*/
|
||||
public static void updateStatus(Context context, AppConfigBean configBean) {
|
||||
LogUtils.d(TAG, "updateStatus: 发送业务配置更新指令");
|
||||
if (context == null || configBean == null) {
|
||||
LogUtils.e(TAG, "updateStatus: Context/业务配置为空,发送失败");
|
||||
return;
|
||||
}
|
||||
|
||||
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) {
|
||||
context.startForegroundService(intent);
|
||||
} else {
|
||||
context.startService(intent);
|
||||
}
|
||||
LogUtils.d(TAG, "updateStatus: 业务配置更新指令发送成功");
|
||||
} catch (Exception e) {
|
||||
LogUtils.e(TAG, "updateStatus: 发送指令异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
// ================================== Getter/Setter 方法(新增前台状态相关,线程安全)=================================
|
||||
// ================================== Getter/Setter 方法(线程安全)=================================
|
||||
public RemindThread getRemindThread() {
|
||||
synchronized (mServiceLock) {
|
||||
return mRemindThread;
|
||||
@@ -805,29 +583,24 @@ public class ControlCenterService extends Service {
|
||||
}
|
||||
|
||||
public void setCurrentConfigBean(AppConfigBean configBean) {
|
||||
LogUtils.d(TAG, "setCurrentConfigBean: 更新服务配置");
|
||||
if (configBean != null) {
|
||||
synchronized (mServiceLock) {
|
||||
this.mCurrentConfigBean = configBean;
|
||||
syncConfigToRemindThread();
|
||||
}
|
||||
LogUtils.d(TAG, "setCurrentConfigBean: 配置更新成功");
|
||||
} else {
|
||||
LogUtils.e(TAG, "setCurrentConfigBean: 配置为空,更新失败");
|
||||
LogUtils.d(TAG, "setCurrentConfigBean: 更新业务配置");
|
||||
if (configBean == null) {
|
||||
LogUtils.e(TAG, "setCurrentConfigBean: 配置为空");
|
||||
return;
|
||||
}
|
||||
synchronized (mServiceLock) {
|
||||
this.mCurrentConfigBean = configBean;
|
||||
syncConfigToRemindThread();
|
||||
}
|
||||
}
|
||||
|
||||
// 更新服务控制配置(内存+本地持久化同步)
|
||||
public void setServiceControlBean(ControlCenterServiceBean controlBean) {
|
||||
LogUtils.d(TAG, "setServiceControlBean: 更新服务控制配置");
|
||||
LogUtils.d(TAG, "setServiceControlBean: 更新控制配置");
|
||||
if (controlBean != null) {
|
||||
updateAndSaveServiceControlConfig(controlBean);
|
||||
} else {
|
||||
LogUtils.e(TAG, "setServiceControlBean: 控制配置为空,更新失败");
|
||||
}
|
||||
}
|
||||
|
||||
// 获取服务控制配置(外部查询启用状态)
|
||||
public ControlCenterServiceBean getServiceControlBean() {
|
||||
synchronized (mServiceLock) {
|
||||
return mServiceControlBean;
|
||||
@@ -857,21 +630,5 @@ public class ControlCenterService extends Service {
|
||||
return mIsDestroyed;
|
||||
}
|
||||
}
|
||||
|
||||
// 新增:获取应用前台状态(外部查询,线程安全)
|
||||
public boolean isAppForeground() {
|
||||
synchronized (mServiceLock) {
|
||||
return mIsAppForeground;
|
||||
}
|
||||
}
|
||||
|
||||
// 新增:设置应用前台状态(内部/外部调用,同步到线程)
|
||||
// public void setAppForeground(boolean isForeground) {
|
||||
// LogUtils.d(TAG, "setAppForeground: 更新应用前台状态=" + isForeground);
|
||||
// synchronized (mServiceLock) {
|
||||
// mIsAppForeground = isForeground;
|
||||
// syncAppForegroundStateToThread();
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user