From b0dee5e98e2699d8b5a66a10970d2210240ba304 Mon Sep 17 00:00:00 2001 From: ZhanGSKen Date: Thu, 18 Dec 2025 21:15:24 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E7=BA=BF=E7=A8=8B=E8=B0=83?= =?UTF-8?q?=E8=AF=95=E4=B8=AD=EF=BC=8C=E7=9B=AE=E6=A0=87=E5=B0=B1=E6=98=AF?= =?UTF-8?q?=E7=BA=BF=E7=A8=8B=E6=94=BE=E5=85=A5=E6=9C=8D=E5=8A=A1=E7=B1=BB?= =?UTF-8?q?=E4=BD=BF=E7=94=A8handler=E4=B8=8E=E6=9C=8D=E5=8A=A1=E9=80=9A?= =?UTF-8?q?=E4=BF=A1=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- powerbell/build.properties | 4 +- .../studio/powerbell/MainActivity.java | 350 ++++----- .../ControlCenterServiceReceiver.java | 22 +- .../services/ControlCenterService.java | 576 +++++++-------- .../powerbell/threads/RemindThread.java | 695 ++++++++---------- 5 files changed, 730 insertions(+), 917 deletions(-) diff --git a/powerbell/build.properties b/powerbell/build.properties index 5371d5a..7f20198 100644 --- a/powerbell/build.properties +++ b/powerbell/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Thu Dec 18 09:51:07 GMT 2025 +#Thu Dec 18 12:48:12 GMT 2025 stageCount=10 libraryProject= baseVersion=15.14 publishVersion=15.14.9 -buildCount=35 +buildCount=42 baseBetaVersion=15.14.10 diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java index 9558f59..036bf4c 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java @@ -45,43 +45,42 @@ import cc.winboll.studio.powerbell.views.MainContentView; * @Date 2025/12/17 13:14 * @Describe 主活动类:应用核心页面,管理电池监控、背景设置、服务控制等核心功能 * 适配:Java7 | API30 | 小米手机,优化性能与稳定性,杜绝内存泄漏 - * 核心规则:UI开关仅管理本地配置,服务启停仅在应用启动时根据配置执行 + * 核心规则:UI开关直接联动服务启停,本地配置与服务状态实时同步 */ public class MainActivity extends WinBoLLActivity implements MainContentView.OnViewActionListener { // ======================== 静态常量(置顶统一,抽离魔法值,便于维护)======================== public static final String TAG = "MainActivity"; // 请求码 - private static final int REQUEST_READ_MEDIA_IMAGES = 1001; // 背景设置请求码 + private static final int REQUEST_READ_MEDIA_IMAGES = 1001; // 延迟时间 - private static final int DELAY_LOAD_NON_CRITICAL = 500; // 非核心视图延迟加载(ms) + private static final long DELAY_LOAD_NON_CRITICAL = 500L; // Handler消息标识(按业务优先级排序) - public static final int MSG_RELOAD_APPCONFIG = 0; // 重新加载配置 - public static final int MSG_CURRENTVALUEBATTERY = 1; // 更新当前电量 - public static final int MSG_LOAD_BACKGROUND = 2; // 加载背景 - private static final int MSG_RESTART_REMIND_THREAD = 3; // 重启RemindThread线程 - private static final int MSG_UPDATE_SERVICE_SWITCH = 4; // 更新服务开关UI + public static final int MSG_RELOAD_APPCONFIG = 0; + public static final int MSG_CURRENTVALUEBATTERY = 1; + public static final int MSG_LOAD_BACKGROUND = 2; + private static final int MSG_START_REMIND_THREAD = 3; + private static final int MSG_UPDATE_SERVICE_SWITCH = 4; // ======================== 静态成员(全局共享,严格管控生命周期)======================== - private static MainActivity sMainActivity; // 全局Activity实例(销毁时必须置空) - private static Handler sGlobalHandler; // 全局Handler(统一消息分发) + private static MainActivity sMainActivity; + private static Handler sGlobalHandler; - // ======================== 成员属性(按「依赖→核心→辅助」分类,优先级递减)======================== - // 工具类实例(单例,避免重复初始化) + // ======================== 工具类实例(单例,避免重复初始化)======================== private PermissionUtils mPermissionUtils; private AppConfigUtils mAppConfigUtils; private BackgroundSourceUtils mBgSourceUtils; - // 应用核心实例 + + // ======================== 应用核心实例 ========================= private App mApplication; - private MainContentView mMainContentView; // 核心视图封装类 - // 基础视图组件 + private MainContentView mMainContentView; + private ControlCenterServiceBean mServiceControlBean; + + // ======================== 基础视图组件 ========================= private Toolbar mToolbar; private ViewStub mAdsViewStub; - private ADsBannerView mADsBannerView; // 广告视图(非核心,延迟加载) - // 资源与菜单 + private ADsBannerView mADsBannerView; + private Drawable mFrameDrawable; private Menu mMenu; - private Drawable mFrameDrawable; // 框架背景资源 - // 服务控制核心Bean - private ControlCenterServiceBean mServiceControlBean; // ======================== 生命周期方法(按系统调用顺序排列,逻辑闭环)======================== @Override @@ -96,83 +95,79 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV @Override protected void onCreate(Bundle savedInstanceState) { - LogUtils.d(TAG, "onCreate: 进入"); + LogUtils.d(TAG, "onCreate: start"); super.onCreate(savedInstanceState); - // 1. 初始化全局Handler(优先初始化,避免消息丢失) + // 优先初始化全局Handler,避免消息丢失 initGlobalHandler(); - // 2. 加载布局+初始化核心流程 + // 布局与核心流程初始化 setContentView(R.layout.activity_main); initPermissionUtils(); initMainContentView(); initCriticalView(); initCoreUtilsAsync(); loadNonCriticalViewDelayed(); - LogUtils.d(TAG, "onCreate: 退出"); + LogUtils.d(TAG, "onCreate: end"); } @Override protected void onPostCreate(Bundle savedInstanceState) { - LogUtils.d(TAG, "onPostCreate: 进入"); + LogUtils.d(TAG, "onPostCreate: start"); super.onPostCreate(savedInstanceState); mPermissionUtils.startPermissionRequest(this); - LogUtils.d(TAG, "onPostCreate: 退出"); + LogUtils.d(TAG, "onPostCreate: end"); } @Override protected void onResume() { - LogUtils.d(TAG, "onResume: 进入"); + LogUtils.d(TAG, "onResume: start"); super.onResume(); - // 恢复背景+同步服务开关UI(仅本地配置) + // 恢复背景与服务开关UI if (sGlobalHandler != null) { sGlobalHandler.sendEmptyMessage(MSG_LOAD_BACKGROUND); sGlobalHandler.sendEmptyMessage(MSG_UPDATE_SERVICE_SWITCH); - LogUtils.d(TAG, "onResume: 发送背景加载+服务开关更新消息"); + LogUtils.d(TAG, "onResume: send MSG_LOAD_BACKGROUND & MSG_UPDATE_SERVICE_SWITCH"); } // 恢复广告 if (mADsBannerView != null) { mADsBannerView.resumeADs(this); } -// // 设置RemindThread前台状态 -// setRemindThreadForeground(true); - LogUtils.d(TAG, "onResume: 退出"); + LogUtils.d(TAG, "onResume: end"); } @Override protected void onPause() { - LogUtils.d(TAG, "onPause: 进入"); + LogUtils.d(TAG, "onPause: start"); super.onPause(); -// // 设置RemindThread后台状态 -// setRemindThreadForeground(false); - LogUtils.d(TAG, "onPause: 退出"); + LogUtils.d(TAG, "onPause: end"); } @Override protected void onDestroy() { - LogUtils.d(TAG, "onDestroy: 进入"); + LogUtils.d(TAG, "onDestroy: start"); super.onDestroy(); - // 1. 释放广告资源 + // 释放广告资源 if (mADsBannerView != null) { mADsBannerView.releaseAdResources(); mADsBannerView = null; } - // 2. 释放核心视图资源 + // 释放核心视图 if (mMainContentView != null) { mMainContentView.releaseResources(); mMainContentView = null; } - // 3. 销毁线程+清理Handler - RemindThread.destroyInstance(); + // 销毁线程与Handler + RemindThread.stopRemindThread(); if (sGlobalHandler != null) { sGlobalHandler.removeCallbacksAndMessages(null); sGlobalHandler = null; } - // 4. 释放Drawable+置空全局实例 + // 释放Drawable,防止内存泄漏 if (mFrameDrawable != null) { mFrameDrawable.setCallback(null); mFrameDrawable = null; } + // 置空所有引用 sMainActivity = null; - // 5. 置空所有辅助实例 mPermissionUtils = null; mAppConfigUtils = null; mBgSourceUtils = null; @@ -181,27 +176,24 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV mApplication = null; mToolbar = null; mAdsViewStub = null; - LogUtils.d(TAG, "onDestroy: 退出"); + LogUtils.d(TAG, "onDestroy: end"); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - LogUtils.d(TAG, "onActivityResult: 进入,requestCode=" + requestCode + ",resultCode=" + resultCode); + LogUtils.d(TAG, "onActivityResult: requestCode=" + requestCode + ", resultCode=" + resultCode); super.onActivityResult(requestCode, resultCode, data); mPermissionUtils.handlePermissionRequest(this, requestCode, resultCode, data); - // 背景设置完成后重新加载背景 - if (requestCode == REQUEST_READ_MEDIA_IMAGES) { - if (sGlobalHandler != null) { - sGlobalHandler.sendEmptyMessage(MSG_LOAD_BACKGROUND); - } + // 背景设置完成后重新加载 + if (requestCode == REQUEST_READ_MEDIA_IMAGES && sGlobalHandler != null) { + sGlobalHandler.sendEmptyMessage(MSG_LOAD_BACKGROUND); } - LogUtils.d(TAG, "onActivityResult: 退出"); } // ======================== 菜单与导航方法 ======================== @Override public boolean onCreateOptionsMenu(Menu menu) { - LogUtils.d(TAG, "onCreateOptionsMenu: 进入"); + LogUtils.d(TAG, "onCreateOptionsMenu: start"); mMenu = menu; AESThemeUtil.inflateMenu(this, menu); if (App.isDebugging()) { @@ -209,13 +201,13 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV getMenuInflater().inflate(R.menu.toolbar_unittest, mMenu); } getMenuInflater().inflate(R.menu.toolbar_main, mMenu); - LogUtils.d(TAG, "onCreateOptionsMenu: 退出"); + LogUtils.d(TAG, "onCreateOptionsMenu: end"); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { - LogUtils.d(TAG, "onOptionsItemSelected: 进入,itemId=" + item.getItemId()); + LogUtils.d(TAG, "onOptionsItemSelected: itemId=" + item.getItemId()); if (AESThemeUtil.onAppThemeItemSelected(this, item)) { recreate(); return true; @@ -245,7 +237,6 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV default: return super.onOptionsItemSelected(item); } - LogUtils.d(TAG, "onOptionsItemSelected: 退出"); return true; } @@ -260,7 +251,7 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV @Override public void onBackPressed() { moveTaskToBack(true); - LogUtils.d(TAG, "onBackPressed: 应用退到后台"); + LogUtils.d(TAG, "onBackPressed: app move to background"); } @Override @@ -270,26 +261,23 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV // ======================== 核心初始化方法 ======================== private void initPermissionUtils() { - LogUtils.d(TAG, "initPermissionUtils: 进入"); + LogUtils.d(TAG, "initPermissionUtils: start"); mPermissionUtils = PermissionUtils.getInstance(); - LogUtils.d(TAG, "initPermissionUtils: 退出"); + LogUtils.d(TAG, "initPermissionUtils: end"); } - /** - * 初始化全局Handler(核心优化:弱引用+生命周期校验,杜绝内存泄漏) - */ private void initGlobalHandler() { - LogUtils.d(TAG, "initGlobalHandler: 进入"); + LogUtils.d(TAG, "initGlobalHandler: start"); if (sGlobalHandler == null) { sGlobalHandler = new Handler() { @Override public void handleMessage(Message msg) { - // 严格校验Activity状态,避免销毁后操作UI + // 校验Activity状态,避免销毁后操作UI if (sMainActivity == null || sMainActivity.isFinishing() || sMainActivity.isDestroyed()) { - LogUtils.w(TAG, "handleMessage: Activity已销毁,跳过消息处理"); + LogUtils.w(TAG, "handleMessage: Activity destroyed, skip msg what=" + msg.what); return; } - LogUtils.d(TAG, "handleMessage: 接收消息,what=" + msg.what); + LogUtils.d(TAG, "handleMessage: receive msg what=" + msg.what); switch (msg.what) { case MSG_RELOAD_APPCONFIG: sMainActivity.updateViewData(); @@ -303,32 +291,30 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV sMainActivity.reloadBackground(); sMainActivity.setMainLayoutBackgroundColor(); break; - case MSG_RESTART_REMIND_THREAD: + case MSG_START_REMIND_THREAD: AppConfigBean configBean = (AppConfigBean) msg.obj; - sMainActivity.restartRemindThread(configBean); + LogUtils.d(TAG, "MSG_START_REMIND_THREAD not yet."); break; case MSG_UPDATE_SERVICE_SWITCH: sMainActivity.updateServiceSwitchUI(); break; } - super.handleMessage(msg); } }; - LogUtils.d(TAG, "initGlobalHandler: 全局Handler初始化完成"); + LogUtils.d(TAG, "initGlobalHandler: handler created"); } - LogUtils.d(TAG, "initGlobalHandler: 退出"); + LogUtils.d(TAG, "initGlobalHandler: end"); } private void initMainContentView() { - LogUtils.d(TAG, "initMainContentView: 进入"); + LogUtils.d(TAG, "initMainContentView: start"); View rootView = findViewById(android.R.id.content); mMainContentView = new MainContentView(this, rootView, this); - LogUtils.d(TAG, "initMainContentView: 核心视图封装类初始化完成"); - LogUtils.d(TAG, "initMainContentView: 退出"); + LogUtils.d(TAG, "initMainContentView: MainContentView created"); } private void initCriticalView() { - LogUtils.d(TAG, "initCriticalView: 进入"); + LogUtils.d(TAG, "initCriticalView: start"); sMainActivity = this; mToolbar = findViewById(R.id.toolbar); setSupportActionBar(mToolbar); @@ -336,81 +322,75 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV mToolbar.setTitleTextAppearance(this, R.style.Toolbar_TitleText); } mAdsViewStub = findViewById(R.id.stub_ads_banner); - LogUtils.d(TAG, "initCriticalView: 退出"); + LogUtils.d(TAG, "initCriticalView: end"); } - /** - * 异步初始化核心工具类(保留服务启停逻辑:应用启动时根据配置执行) - */ private void initCoreUtilsAsync() { - LogUtils.d(TAG, "initCoreUtilsAsync: 进入"); + LogUtils.d(TAG, "initCoreUtilsAsync: start"); new Thread(new Runnable() { @Override public void run() { - LogUtils.d(TAG, "initCoreUtilsAsync: 异步线程启动"); + LogUtils.d(TAG, "initCoreUtilsAsync: async thread start"); mApplication = (App) getApplication(); mAppConfigUtils = AppConfigUtils.getInstance(getApplicationContext()); mBgSourceUtils = BackgroundSourceUtils.getInstance(getActivity()); - // 初始化服务控制Bean(优先读取本地配置,无则创建默认) + // 初始化服务控制配置 mServiceControlBean = ControlCenterServiceBean.loadBean(getApplicationContext(), ControlCenterServiceBean.class); if (mServiceControlBean == null) { mServiceControlBean = new ControlCenterServiceBean(false); ControlCenterServiceBean.saveBean(getApplicationContext(), mServiceControlBean); - LogUtils.d(TAG, "initCoreUtilsAsync: 创建默认服务控制配置(禁用)"); + LogUtils.d(TAG, "initCoreUtilsAsync: create default service config (disabled)"); } - // 应用启动时:根据本地配置执行服务启停(仅执行一次) - if (mServiceControlBean.isEnableService()) { - if (!ServiceUtils.isServiceAlive(getApplicationContext(), ControlCenterService.class.getName())) { - runOnUiThread(new Runnable() { - @Override - public void run() { - ControlCenterService.startControlCenterService(getApplicationContext()); - LogUtils.d(TAG, "initCoreUtilsAsync: 应用启动,根据配置启动服务"); - } - }); - } - } else { - if (ServiceUtils.isServiceAlive(getApplicationContext(), ControlCenterService.class.getName())) { - runOnUiThread(new Runnable() { - @Override - public void run() { - ControlCenterService.stopControlCenterService(getApplicationContext()); - LogUtils.d(TAG, "initCoreUtilsAsync: 应用启动,根据配置停止服务"); - } - }); - } + // 根据配置启停服务 + final boolean isServiceEnable = mServiceControlBean.isEnableService(); + final boolean isServiceAlive = ServiceUtils.isServiceAlive(getApplicationContext(), ControlCenterService.class.getName()); + if (isServiceEnable && !isServiceAlive) { + runOnUiThread(new Runnable() { + @Override + public void run() { + ControlCenterService.startControlCenterService(getApplicationContext()); + LogUtils.d(TAG, "initCoreUtilsAsync: start service by config"); + } + }); + } else if (!isServiceEnable && isServiceAlive) { + runOnUiThread(new Runnable() { + @Override + public void run() { + ControlCenterService.stopControlCenterService(getApplicationContext()); + LogUtils.d(TAG, "initCoreUtilsAsync: stop service by config"); + } + }); } - // 切换主线程更新UI + // 主线程更新UI runOnUiThread(new Runnable() { @Override public void run() { if (isFinishing() || isDestroyed()) { - LogUtils.w(TAG, "initCoreUtilsAsync: Activity已销毁,跳过UI更新"); + LogUtils.w(TAG, "initCoreUtilsAsync: Activity destroyed, skip UI update"); return; } - // 适配API30+主题加载Drawable + // 加载框架背景 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { mFrameDrawable = getResources().getDrawable(R.drawable.bg_frame, getTheme()); } else { mFrameDrawable = getResources().getDrawable(R.drawable.bg_frame); } - // 执行核心业务 updateViewData(); sGlobalHandler.sendEmptyMessage(MSG_LOAD_BACKGROUND); sGlobalHandler.sendEmptyMessage(MSG_UPDATE_SERVICE_SWITCH); } }); - LogUtils.d(TAG, "initCoreUtilsAsync: 异步线程结束"); + LogUtils.d(TAG, "initCoreUtilsAsync: async thread end"); } }).start(); - LogUtils.d(TAG, "initCoreUtilsAsync: 退出"); + LogUtils.d(TAG, "initCoreUtilsAsync: end"); } private void loadNonCriticalViewDelayed() { - LogUtils.d(TAG, "loadNonCriticalViewDelayed: 进入"); + LogUtils.d(TAG, "loadNonCriticalViewDelayed: start"); new Handler().postDelayed(new Runnable() { @Override public void run() { @@ -420,38 +400,38 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV loadAdsView(); } }, DELAY_LOAD_NON_CRITICAL); - LogUtils.d(TAG, "loadNonCriticalViewDelayed: 退出"); + LogUtils.d(TAG, "loadNonCriticalViewDelayed: end"); } // ======================== 视图操作方法 ======================== private void loadAdsView() { - LogUtils.d(TAG, "loadAdsView: 进入"); + LogUtils.d(TAG, "loadAdsView: start"); if (mAdsViewStub == null) { - LogUtils.e(TAG, "loadAdsView: 广告ViewStub为空"); + LogUtils.e(TAG, "loadAdsView: AdsViewStub is null"); return; } if (mADsBannerView == null) { View adsView = mAdsViewStub.inflate(); mADsBannerView = adsView.findViewById(R.id.adsbanner); + LogUtils.d(TAG, "loadAdsView: ADsBannerView created"); } - LogUtils.d(TAG, "loadAdsView: 退出"); + LogUtils.d(TAG, "loadAdsView: end"); } private void updateViewData() { - LogUtils.d(TAG, "updateViewData: 进入"); + LogUtils.d(TAG, "updateViewData: start"); if (mMainContentView == null || mFrameDrawable == null) { - LogUtils.e(TAG, "updateViewData: 核心视图/框架资源为空"); + LogUtils.e(TAG, "updateViewData: MainContentView or FrameDrawable is null"); return; } mMainContentView.updateViewData(mFrameDrawable); - LogUtils.d(TAG, "updateViewData: 视图数据更新完成"); - LogUtils.d(TAG, "updateViewData: 退出"); + LogUtils.d(TAG, "updateViewData: view data updated"); } private void reloadBackground() { - LogUtils.d(TAG, "reloadBackground: 进入"); + LogUtils.d(TAG, "reloadBackground: start"); if (mMainContentView == null || mBgSourceUtils == null) { - LogUtils.e(TAG, "reloadBackground: 核心视图/背景工具类为空"); + LogUtils.e(TAG, "reloadBackground: MainContentView or BackgroundSourceUtils is null"); return; } BackgroundBean currentBgBean = mBgSourceUtils.getCurrentBackgroundBean(); @@ -460,133 +440,114 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV } else { mMainContentView.backgroundView.setBackgroundResource(R.drawable.default_background); } - LogUtils.d(TAG, "reloadBackground: 退出"); + LogUtils.d(TAG, "reloadBackground: end"); } private void setMainLayoutBackgroundColor() { - LogUtils.d(TAG, "setMainLayoutBackgroundColor: 进入"); + LogUtils.d(TAG, "setMainLayoutBackgroundColor: start"); if (isFinishing() || isDestroyed() || mMainContentView == null || mBgSourceUtils == null) { - LogUtils.e(TAG, "setMainLayoutBackgroundColor: 环境无效"); + LogUtils.e(TAG, "setMainLayoutBackgroundColor: invalid context"); return; } BackgroundBean currentBgBean = mBgSourceUtils.getCurrentBackgroundBean(); if (currentBgBean != null) { mMainContentView.mainLayout.setBackgroundColor(currentBgBean.getPixelColor()); } - LogUtils.d(TAG, "setMainLayoutBackgroundColor: 退出"); + LogUtils.d(TAG, "setMainLayoutBackgroundColor: end"); } - /** - * 更新服务开关UI(仅同步本地配置,不校验服务状态) - */ private void updateServiceSwitchUI() { - LogUtils.d(TAG, "updateServiceSwitchUI: 进入"); + LogUtils.d(TAG, "updateServiceSwitchUI: start"); if (mMainContentView == null || mServiceControlBean == null) { - LogUtils.e(TAG, "updateServiceSwitchUI: 核心视图/服务控制Bean为空"); + LogUtils.e(TAG, "updateServiceSwitchUI: MainContentView or ServiceControlBean is null"); return; } - // 仅读取本地配置状态,不涉及服务状态校验 boolean configEnabled = mServiceControlBean.isEnableService(); - LogUtils.d(TAG, "updateServiceSwitchUI: 本地配置状态=" + configEnabled); - - // 仅更新UI开关状态 + LogUtils.d(TAG, "updateServiceSwitchUI: config enabled=" + configEnabled); mMainContentView.setServiceSwitchEnabled(false); mMainContentView.setServiceSwitchChecked(configEnabled); mMainContentView.setServiceSwitchEnabled(true); - LogUtils.d(TAG, "updateServiceSwitchUI: 退出"); + LogUtils.d(TAG, "updateServiceSwitchUI: end"); } // ======================== 服务与线程管理方法 ======================== - /** - * 重启提醒线程(仅由配置变更触发,不与UI开关联动) - */ - private void restartRemindThread(AppConfigBean configBean) { - LogUtils.d(TAG, "restartRemindThread: 进入"); - if (configBean == null || mServiceControlBean == null) { - LogUtils.e(TAG, "restartRemindThread: 配置/服务控制Bean为空"); - return; - } - if (!mServiceControlBean.isEnableService()) { - LogUtils.w(TAG, "restartRemindThread: 服务已禁用,跳过线程重启"); - return; - } - if (!ServiceUtils.isServiceAlive(getApplicationContext(), ControlCenterService.class.getName())) { - ControlCenterService.startControlCenterService(getApplicationContext()); - } - RemindThread.destroyInstance(); - ControlCenterService.updateStatus(getApplicationContext(), configBean); - LogUtils.d(TAG, "restartRemindThread: 退出"); - } - - /** - * 设置线程前后台状态(依赖服务运行状态) - */ -// private void setRemindThreadForeground(boolean isForeground) { -// LogUtils.d(TAG, "setRemindThreadForeground: 进入,前台状态=" + isForeground); -// if (!ServiceUtils.isServiceAlive(getApplicationContext(), ControlCenterService.class.getName())) { -// LogUtils.w(TAG, "setRemindThreadForeground: 服务未运行,跳过状态设置"); +// private void restartRemindThread(AppConfigBean configBean) { +// LogUtils.d(TAG, "restartRemindThread: start, configBean=" + configBean); +// if (configBean == null || mServiceControlBean == null) { +// LogUtils.e(TAG, "restartRemindThread: configBean or ServiceControlBean is null"); // return; // } -// try { -// RemindThread.getInstance(getApplicationContext(), null).setAppForeground(isForeground); -// } catch (IllegalArgumentException e) { -// LogUtils.w(TAG, "setRemindThreadForeground: 线程未初始化", e); +// if (!mServiceControlBean.isEnableService()) { +// LogUtils.w(TAG, "restartRemindThread: service is disabled, skip"); +// return; // } -// LogUtils.d(TAG, "setRemindThreadForeground: 退出"); +// if (!ServiceUtils.isServiceAlive(getApplicationContext(), ControlCenterService.class.getName())) { +// ControlCenterService.startControlCenterService(getApplicationContext()); +// } +// RemindThread.destroyInstance(); +// ControlCenterService.updateStatus(getApplicationContext(), configBean); +// LogUtils.d(TAG, "restartRemindThread: end"); // } - /** - * 切换服务启用状态(仅持久化本地配置,点击UI开关时不联动服务启停) - */ private void toggleServiceEnableState(boolean isEnable) { - LogUtils.d(TAG, "toggleServiceEnableState: 进入,目标状态=" + isEnable); + LogUtils.d(TAG, "toggleServiceEnableState: target state=" + isEnable); if (mServiceControlBean == null) { - LogUtils.e(TAG, "toggleServiceEnableState: 服务控制Bean为空"); + LogUtils.e(TAG, "toggleServiceEnableState: ServiceControlBean is null"); return; } - // 仅更新本地配置并持久化 mServiceControlBean.setIsEnableService(isEnable); ControlCenterServiceBean.saveBean(getApplicationContext(), mServiceControlBean); - LogUtils.d(TAG, "toggleServiceEnableState: 本地服务控制配置已持久化,状态=" + isEnable); - // 仅更新UI,无服务启停操作 + // ========== 核心新增逻辑:UI开关联动服务启停 + 线程销毁 ========== + if (isEnable) { + // 开启:启动服务 + if (!ServiceUtils.isServiceAlive(getApplicationContext(), ControlCenterService.class.getName())) { + ControlCenterService.startControlCenterService(getApplicationContext()); + LogUtils.d(TAG, "toggleServiceEnableState: start service success"); + } + } else { + // 关闭:停止服务 + 销毁线程 + ControlCenterService.stopControlCenterService(getApplicationContext()); + LogUtils.d(TAG, "toggleServiceEnableState: stop service + destroy thread success"); + } + sGlobalHandler.sendEmptyMessage(MSG_UPDATE_SERVICE_SWITCH); - LogUtils.d(TAG, "toggleServiceEnableState: 退出"); + LogUtils.d(TAG, "toggleServiceEnableState: config saved + service state synced"); } // ======================== 页面跳转方法 ======================== private void startAboutActivity() { - LogUtils.d(TAG, "startAboutActivity: 进入"); + LogUtils.d(TAG, "startAboutActivity: start"); Intent aboutIntent = new Intent(getApplicationContext(), AboutActivity.class); APPInfo appInfo = genDefaultAppInfo(); aboutIntent.putExtra(AboutActivity.EXTRA_APPINFO, appInfo); WinBoLLActivityManager.getInstance().startWinBoLLActivity(getApplicationContext(), aboutIntent, AboutActivity.class); - LogUtils.d(TAG, "startAboutActivity: 退出"); + LogUtils.d(TAG, "startAboutActivity: end"); } // ======================== 消息发送方法 ======================== private void sendRestartRemindThreadMessage() { - LogUtils.d(TAG, "sendRestartRemindThreadMessage: 进入"); + LogUtils.d(TAG, "sendRestartRemindThreadMessage: start"); if (sGlobalHandler == null || mAppConfigUtils == null || mAppConfigUtils.mAppConfigBean == null) { - LogUtils.e(TAG, "sendRestartRemindThreadMessage: 环境无效"); + LogUtils.e(TAG, "sendRestartRemindThreadMessage: invalid context"); return; } - Message msg = sGlobalHandler.obtainMessage(MSG_RESTART_REMIND_THREAD); + Message msg = sGlobalHandler.obtainMessage(MSG_START_REMIND_THREAD); msg.obj = mAppConfigUtils.mAppConfigBean; sGlobalHandler.sendMessage(msg); - LogUtils.d(TAG, "sendRestartRemindThreadMessage: 退出"); + LogUtils.d(TAG, "sendRestartRemindThreadMessage: msg sent"); } // ======================== 静态工具方法 ======================== public static void reloadAppConfig() { - LogUtils.d(TAG, "reloadAppConfig: 发送配置更新消息"); + LogUtils.d(TAG, "reloadAppConfig: send MSG_RELOAD_APPCONFIG"); if (sGlobalHandler != null) { sGlobalHandler.sendEmptyMessage(MSG_RELOAD_APPCONFIG); } } public static void sendCurrentBatteryValueMessage(int value) { - LogUtils.d(TAG, "sendCurrentBatteryValueMessage: 电量=" + value); + LogUtils.d(TAG, "sendCurrentBatteryValueMessage: battery=" + value); if (sGlobalHandler != null) { Message msg = sGlobalHandler.obtainMessage(MSG_CURRENTVALUEBATTERY); msg.arg1 = value; @@ -596,9 +557,9 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV // ======================== 辅助工具方法 ======================== private String getRealPathFromUri(Uri contentUri) { - LogUtils.d(TAG, "getRealPathFromUri: 进入"); + LogUtils.d(TAG, "getRealPathFromUri: uri=" + contentUri); if (contentUri == null) { - LogUtils.e(TAG, "getRealPathFromUri: URI为空"); + LogUtils.e(TAG, "getRealPathFromUri: Uri is null"); return null; } String realPath = null; @@ -616,12 +577,12 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV cursor.close(); } } - LogUtils.d(TAG, "getRealPathFromUri: 退出,路径=" + realPath); + LogUtils.d(TAG, "getRealPathFromUri: path=" + realPath); return realPath; } private APPInfo genDefaultAppInfo() { - LogUtils.d(TAG, "genDefaultAppInfo: 进入"); + LogUtils.d(TAG, "genDefaultAppInfo: start"); String branchName = "powerbell"; APPInfo appInfo = new APPInfo(); appInfo.setAppName(getString(R.string.app_name)); @@ -634,39 +595,38 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV appInfo.setAppHomePage("https://www.winboll.cc/apks/index.php?project=PowerBell"); appInfo.setAppAPKName("PowerBell"); appInfo.setAppAPKFolderName("PowerBell"); - LogUtils.d(TAG, "genDefaultAppInfo: 退出"); + LogUtils.d(TAG, "genDefaultAppInfo: end"); return appInfo; } // ======================== MainContentView 事件回调 ======================== @Override public void onChargeReminderSwitchChanged(boolean isChecked) { - LogUtils.d(TAG, "onChargeReminderSwitchChanged: 状态=" + isChecked); + LogUtils.d(TAG, "onChargeReminderSwitchChanged: isChecked=" + isChecked); sendRestartRemindThreadMessage(); } @Override public void onUsageReminderSwitchChanged(boolean isChecked) { - LogUtils.d(TAG, "onUsageReminderSwitchChanged: 状态=" + isChecked); + LogUtils.d(TAG, "onUsageReminderSwitchChanged: isChecked=" + isChecked); sendRestartRemindThreadMessage(); } @Override public void onServiceSwitchChanged(boolean isChecked) { - LogUtils.d(TAG, "onServiceSwitchChanged: 状态=" + isChecked); - // 仅更新本地配置,不触发服务启停 + LogUtils.d(TAG, "onServiceSwitchChanged: isChecked=" + isChecked); toggleServiceEnableState(isChecked); } @Override public void onChargeReminderProgressChanged(int progress) { - LogUtils.d(TAG, "onChargeReminderProgressChanged: 进度=" + progress); + LogUtils.d(TAG, "onChargeReminderProgressChanged: progress=" + progress); sendRestartRemindThreadMessage(); } @Override public void onUsageReminderProgressChanged(int progress) { - LogUtils.d(TAG, "onUsageReminderProgressChanged: 进度=" + progress); + LogUtils.d(TAG, "onUsageReminderProgressChanged: progress=" + progress); sendRestartRemindThreadMessage(); } } diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/receivers/ControlCenterServiceReceiver.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/receivers/ControlCenterServiceReceiver.java index 5416741..e1e4a2e 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/receivers/ControlCenterServiceReceiver.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/receivers/ControlCenterServiceReceiver.java @@ -216,19 +216,15 @@ public class ControlCenterServiceReceiver extends BroadcastReceiver { // 先同步完整配置(核心:setAppConfigBean已包含状态同步,无需重复设置) remindThread.setAppConfigBean(config); - // 额外同步实时状态(兜底,确保最新) - remindThread.setIsCharging(isCharging); - remindThread.setQuantityOfElectricity(batteryLevel); - // 确保线程开启提醒功能 - remindThread.setIsReminding(true); - - // 线程未运行时唤醒,已运行时无需操作(避免重复唤醒导致逻辑紊乱) - if (!remindThread.isRunning()) { - synchronized (remindThread) { - remindThread.notify(); - LogUtils.d(TAG, "updateRemindThreadConfig: remindThread is woken up"); - } - } +// +// +// // 线程未运行时唤醒,已运行时无需操作(避免重复唤醒导致逻辑紊乱) +// 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); diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/services/ControlCenterService.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/services/ControlCenterService.java index bca0ee1..dd9b215 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/services/ControlCenterService.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/services/ControlCenterService.java @@ -1,7 +1,6 @@ package cc.winboll.studio.powerbell.services; import android.app.ActivityManager; -import android.app.Notification; import android.app.Service; import android.content.Context; import android.content.Intent; @@ -10,11 +9,8 @@ import android.os.Build; import android.os.IBinder; import android.os.PowerManager; import android.provider.Settings; -import android.text.TextUtils; -import androidx.core.app.NotificationCompat; import cc.winboll.studio.libappbase.LogUtils; import cc.winboll.studio.libappbase.ToastUtils; -import cc.winboll.studio.powerbell.R; import cc.winboll.studio.powerbell.handlers.ControlCenterServiceHandler; import cc.winboll.studio.powerbell.models.AppConfigBean; import cc.winboll.studio.powerbell.models.ControlCenterServiceBean; @@ -30,13 +26,15 @@ import java.util.List; * @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; - // ================================== 成员变量(按功能分类,私有封装+并发锁保护)================================= + // ================================== 成员变量(按功能分类,私有封装)================================= // 服务控制核心 private ControlCenterServiceBean mServiceControlBean; // 业务核心组件 @@ -45,184 +43,164 @@ public class ControlCenterService extends Service { private NotificationManagerUtils mNotificationManager; private AppConfigBean mCurrentConfigBean; private NotificationMessage mForegroundNotifyMsg; - // 状态标记(复用 isServiceRunning 替代原 isCoreBusinessStarted) + // 状态标记(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: 服务生命周期启动 ====="); + LogUtils.d(TAG, "onCreate: 当前线程=" + Thread.currentThread().getName() + " | 进程ID=" + android.os.Process.myPid()); runCoreServiceLogic(); - LogUtils.d(TAG, "onCreate: 服务创建完成,前台通知已发送,启用状态=" + mServiceControlBean.isEnableService()); + LogUtils.d(TAG, "===== onCreate: 服务生命周期结束 | 前台通知状态=" + (isServiceRunning ? "✅已发送" : "❌未发送") + " | 启用状态=" + (mServiceControlBean != null ? mServiceControlBean.isEnableService() : false) + " ====="); } @Override public int onStartCommand(Intent intent, int flags, int startId) { - LogUtils.d(TAG, "onStartCommand: 服务启动指令触发"); - // 读取最新控制配置 + 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")); loadLatestServiceControlConfig(); - // 调用抽取的核心运行函数 runCoreServiceLogic(); - if (mServiceControlBean.isEnableService()) { - LogUtils.d(TAG, "onStartCommand: 服务已启用,返回START_STICKY"); - return START_STICKY; - } else { - return super.onStartCommand(intent, flags, startId); - } - + 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 + " ====="); + return returnFlag; } @Override public void onDestroy() { + LogUtils.d(TAG, "===== onDestroy: 服务销毁流程启动 ====="); super.onDestroy(); - LogUtils.d(TAG, "onDestroy: 服务开始销毁"); - // 顺序释放资源 stopForegroundService(); stopRemindThreadSafely(); destroyHandler(); releaseNotificationResource(); clearAllReferences(); - - // 重置核心业务标记 - mCurrentConfigBean = null; - mForegroundNotifyMsg = null; - // 重置核心业务标记 - mServiceHandler = null; - isServiceRunning = false; - mIsDestroyed = true; - LogUtils.d(TAG, "onDestroy: 服务销毁完成"); + // 重置核心状态标记 + mCurrentConfigBean = null; + mForegroundNotifyMsg = null; + mServiceHandler = null; + isServiceRunning = false; + mIsDestroyed = true; + LogUtils.d(TAG, "===== onDestroy: 服务销毁流程完成 ====="); } @Override public IBinder onBind(Intent intent) { + LogUtils.d(TAG, "onBind: 服务绑定请求 | intent=" + intent); return null; } - // ================================== 【核心抽取函数】运行服务核心逻辑 ================================= + // ================================== 核心业务逻辑(抽取独立方法,统一管理)================================= /** * 抽取的服务核心运行逻辑,统一在onCreate和onStartCommand调用 * 复用 isServiceRunning 做重复运行判断,避免重复初始化业务 */ private void runCoreServiceLogic() { - loadLatestServiceControlConfig(); - - // 核心校验:服务已启用 + 服务处于运行状态 + 未被销毁 + 业务未初始化(通过mServiceHandler判空) - if (mServiceControlBean.isEnableService()) { - if (!isServiceRunning) { - isServiceRunning = true; - mIsDestroyed = false; - LogUtils.d(TAG, "runCoreServiceLogic: 开始执行服务核心业务"); - // 初始化通知 + 默认配置 + Handler + 线程 - // 优先发送前台通知,避免5秒超时异常 - initForegroundNotificationImmediately(); - // 加载本地服务控制配置 - - //initNotificationManager(); - loadDefaultConfig(); - initServiceBusinessLogic(); - LogUtils.d(TAG, "runCoreServiceLogic: 核心业务执行完成"); - } else { - LogUtils.d(TAG, "runCoreServiceLogic: 核心业务已在运行,无需重复执行"); - } - } else { - 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; + } + } else { + LogUtils.d(TAG, "runCoreServiceLogic: 核心业务已运行或服务已销毁,无需重复执行"); + } + } else { + LogUtils.d(TAG, "runCoreServiceLogic: 服务未启用,跳过核心业务执行"); + } } - // ================================== 前台通知核心方法(优先执行,防止超时)================================= + // ================================== 前台通知管理(优先执行,防止超时异常)================================= /** * 立即初始化前台通知,内置兜底方案 + * @return true:通知初始化成功 false:通知初始化失败 */ - private void initForegroundNotificationImmediately() { - LogUtils.d(TAG, "initForegroundNotificationImmediately: 初始化前台通知"); + private boolean 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()); } mNotificationManager.startForegroundServiceNotify(this, mForegroundNotifyMsg); - ToastUtils.show("startForegroundServiceNotify 已调用"); - LogUtils.d(TAG, "initForegroundNotificationImmediately: 前台通知发送成功,ID=" + NotificationManagerUtils.NOTIFY_ID_FOREGROUND_SERVICE); + ToastUtils.show("startForegroundServiceNotify 已调用"); + LogUtils.d(TAG, "initForegroundNotificationImmediately: 前台通知发送成功 | 通知ID=" + NotificationManagerUtils.NOTIFY_ID_FOREGROUND_SERVICE); + LogUtils.d(TAG, "initForegroundNotificationImmediately: 前台通知初始化流程成功结束"); + return true; } catch (Exception e) { - LogUtils.e(TAG, "initForegroundNotificationImmediately: 工具类发送失败,执行兜底方案", e); - fallbackStartForeground(); + LogUtils.e(TAG, "initForegroundNotificationImmediately: 前台通知初始化流程异常", e); + return false; } } /** - * 前台通知兜底方案,直接构建Notification + * 停止前台服务并取消通知 */ - private void fallbackStartForeground() { + private void stopForegroundService() { + LogUtils.d(TAG, "stopForegroundService: 停止前台服务流程启动"); try { - Notification notification = new NotificationCompat.Builder(this, NotificationManagerUtils.CHANNEL_ID_FOREGROUND) - .setContentTitle("电池监测服务") - .setContentText("后台运行中") - .setSmallIcon(R.drawable.ic_launcher) - .setPriority(NotificationCompat.PRIORITY_LOW) - .build(); - startForeground(NotificationManagerUtils.NOTIFY_ID_FOREGROUND_SERVICE, notification); - LogUtils.d(TAG, "fallbackStartForeground: 兜底前台通知发送成功"); + stopForeground(true); + LogUtils.d(TAG, "stopForegroundService: 前台服务停止成功,通知已取消"); } catch (Exception e) { - LogUtils.e(TAG, "fallbackStartForeground: 兜底发送失败,服务会被系统杀死", 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()); - } else { - LogUtils.w(TAG, "loadLatestServiceControlConfig: 本地无配置,沿用当前状态"); - } + if (latestBean != null) { + mServiceControlBean = latestBean; + LogUtils.d(TAG, "loadLatestServiceControlConfig: 本地配置读取成功 | 启用状态=" + mServiceControlBean.isEnableService()); + } else { + LogUtils.w(TAG, "loadLatestServiceControlConfig: 本地无配置文件,沿用当前内存配置 | 当前配置=" + mServiceControlBean); + } } - /** - * 更新并持久化服务控制配置 - */ - private void updateAndSaveServiceControlConfig(ControlCenterServiceBean newControlBean) { - ControlCenterServiceBean.saveBean(this, mServiceControlBean); - } - - // ================================== 业务初始化与停止(按需加载,避免重复)================================= - /** - * 初始化通知管理工具类 - */ -// private void initNotificationManager() { -// 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"); -// } -// } - /** * 加载默认应用配置 */ private void loadDefaultConfig() { - LogUtils.d(TAG, "loadDefaultConfig: 加载默认配置"); + LogUtils.d(TAG, "loadDefaultConfig: 加载默认业务配置"); if (mCurrentConfigBean == null) { mCurrentConfigBean = new AppConfigBean(); mCurrentConfigBean.setEnableChargeReminder(true); @@ -230,242 +208,214 @@ public class ControlCenterService extends Service { mCurrentConfigBean.setEnableUsageReminder(true); mCurrentConfigBean.setUsageReminderValue(20); mCurrentConfigBean.setBatteryDetectInterval(1000); - LogUtils.d(TAG, "loadDefaultConfig: 默认配置加载完成"); + LogUtils.d(TAG, "loadDefaultConfig: 默认配置加载完成 | 充电阈值=" + 80 + " | 耗电阈值=" + 20 + " | 检测间隔=" + 1000 + "ms"); + } else { + LogUtils.d(TAG, "loadDefaultConfig: 内存中已有业务配置,无需加载默认值 | 当前充电阈值=" + mCurrentConfigBean.getChargeReminderValue()); } } + // ================================== 业务组件初始化与销毁================================= /** * 初始化业务核心逻辑(Handler+线程) */ private void initServiceBusinessLogic() { - LogUtils.d(TAG, "initServiceBusinessLogic: 初始化Handler与线程"); + LogUtils.d(TAG, "initServiceBusinessLogic: 业务组件初始化流程启动"); if (mServiceHandler == null) { mServiceHandler = new ControlCenterServiceHandler(this); + LogUtils.d(TAG, "initServiceBusinessLogic: ControlCenterServiceHandler初始化完成"); + } else { + LogUtils.d(TAG, "initServiceBusinessLogic: ControlCenterServiceHandler已存在,无需重复初始化"); } restartRemindThreadSafely(); - } - - // ================================== 提醒线程管理(安全启停,并发保护)================================= - /** - * 安全重启提醒线程 - */ - public void restartRemindThreadSafely() { - LogUtils.d(TAG, "restartRemindThreadSafely: 开始重启线程"); - - // 停止旧线程 - stopRemindThreadSafely(); - if (mServiceHandler == null) { - // 创建新线程实例 - RemindThread.destroyInstance(); - mRemindThread = RemindThread.getInstance(this, mServiceHandler); - syncConfigToRemindThread(); - // 启动线程 - if (mRemindThread != null && !mRemindThread.isAlive() && !mRemindThread.isThreadStarted()) { - try { - mRemindThread.start(); - LogUtils.d(TAG, "restartRemindThreadSafely: 新线程启动成功,ID=" + mRemindThread.getId()); - } catch (IllegalThreadStateException e) { - LogUtils.e(TAG, "restartRemindThreadSafely: 线程重复启动异常", e); - mRemindThread = null; - } - } else { - LogUtils.w(TAG, "restartRemindThreadSafely: 线程状态异常,跳过启动"); - } - } else { - LogUtils.d(TAG, "mServiceHandler is null"); - } - + LogUtils.d(TAG, "initServiceBusinessLogic: 业务组件初始化流程结束"); } /** - * 安全停止提醒线程 - */ - private void stopRemindThreadSafely() { - LogUtils.d(TAG, "stopRemindThreadSafely: 停止提醒线程"); - if (mRemindThread == null) { - LogUtils.w(TAG, "stopRemindThreadSafely: 线程实例为空"); - return; - } - try { - if (mRemindThread.isThreadStarted() || mRemindThread.isAlive()) { - mRemindThread.setIsReminding(false); - mRemindThread.stopThread(); - // 等待线程终止,超时1秒强制中断 - long waitStartTime = System.currentTimeMillis(); - while (mRemindThread.isAlive()) { - if (System.currentTimeMillis() - waitStartTime > 1000) { - LogUtils.w(TAG, "stopRemindThreadSafely: 线程停止超时,强制中断"); - mRemindThread.interrupt(); - break; - } - Thread.yield(); - } - } - } catch (Exception e) { - LogUtils.e(TAG, "stopRemindThreadSafely: 停止线程异常", e); - } finally { - mRemindThread = null; - RemindThread.destroyInstance(); - } - } - - /** - * 同步配置到提醒线程 - */ - private void syncConfigToRemindThread() { - LogUtils.d(TAG, "syncConfigToRemindThread: 同步配置"); - if (mRemindThread == null || mCurrentConfigBean == null) { - LogUtils.e(TAG, "syncConfigToRemindThread: 线程或配置为空,同步失败"); - return; - } - mRemindThread.setAppConfigBean(mCurrentConfigBean); - mRemindThread.setIsReminding(true); - } - - // ================================== 外部指令处理(接收Intent指令)================================= - /** - * 处理外部发送的服务指令 - */ -// private void handleExternalCommand(Intent intent) { -// LogUtils.d(TAG, "handleExternalCommand: 处理外部指令"); -// if (intent == null || TextUtils.isEmpty(intent.getAction())) { -// LogUtils.e(TAG, "handleExternalCommand: Intent或Action为空"); -// return; -// } -// String action = intent.getAction(); -// if (ACTION_RESTART_REMIND_THREAD.equals(action)) { -// synchronized (mServiceLock) { -// if (mServiceControlBean.isEnableService()) { -// AppConfigBean newConfig = (AppConfigBean) intent.getSerializableExtra(EXTRA_APP_CONFIG_BEAN); -// if (newConfig != null) { -// mCurrentConfigBean = newConfig; -// LogUtils.d(TAG, "handleExternalCommand: 收到配置更新,重启线程"); -// restartRemindThreadSafely(); -// } else { -// LogUtils.e(TAG, "handleExternalCommand: 配置为空,重启失败"); -// } -// } else { -// LogUtils.w(TAG, "handleExternalCommand: 服务已禁用,忽略指令"); -// } -// } -// } -// } - - - // ================================== 资源释放方法(防止内存泄漏)================================= - /** - * 停止前台服务 - */ - private void stopForegroundService() { - LogUtils.d(TAG, "stopForegroundService: 停止前台服务"); - if (mNotificationManager != null) { - mNotificationManager.cancelForegroundServiceNotify(); - } - try { - stopForeground(STOP_FOREGROUND_REMOVE); - } catch (Exception 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已销毁,所有消息已移除"); + } else { + 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: 通知工具类资源释放完成"); + } else { + LogUtils.w(TAG, "releaseNotificationResource: 通知工具类实例为空,无需释放"); } + LogUtils.d(TAG, "releaseNotificationResource: 通知资源释放流程结束"); } /** - * 置空所有引用 + * 置空所有引用,防止内存泄漏 */ private void 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: 配置同步流程结束"); + } + + // ================================== 静态工具方法(对外提供服务入口,按功能归类)================================= /** * 启动服务 */ 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; } - - // 保存服务启动配置 - ControlCenterServiceBean.saveBean(context, new ControlCenterServiceBean(true)); - + // 保存服务启动配置 + ControlCenterServiceBean controlBean = new ControlCenterServiceBean(true); + ControlCenterServiceBean.saveBean(context, controlBean); + LogUtils.d(TAG, "startControlCenterService: 服务启动配置已保存 | 启用状态=" + controlBean.isEnableService()); + // 构建启动Intent 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, "startForegroundService 已调用"); } else { + LogUtils.d(TAG, "startControlCenterService: SDK版本<26,调用startService启动普通服务"); context.startService(intent); - LogUtils.d(TAG, "startService 已调用"); } + 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; } - - // 保存服务启动配置 - ControlCenterServiceBean.saveBean(context, new ControlCenterServiceBean(false)); - + // 保存服务停止配置 + 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: 外部停止服务接口调用完成 ====="); } - /** - * 更新服务控制配置并启停服务 - */ -// public static void updateServiceControlConfig(Context context, ControlCenterServiceBean controlBean) { -// LogUtils.d(TAG, "updateServiceControlConfig: 更新控制配置,启用状态=" + controlBean.isEnableService()); -// if (context == null || controlBean == null) { -// LogUtils.e(TAG, "updateServiceControlConfig: 参数为空"); -// return; -// } -// if (controlBean.isEnableService()) { -// startControlCenterService(context); -// } else { -// stopControlCenterService(context); -// } -// } - /** * 更新业务配置并触发线程重启 */ public static void updateStatus(Context context, AppConfigBean configBean) { - LogUtils.d(TAG, "updateStatus: 发送配置更新指令"); + LogUtils.d(TAG, "===== updateStatus: 外部更新配置接口调用 ====="); if (context == null || configBean == null) { - LogUtils.e(TAG, "updateStatus: 参数为空"); + LogUtils.e(TAG, "updateStatus: 参数为空 | context=" + context + " | configBean=" + configBean); 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); @@ -473,21 +423,26 @@ public class ControlCenterService extends Service { 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: 外部更新配置接口调用完成 ====="); } /** * 检查并引导用户开启忽略电池优化 */ public static void checkIgnoreBatteryOptimization(Context context) { - LogUtils.d(TAG, "checkIgnoreBatteryOptimization: 检查电池优化状态"); + LogUtils.d(TAG, "checkIgnoreBatteryOptimization: 电池优化检查流程启动"); if (context == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + LogUtils.w(TAG, "checkIgnoreBatteryOptimization: 无需检查 | context=" + context + " | SDK版本=" + (Build.VERSION.SDK_INT)); return; } PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); @@ -496,32 +451,43 @@ public class ControlCenterService extends Service { return; } try { - boolean isIgnored = powerManager.isIgnoringBatteryOptimizations(context.getPackageName()); + 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:" + context.getPackageName())); + 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: 已跳转至系统设置页,引导用户开启忽略电池优化"); + } else { + LogUtils.d(TAG, "checkIgnoreBatteryOptimization: 已开启忽略电池优化,无需引导"); } } catch (Exception e) { - LogUtils.e(TAG, "checkIgnoreBatteryOptimization: 引导异常", e); + LogUtils.e(TAG, "checkIgnoreBatteryOptimization: 引导用户开启忽略电池优化异常", e); } + LogUtils.d(TAG, "checkIgnoreBatteryOptimization: 电池优化检查流程结束"); } /** * 判断服务是否运行(适配API30+) */ private static boolean isServiceRunning(Context context, Class serviceClass) { + LogUtils.d(TAG, "isServiceRunning: 服务运行状态检查流程启动 | serviceClass=" + (serviceClass != null ? serviceClass.getName() : "null")); if (context == null || serviceClass == null) { + LogUtils.e(TAG, "isServiceRunning: 参数为空 | context=" + context + " | serviceClass=" + serviceClass); + LogUtils.d(TAG, "isServiceRunning: 服务运行状态检查流程结束 | 结果=false"); 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; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + LogUtils.d(TAG, "isServiceRunning: SDK版本>=30,使用进程信息判断"); String packageName = context.getPackageName(); List processes = am.getRunningAppProcesses(); if (processes != null) { @@ -529,78 +495,86 @@ public class ControlCenterService extends Service { if (packageName.equals(process.processName) && (process.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE || process.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND)) { - return true; + isRunning = true; + LogUtils.d(TAG, "isServiceRunning: 检测到前台服务进程,判定服务运行"); + break; } } } - return isServiceStarted(context, serviceClass); + if (!isRunning) { + LogUtils.d(TAG, "isServiceRunning: API30+未检测到运行,执行兜底判断"); + isRunning = isServiceStarted(context, serviceClass); + } } else { + LogUtils.d(TAG, "isServiceRunning: SDK版本<30,使用服务列表判断"); List runningServices = am.getRunningServices(100); if (runningServices != null) { String serviceClassName = serviceClass.getName(); for (ActivityManager.RunningServiceInfo info : runningServices) { if (serviceClassName.equals(info.service.getClassName())) { - return true; + isRunning = true; + LogUtils.d(TAG, "isServiceRunning: 检测到服务在运行列表中,判定服务运行"); + break; } } } - return false; } + LogUtils.d(TAG, "isServiceRunning: 服务运行状态检查流程结束 | 结果=" + isRunning); + return isRunning; } /** * 兜底判断服务是否已启动 */ private static boolean isServiceStarted(Context context, Class serviceClass) { + LogUtils.d(TAG, "isServiceStarted: 服务状态兜底判断流程启动"); + boolean result = false; try { ControlCenterServiceBean controlBean = ControlCenterServiceBean.loadBean(context, ControlCenterServiceBean.class); - return controlBean != null && controlBean.isEnableService(); + result = controlBean != null && controlBean.isEnableService(); + LogUtils.d(TAG, "isServiceStarted: 兜底判断结果=" + result + " | 配置启用状态=" + (controlBean != null ? controlBean.isEnableService() : "null")); } catch (Exception e) { LogUtils.e(TAG, "isServiceStarted: 兜底判断异常", e); - return false; + result = false; } + LogUtils.d(TAG, "isServiceStarted: 服务状态兜底判断流程结束 | 结果=" + result); + return result; } - // ================================== Getter/Setter 方法(线程安全)================================= + // ================================== Getter/Setter 方法(添加日志)================================= public RemindThread getRemindThread() { - return mRemindThread; + return mRemindThread; } public void setCurrentConfigBean(AppConfigBean configBean) { - LogUtils.d(TAG, "setCurrentConfigBean: 更新业务配置"); + LogUtils.d(TAG, "setCurrentConfigBean: 业务配置更新接口调用"); if (configBean == null) { - LogUtils.e(TAG, "setCurrentConfigBean: 配置为空"); + LogUtils.e(TAG, "setCurrentConfigBean: 待更新配置为空,更新失败"); return; } - this.mCurrentConfigBean = configBean; - syncConfigToRemindThread(); + this.mCurrentConfigBean = configBean; + syncConfigToRemindThread(); + LogUtils.d(TAG, "setCurrentConfigBean: 业务配置更新完成 | 新充电阈值=" + configBean.getChargeReminderValue()); } -// public void setServiceControlBean(ControlCenterServiceBean controlBean) { -// LogUtils.d(TAG, "setServiceControlBean: 更新控制配置"); -// if (controlBean != null) { -// updateAndSaveServiceControlConfig(controlBean); -// } -// } - public ControlCenterServiceBean getServiceControlBean() { - return mServiceControlBean; + return mServiceControlBean; } public NotificationManagerUtils getNotificationManager() { - return mNotificationManager; + return mNotificationManager; } public NotificationMessage getForegroundNotifyMsg() { - return mForegroundNotifyMsg; + return mForegroundNotifyMsg; } public AppConfigBean getCurrentConfigBean() { - return mCurrentConfigBean; + return mCurrentConfigBean; } public boolean isDestroyed() { - return mIsDestroyed; + return mIsDestroyed; } } diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/threads/RemindThread.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/threads/RemindThread.java index fc58b6d..1965afa 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/threads/RemindThread.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/threads/RemindThread.java @@ -8,79 +8,137 @@ import cc.winboll.studio.powerbell.models.AppConfigBean; import java.lang.ref.WeakReference; /** - * @Author ZhanGSKen&豆包大模型 - * @Date 2025/12/17 13:38 - * @Describe 提醒线程(单例模式):统一管理充电/耗电提醒逻辑,适配Java7+API30+,发送提醒时同步携带当前电量+充电状态 + * 提醒线程(单例模式) + * 功能:统一管理充电/耗电提醒逻辑,发送提醒时携带当前电量+充电状态 + * 适配:Java7 | API30 | 小米手机 + * 特性:线程安全、内存泄漏防护、配置重试兜底 + * 对外接口:仅保留 {@link #startRemindThread(Context, ControlCenterServiceHandler, AppConfigBean)} 和 {@link #stopRemindThread()} */ public class RemindThread extends Thread { - // ================================== 静态常量(置顶,统一管理魔法值)================================= + // ================================== 静态常量(置顶归类,消除魔法值)================================= public static final String TAG = "RemindThread"; - private static final long INIT_DELAY_TIME = 500L; // 初始化延迟(ms,等待服务就绪) - private static final int MIN_SLEEP_TIME = 500; // 最小检测间隔(ms,防高频轮询) - private static final int DEFAULT_SLEEP_TIME = 1000; // 默认检测间隔(ms) - private static final long REMIND_INTERVAL = 3000L; // 重复提醒间隔(ms,防骚扰) - private static final int CONFIG_RETRY_MAX = 3; // 配置同步重试次数(兜底) - private static final int INVALID_BATTERY_VALUE = -1; // 无效电量标记 - private static final long BACKGROUND_SLEEP_TIME = 5000L;// 后台休眠间隔(ms,减少资源占用) - // ================================== 单例核心(线程安全,避免复用旧实例)================================= + // 时间常量 (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 int CONFIG_RETRY_MAX = 3; + private static final int INVALID_BATTERY_VALUE = -1; + + // ================================== 单例核心(线程安全,双重校验锁)================================= private static volatile RemindThread sInstance; - // ================================== 成员变量(按功能分类,volatile+锁保护)================================= - // 依赖资源(防内存泄漏) + // ================================== 成员变量(按功能分层,volatile保证多线程可见性,防内存泄漏)================================= + // 弱引用依赖(避免内存泄漏) private Context mContext; private WeakReference mwrControlCenterServiceHandler; - // 线程状态(核心标记,多线程可见) - private volatile boolean isExist; // 退出标记(true=退出) - private volatile boolean isThreadStarted; // 启动标记(区分isAlive()) - private volatile boolean isReminding; // 全局提醒开关 - private volatile boolean isRemindTimerRunning; // 提醒恢复计时器状态 + // 线程状态标记(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; // 检测间隔(ms,改为long适配大间隔) - private volatile int chargeReminderValue; // 充电提醒阈值(0-100) - private volatile int usageReminderValue; // 耗电提醒阈值(0-100) - private volatile int quantityOfElectricity; // 当前电量(0-100,无效为-1) - private volatile boolean isCharging; // 充电状态标记 + // 业务配置参数(范围校验,实时同步) + private volatile boolean isEnableChargeReminder; + private volatile boolean isEnableUsageReminder; + private volatile long sleepTime; + private volatile int chargeReminderValue; + private volatile int usageReminderValue; + private volatile int quantityOfElectricity; + private volatile boolean isCharging; // 辅助变量(并发安全+防重复提醒) - private volatile long lastRemindTime; // 上次提醒时间戳(ms) - private final Object mLock = new Object(); // 全局锁(保护所有状态变量) + private volatile long lastRemindTime; + private final Object mLock = new Object(); // ================================== 私有构造器(单例专用,初始化状态+防护泄漏)================================= private RemindThread(Context context, ControlCenterServiceHandler handler) { - LogUtils.d(TAG, "构造线程实例,线程名称:" + getName()); this.mContext = context.getApplicationContext(); this.mwrControlCenterServiceHandler = new WeakReference<>(handler); - resetThreadStateInternal(); // 初始化所有状态,避免脏数据 + resetThreadStateInternal(); + LogUtils.d(TAG, "构造线程实例 | threadName=" + getName() + " | threadId=" + getId()); } - // ================================== 单例管理(获取+销毁,彻底释放资源)================================= + // ================================== 对外公开静态方法(仅保留两个:启动+停止)================================= /** - * 获取单例实例(旧线程停止自动销毁,强制入参校验) + * 对外启动线程接口 + * @param context 上下文 + * @param handler 服务处理器 + * @param config 应用配置Bean + * @return 若 isReminding 为 true 直接返回 true;否则创建/启动线程后返回 false */ - public static RemindThread getInstance(Context context, ControlCenterServiceHandler handler) { - LogUtils.d(TAG, "获取单例,当前实例是否存在:" + (sInstance != null)); - if (context == null || handler == null) { - LogUtils.e(TAG, "致命错误:Context/ControlCenterServiceHandler不能为空"); - throw new IllegalArgumentException("Context and ControlCenterServiceHandler cannot be null"); + public static boolean startRemindThread(Context context, ControlCenterServiceHandler handler, AppConfigBean config) { + // 入参校验 + if (context == null || handler == null || config == null) { + LogUtils.e(TAG, "startRemindThread: 入参为空,启动失败"); + return false; } - // 旧线程停止则销毁,确保新实例有效 - if (sInstance != null && !sInstance.isRunning()) { - destroyInstance(); - LogUtils.d(TAG, "旧线程已停止,销毁单例准备创建新实例"); + // 1. 若 isReminding 为真,直接返回 true 无需操作 + if (sInstance != null && sInstance.isReminding) { + LogUtils.d(TAG, "startRemindThread: isReminding为true,直接返回"); + return true; } - // 双重校验锁创建单例 + // 2. 未创建实例则创建 if (sInstance == null) { synchronized (RemindThread.class) { if (sInstance == null) { sInstance = new RemindThread(context, handler); - LogUtils.d(TAG, "新线程实例创建成功,线程ID:" + sInstance.getId()); + } + } + } + + // 3. 同步配置 + sInstance.setAppConfigBean(config); + + // 4. 线程未运行则启动 + if (!sInstance.isRunning()) { + sInstance.isExist = false; // 重置退出标记 + sInstance.start(); + LogUtils.d(TAG, "startRemindThread: 线程启动成功 | threadId=" + sInstance.getId()); + } else { + LogUtils.d(TAG, "startRemindThread: 线程已在运行 | threadId=" + sInstance.getId()); + } + + return false; + } + + /** + * 对外停止线程接口:直接销毁单例 + */ + public static void stopRemindThread() { + LogUtils.d(TAG, "stopRemindThread: 开始停止线程"); + destroyInstance(); + LogUtils.d(TAG, "stopRemindThread: 线程已停止并销毁"); + } + + // ================================== 私有单例管理方法(内部使用)================================= + /** + * 获取单例实例(私有化,仅内部调用) + */ + 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()); } } } @@ -90,201 +148,213 @@ public class RemindThread extends Thread { /** * 销毁单例(安全停止线程+释放资源,避免内存泄漏) */ - public static void destroyInstance() { - LogUtils.d(TAG, "开始销毁线程单例"); + private static void destroyInstance() { + LogUtils.d(TAG, "destroyInstance: 开始销毁线程单例"); synchronized (RemindThread.class) { if (sInstance != null) { - sInstance.stopThread(); - sInstance.releaseResources(); + sInstance.isExist = true; + sInstance.isReminding = false; + sInstance.isRemindTimerRunning = false; + if (sInstance.isAlive()) { + sInstance.interrupt(); + LogUtils.d(TAG, "destroyInstance: 线程已中断"); + } + sInstance.releaseResourcesInternal(); sInstance = null; - LogUtils.d(TAG, "线程单例销毁完成"); + LogUtils.d(TAG, "destroyInstance: 线程单例销毁完成"); } else { - LogUtils.w(TAG, "单例已为空,跳过销毁"); + LogUtils.w(TAG, "destroyInstance: 单例已为空,跳过销毁"); } } } - // ================================== 线程核心逻辑(run方法,高效退出+异常容错)================================= + // ================================== 线程核心逻辑(run方法,高效退出+异常容错,仅此处保留mLock)================================= @Override public void run() { - LogUtils.d(TAG, "线程启动,ID:" + Thread.currentThread().getId() + ",状态:" + getState()); - // 防止run方法重复执行 + LogUtils.d(TAG, "run: 线程启动 | threadId=" + Thread.currentThread().getId() + " | state=" + getState()); + + // 仅保留此处的mLock,保护isReminding等核心状态的读写,防止线程重复启动 synchronized (mLock) { if (isThreadStarted || isExist) { - LogUtils.e(TAG, "线程已启动/待退出,禁止重复执行run"); + LogUtils.e(TAG, "run: 线程重复启动 | isThreadStarted=" + isThreadStarted + " | isExist=" + isExist); return; } isThreadStarted = true; lastRemindTime = 0; + // 确保isReminding初始状态正确 + isReminding = isEnableChargeReminder || isEnableUsageReminder; } // 配置同步重试(失败则兜底默认值) boolean configValid = syncConfigRetry(); if (!configValid) { - LogUtils.e(TAG, "配置同步失败,使用默认阈值兜底启动"); + LogUtils.e(TAG, "run: 配置同步失败,使用兜底阈值启动"); } // 初始化延迟(等待服务就绪) try { - LogUtils.d(TAG, "初始化延迟" + INIT_DELAY_TIME + "ms"); + LogUtils.d(TAG, "run: 初始化延迟 | delayTime=" + INIT_DELAY_TIME + "ms"); Thread.sleep(INIT_DELAY_TIME); if (isExist) { - LogUtils.d(TAG, "延迟期间收到退出指令,线程终止"); - cleanThreadState(); + LogUtils.d(TAG, "run: 延迟期间收到退出指令,线程终止"); + cleanThreadStateInternal(); return; } } catch (InterruptedException e) { Thread.currentThread().interrupt(); - LogUtils.e(TAG, "初始化延迟被中断,线程终止", e); - cleanThreadState(); + LogUtils.e(TAG, "run: 初始化延迟被中断,线程终止", e); + cleanThreadStateInternal(); return; } + // ===================== 新增:首次电量检测,立即触发符合条件的提醒 ===================== + LogUtils.d(TAG, "run: 执行首次电量检测"); + if (!isExist && isReminding && quantityOfElectricity != INVALID_BATTERY_VALUE) { + // 充电提醒:充电中 + 充电提醒开启 + 电量≥阈值 + if (isCharging && isEnableChargeReminder && quantityOfElectricity >= chargeReminderValue) { + LogUtils.d(TAG, "run: 首次检测触发充电提醒 | battery=" + quantityOfElectricity + " ≥ threshold=" + chargeReminderValue); + sendNotificationMessageInternal("+", quantityOfElectricity, isCharging); + lastRemindTime = System.currentTimeMillis(); + startRemindRecoveryTimerInternal(); + } + // 耗电提醒:未充电 + 耗电提醒开启 + 电量≤阈值 + else if (!isCharging && isEnableUsageReminder && quantityOfElectricity <= usageReminderValue) { + LogUtils.d(TAG, "run: 首次检测触发耗电提醒 | battery=" + quantityOfElectricity + " ≤ threshold=" + usageReminderValue); + sendNotificationMessageInternal("-", quantityOfElectricity, isCharging); + lastRemindTime = System.currentTimeMillis(); + startRemindRecoveryTimerInternal(); + } + } + // 核心检测循环(快速退出+并发安全) - LogUtils.d(TAG, "进入电量检测循环,间隔:" + sleepTime + "ms"); + LogUtils.d(TAG, "run: 进入电量检测循环 | sleepTime=" + sleepTime + "ms"); while (!isExist) { try { if (isExist) break; - // 核心防护:提醒关闭/电量无效,直接休眠(跳过提醒检测) - synchronized (mLock) { - // 提醒关闭/电量无效:正常休眠,不检测 - if (!isReminding || quantityOfElectricity == INVALID_BATTERY_VALUE) { - safeSleep(sleepTime); - continue; - } - // 电量超出范围:修正为无效,休眠重试 - if (quantityOfElectricity < 0 || quantityOfElectricity > 100) { - LogUtils.w(TAG, "电量无效(" + quantityOfElectricity + "),标记为无效值"); - quantityOfElectricity = INVALID_BATTERY_VALUE; - safeSleep(sleepTime); - continue; - } + // 核心防护:提醒关闭/电量无效,直接休眠(依赖volatile保证可见性) + if (!isReminding || quantityOfElectricity == INVALID_BATTERY_VALUE) { + safeSleepInternal(sleepTime); + continue; + } + // 电量超出范围:修正为无效值 + if (quantityOfElectricity < 0 || quantityOfElectricity > 100) { + LogUtils.w(TAG, "run: 电量无效,修正为无效值 | currentBattery=" + quantityOfElectricity); + quantityOfElectricity = INVALID_BATTERY_VALUE; + safeSleepInternal(sleepTime); + continue; } - // 锁保护核心提醒逻辑(仅提醒开启+电量有效时执行) - synchronized (mLock) { - if (isExist || !isReminding || quantityOfElectricity == INVALID_BATTERY_VALUE) { - safeSleep(sleepTime); - continue; - } - - // 防重复提醒(间隔未到/计时器运行中) - long currentTime = System.currentTimeMillis(); - if ((currentTime - lastRemindTime < REMIND_INTERVAL) || isRemindTimerRunning) { - safeSleep(sleepTime); - continue; - } - - // 充电提醒触发(携带当前电量+充电状态发送) - if (isCharging && isEnableChargeReminder && quantityOfElectricity >= chargeReminderValue) { - LogUtils.d(TAG, "触发充电提醒:充电中,电量" + quantityOfElectricity + "≥阈值" + chargeReminderValue); - sendNotificationMessage("+", quantityOfElectricity, isCharging); - lastRemindTime = currentTime; - startRemindRecoveryTimer(); - } - // 耗电提醒触发(携带当前电量+充电状态发送) - else if (!isCharging && isEnableUsageReminder && quantityOfElectricity <= usageReminderValue) { - LogUtils.d(TAG, "触发耗电提醒:未充电,电量" + quantityOfElectricity + "≤阈值" + usageReminderValue); - sendNotificationMessage("-", quantityOfElectricity, isCharging); - lastRemindTime = currentTime; - startRemindRecoveryTimer(); - } + // 防重复提醒(间隔未到/计时器运行中,依赖volatile保证可见性) + long currentTime = System.currentTimeMillis(); + if ((currentTime - lastRemindTime < REMIND_INTERVAL) || isRemindTimerRunning) { + safeSleepInternal(sleepTime); + continue; } - safeSleep(sleepTime); + // 充电提醒触发 + if (isCharging && isEnableChargeReminder && quantityOfElectricity >= 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); + sendNotificationMessageInternal("-", quantityOfElectricity, isCharging); + lastRemindTime = currentTime; + startRemindRecoveryTimerInternal(); + } + + safeSleepInternal(sleepTime); } catch (Exception e) { - LogUtils.e(TAG, "线程运行异常,休眠重试", e); - safeSleep(sleepTime); + LogUtils.e(TAG, "run: 线程运行异常,休眠重试", e); + safeSleepInternal(sleepTime); } } // 退出清理 - cleanThreadState(); - LogUtils.d(TAG, "线程循环退出,ID:" + Thread.currentThread().getId()); + 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) { - synchronized (mLock) { - if ((chargeReminderValue >= 0 && chargeReminderValue <= 100) - && (usageReminderValue >= 0 && usageReminderValue <= 100)) { - LogUtils.d(TAG, "配置同步成功,重试次数:" + retryCount); - return true; - } + 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, "配置未同步,重试次数:" + (retryCount + 1)); + LogUtils.w(TAG, "syncConfigRetry: 配置未同步,重试 | retryCount=" + (retryCount + 1)); try { Thread.sleep(1000); retryCount++; } catch (InterruptedException e) { Thread.currentThread().interrupt(); - LogUtils.e(TAG, "配置重试被中断", e); + LogUtils.e(TAG, "syncConfigRetry: 配置重试被中断", e); return false; } } - // 兜底默认阈值(避免无效值触发提醒) - synchronized (mLock) { - chargeReminderValue = (chargeReminderValue < 0 || chargeReminderValue > 100) ? 80 : chargeReminderValue; - usageReminderValue = (usageReminderValue < 0 || usageReminderValue > 100) ? 20 : usageReminderValue; - quantityOfElectricity = INVALID_BATTERY_VALUE; // 兜底电量设为无效,防止误触发 - LogUtils.e(TAG, "配置重试失败,兜底阈值:充电" + chargeReminderValue + ",耗电" + usageReminderValue + "RuntimeException : Config sync failed."); - } + + // 兜底默认阈值 + 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复用,防泄漏) - * @param type 提醒类型(+:充电提醒,-:耗电提醒) - * @param battery 当前电量(0-100) - * @param isCharging 当前充电状态(true=充电中) */ - private void sendNotificationMessage(String type, int battery, boolean isCharging) { - LogUtils.d(TAG, "准备发送提醒消息:类型=" + type + ",电量=" + battery + ",充电状态=" + isCharging); - // 双重防护:线程退出/提醒关闭,跳过发送 + private void sendNotificationMessageInternal(String type, int battery, boolean isCharging) { + LogUtils.d(TAG, "sendNotificationMessageInternal: 准备发送提醒 | type=" + type + " | battery=" + battery + " | isCharging=" + isCharging); + if (isExist || !isReminding) { - LogUtils.d(TAG, "线程退出/提醒关闭,跳过发送"); + LogUtils.d(TAG, "sendNotificationMessageInternal: 线程退出或提醒关闭,跳过发送"); return; } ControlCenterServiceHandler handler = mwrControlCenterServiceHandler != null ? mwrControlCenterServiceHandler.get() : null; if (handler == null) { - LogUtils.w(TAG, "Handler已回收,发送失败"); + LogUtils.w(TAG, "sendNotificationMessageInternal: Handler已回收,发送失败"); return; } - // 构建消息:what=提醒标识,obj=类型,arg1=当前电量,arg2=充电状态(0=未充电,1=充电中) Message message = Message.obtain(handler, ControlCenterServiceHandler.MSG_REMIND_TEXT); message.obj = type; message.arg1 = battery; - message.arg2 = isCharging ? 1 : 0; // boolean转int(兼容Java7) + message.arg2 = isCharging ? 1 : 0; + try { handler.sendMessage(message); - LogUtils.d(TAG, "提醒消息发送成功:类型=" + type + ",电量=" + battery + ",充电状态=" + isCharging); + LogUtils.d(TAG, "sendNotificationMessageInternal: 提醒消息发送成功"); } catch (Exception e) { - LogUtils.e(TAG, "消息发送异常", e); + LogUtils.e(TAG, "sendNotificationMessageInternal: 消息发送异常", e); if (message != null) message.recycle(); } } /** - * 启动提醒恢复计时器(防重复提醒,弱引用线程+锁保护) + * 启动提醒恢复计时器(防重复提醒,弱引用线程) */ - private void startRemindRecoveryTimer() { - LogUtils.d(TAG, "启动提醒恢复计时器,间隔:" + REMIND_INTERVAL + "ms"); - synchronized (mLock) { - if (isExist || isRemindTimerRunning || sInstance != this) { - LogUtils.w(TAG, "计时器启动条件不满足,跳过"); - return; - } - isReminding = false; - isRemindTimerRunning = true; + private void startRemindRecoveryTimerInternal() { + LogUtils.d(TAG, "startRemindRecoveryTimerInternal: 启动提醒恢复计时器 | interval=" + REMIND_INTERVAL + "ms"); + if (isExist || isRemindTimerRunning || sInstance != this) { + LogUtils.w(TAG, "startRemindRecoveryTimerInternal: 计时器启动条件不满足"); + return; } + isReminding = false; + isRemindTimerRunning = true; final WeakReference threadRef = new WeakReference<>(this); new Thread(new Runnable() { @@ -293,323 +363,136 @@ public class RemindThread extends Thread { try { Thread.sleep(REMIND_INTERVAL); RemindThread thread = threadRef.get(); + if (thread == null || thread.isExist || sInstance != thread) { - LogUtils.d(TAG, "线程已销毁,不恢复提醒"); + LogUtils.d(TAG, "startRemindRecoveryTimerInternal: 线程已销毁,不恢复提醒"); return; } - synchronized (thread.mLock) { - // 仅线程存活+有启用提醒时,才恢复提醒 - if (!thread.isExist && sInstance == thread - && (thread.isEnableChargeReminder || thread.isEnableUsageReminder)) { - thread.isReminding = true; - LogUtils.d(TAG, "提醒功能恢复开启"); - } + 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, "计时器被中断", e); + LogUtils.e(TAG, "startRemindRecoveryTimerInternal: 计时器被中断", e); } finally { RemindThread thread = threadRef.get(); - if (thread != null) { - synchronized (thread.mLock) { - if (sInstance == thread) thread.isRemindTimerRunning = false; - } + if (thread != null && sInstance == thread) { + thread.isRemindTimerRunning = false; } - LogUtils.d(TAG, "提醒恢复计时器执行完成"); + LogUtils.d(TAG, "startRemindRecoveryTimerInternal: 提醒恢复计时器执行完成"); } } }, "RemindRecoveryTimer").start(); } - // ================================== 线程控制方法(停止+休眠+状态清理)================================= - /** - * 安全停止线程(快速退出+中断休眠) - */ - public void stopThread() { - LogUtils.d(TAG, "开始停止线程,当前状态:" + getState()); - synchronized (mLock) { - isExist = true; - isReminding = false; - isRemindTimerRunning = false; - } - if (isAlive()) { - interrupt(); - LogUtils.d(TAG, "线程已中断,加速退出"); - } - if (sInstance == this) sInstance = null; - } - - /** - * 废弃方法(统一用stopThread) - */ - @Deprecated - public void forceStopThread() { - LogUtils.w(TAG, "forceStopThread已废弃,请调用stopThread"); - stopThread(); - } - /** * 安全休眠(保留中断标记,确保退出逻辑生效) */ - private void safeSleep(long millis) { + private void safeSleepInternal(long millis) { try { Thread.sleep(millis); } catch (InterruptedException e) { Thread.currentThread().interrupt(); - LogUtils.w(TAG, "休眠被中断,线程准备退出"); + LogUtils.w(TAG, "safeSleepInternal: 休眠被中断,线程准备退出"); } } /** * 清理线程运行状态(退出后重置所有标记) */ - private void cleanThreadState() { - LogUtils.d(TAG, "清理线程运行状态"); - synchronized (mLock) { - isReminding = false; - isExist = true; - isThreadStarted = false; - isRemindTimerRunning = false; - lastRemindTime = 0; - quantityOfElectricity = INVALID_BATTERY_VALUE; // 重置为无效电量,防残留 - } + private void cleanThreadStateInternal() { + LogUtils.d(TAG, "cleanThreadStateInternal: 清理线程运行状态"); + isReminding = false; + isExist = true; + isThreadStarted = false; + isRemindTimerRunning = false; + lastRemindTime = 0; + quantityOfElectricity = INVALID_BATTERY_VALUE; if (isAlive()) interrupt(); - if (sInstance == this) sInstance = null; } - // ================================== 状态重置方法(初始化+运行时重置)================================= /** * 初始状态重置(构造器专用) */ private void resetThreadStateInternal() { - LogUtils.d(TAG, "重置线程初始状态"); - synchronized (mLock) { - // 线程状态 - isExist = false; - isReminding = false; - isThreadStarted = false; - isRemindTimerRunning = false; - lastRemindTime = 0; - // 业务配置 - isEnableChargeReminder = false; - isEnableUsageReminder = false; - sleepTime = DEFAULT_SLEEP_TIME; - chargeReminderValue = -1; - usageReminderValue = -1; - quantityOfElectricity = INVALID_BATTERY_VALUE; // 初始设为无效 - isCharging = false; - } + LogUtils.d(TAG, "resetThreadStateInternal: 重置线程初始状态"); + isExist = false; + isReminding = false; + isThreadStarted = false; + isRemindTimerRunning = false; + lastRemindTime = 0; + isEnableChargeReminder = false; + isEnableUsageReminder = false; + sleepTime = DEFAULT_SLEEP_TIME; + chargeReminderValue = -1; + usageReminderValue = -1; + quantityOfElectricity = INVALID_BATTERY_VALUE; + isCharging = false; } - /** - * 运行时状态重置(外部调用,不重置配置) - */ - public void resetThreadState() { - LogUtils.d(TAG, "重置线程运行状态"); - synchronized (mLock) { - isExist = false; - isRemindTimerRunning = false; - lastRemindTime = 0; - isReminding = (isEnableChargeReminder || isEnableUsageReminder); // 根据开关自动开启提醒 - } - LogUtils.d(TAG, "运行状态重置完成,全局提醒:" + isReminding); - } - - // ================================== 配置同步方法(完整同步配置,原子操作+无效电量防护)================================= /** * 同步应用配置(参数校验+范围限制,立即生效) */ public void setAppConfigBean(AppConfigBean config) { + LogUtils.d(TAG, "setAppConfigBean: 开始同步应用配置 | config=" + config); if (config == null) { - LogUtils.e(TAG, "配置Bean为空,同步失败"); - synchronized (mLock) { - quantityOfElectricity = INVALID_BATTERY_VALUE; // 配置为空,标记电量无效 - } + LogUtils.e(TAG, "setAppConfigBean: 配置Bean为空,同步失败"); + quantityOfElectricity = INVALID_BATTERY_VALUE; return; } - LogUtils.d(TAG, "开始同步配置:充电阈值" + config.getChargeReminderValue() + ",耗电阈值" + config.getUsageReminderValue() + ",当前电量" + config.getCurrentBatteryValue()); - synchronized (mLock) { - // 同步开关 - isEnableChargeReminder = config.isEnableChargeReminder(); - isEnableUsageReminder = config.isEnableUsageReminder(); - // 同步阈值(0-100限制) - 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); - // 同步电池状态(校验有效,无效则标记为-1) - int currentBattery = config.getCurrentBatteryValue(); - quantityOfElectricity = (currentBattery >= 0 && currentBattery <= 100) ? currentBattery : INVALID_BATTERY_VALUE; - isCharging = config.isCharging(); - // 提醒开关:根据配置自动开启 - isReminding = (isEnableChargeReminder || isEnableUsageReminder); - } - LogUtils.d(TAG, "配置同步完成:检测间隔" + sleepTime + "ms,全局提醒" + isReminding + ",当前电量" + quantityOfElectricity); + + 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; + isCharging = config.isCharging(); + isReminding = isEnableChargeReminder || isEnableUsageReminder; + + LogUtils.d(TAG, "setAppConfigBean: 配置同步完成 | sleepTime=" + sleepTime + "ms | isReminding=" + isReminding + " | currentBattery=" + quantityOfElectricity); } - // ================================== Setter/Getter(锁保护,线程安全+精准日志)================================= - public boolean isExist() { - synchronized (mLock) { - return isExist; - } + /** + * 判断线程是否处于运行状态 + */ + private boolean isRunning() { + boolean running = !isExist && isThreadStarted && isAlive(); + LogUtils.d(TAG, "isRunning: 线程运行状态=" + running + " | isExist=" + isExist + " | isThreadStarted=" + isThreadStarted + " | isAlive=" + isAlive()); + return running; } - public void setIsExist(boolean isExist) { - synchronized (mLock) { - this.isExist = isExist; - LogUtils.d(TAG, "设置线程退出标记:" + isExist); + /** + * 释放线程所有资源(内部方法) + */ + private void releaseResourcesInternal() { + LogUtils.d(TAG, "releaseResourcesInternal: 开始释放线程资源"); + mContext = null; + if (mwrControlCenterServiceHandler != null) { + mwrControlCenterServiceHandler.clear(); + mwrControlCenterServiceHandler = null; } + cleanThreadStateInternal(); + LogUtils.d(TAG, "releaseResourcesInternal: 线程资源释放完成"); } - public boolean isReminding() { - synchronized (mLock) { - return isReminding; - } - } - - public void setIsReminding(boolean isReminding) { - synchronized (mLock) { - this.isReminding = isReminding; - LogUtils.d(TAG, "设置全局提醒开关:" + this.isReminding); - } - } - - public boolean isThreadStarted() { - synchronized (mLock) { - return isThreadStarted; - } - } - - public boolean isEnableUsageReminder() { - synchronized (mLock) { - return isEnableUsageReminder; - } - } - - public void setIsEnableUsageReminder(boolean isEnableUsageReminder) { - synchronized (mLock) { - this.isEnableUsageReminder = isEnableUsageReminder; - isReminding = (isEnableChargeReminder || isEnableUsageReminder); - LogUtils.d(TAG, "设置耗电提醒开关:" + isEnableUsageReminder + ",全局提醒:" + isReminding); - } - } - - public boolean isEnableChargeReminder() { - synchronized (mLock) { - return isEnableChargeReminder; - } - } - - public void setIsEnableChargeReminder(boolean isEnableChargeReminder) { - synchronized (mLock) { - this.isEnableChargeReminder = isEnableChargeReminder; - isReminding = (isEnableChargeReminder || isEnableUsageReminder); - LogUtils.d(TAG, "设置充电提醒开关:" + isEnableChargeReminder + ",全局提醒:" + isReminding); - } - } - - public long getSleepTime() { - synchronized (mLock) { - return sleepTime; - } - } - - public void setSleepTime(long sleepTime) { - synchronized (mLock) { - this.sleepTime = Math.max(sleepTime, MIN_SLEEP_TIME); - LogUtils.d(TAG, "设置检测间隔:" + this.sleepTime + "ms"); - } - } - - public int getChargeReminderValue() { - synchronized (mLock) { - return chargeReminderValue; - } - } - - public void setChargeReminderValue(int chargeReminderValue) { - synchronized (mLock) { - this.chargeReminderValue = Math.min(Math.max(chargeReminderValue, 0), 100); - LogUtils.d(TAG, "设置充电提醒阈值:" + this.chargeReminderValue); - } - } - - public int getUsageReminderValue() { - synchronized (mLock) { - return usageReminderValue; - } - } - - public void setUsageReminderValue(int usageReminderValue) { - synchronized (mLock) { - this.usageReminderValue = Math.min(Math.max(usageReminderValue, 0), 100); - LogUtils.d(TAG, "设置耗电提醒阈值:" + this.usageReminderValue); - } - } - - public int getQuantityOfElectricity() { - synchronized (mLock) { - return quantityOfElectricity; - } - } - - public void setQuantityOfElectricity(int quantityOfElectricity) { - synchronized (mLock) { - this.quantityOfElectricity = Math.min(Math.max(quantityOfElectricity, 0), 100); - LogUtils.d(TAG, "更新当前电量:" + this.quantityOfElectricity); - } - } - - public boolean isCharging() { - synchronized (mLock) { - return isCharging; - } - } - - public void setIsCharging(boolean isCharging) { - synchronized (mLock) { - this.isCharging = isCharging; - LogUtils.d(TAG, "更新充电状态:" + isCharging); - } - } - - // ================================== 核心状态判断(Service依赖,精准校验)================================= - public boolean isRunning() { - synchronized (mLock) { - boolean running = !isExist && isThreadStarted && isAlive(); - LogUtils.d(TAG, "线程运行状态:" + running + "(退出:" + isExist + ",已启动:" + isThreadStarted + ",存活:" + isAlive() + ")"); - return running; - } - } - - // ================================== 资源释放(彻底断开引用,防内存泄漏)================================= - public void releaseResources() { - LogUtils.d(TAG, "开始释放线程资源"); - synchronized (mLock) { - mContext = null; - if (mwrControlCenterServiceHandler != null) { - mwrControlCenterServiceHandler.clear(); - mwrControlCenterServiceHandler = null; - } - cleanThreadState(); - } - LogUtils.d(TAG, "线程资源释放完成"); - } - - // ================================== 调试辅助(toString,打印核心状态)================================= + // ================================== 调试辅助(toString 私有化,避免对外暴露状态)================================= @Override public String toString() { return "RemindThread{" + "threadId=" + getId() + ", threadName='" + getName() + '\'' + ", isRunning=" + isRunning() + - ", isReminding=" + isReminding() + - ", chargeThreshold=" + getChargeReminderValue() + - ", usageThreshold=" + getUsageReminderValue() + - ", currentBattery=" + getQuantityOfElectricity() + - ", isCharging=" + isCharging() + - ", sleepTime=" + getSleepTime() + "ms" + + ", isReminding=" + isReminding + + ", chargeThreshold=" + chargeReminderValue + + ", usageThreshold=" + usageReminderValue + + ", currentBattery=" + quantityOfElectricity + + ", isCharging=" + isCharging + + ", sleepTime=" + sleepTime + "ms" + '}'; } }