From bea77409a5ccf350be1c5e3969bc24ea613351eb Mon Sep 17 00:00:00 2001 From: ZhanGSKen Date: Fri, 19 Dec 2025 20:31:43 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E7=BD=AE=E9=80=9A=E7=9F=A5=E6=9E=B6?= =?UTF-8?q?=E6=9E=84=E4=B8=BA=E6=97=A7=E5=BC=8F=E6=96=B9=E6=B3=95=EF=BC=8C?= =?UTF-8?q?=E7=94=A8=E7=BA=BF=E7=A8=8B=E5=90=AF=E5=8A=A8=E6=B3=95=E3=80=82?= =?UTF-8?q?=E8=BF=87=E7=A8=8B=E9=A1=BA=E4=BE=BF=E6=95=B4=E7=90=86=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=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 | 200 +++++++----------- .../activities/ClearRecordActivity.java | 2 +- .../handlers/ControlCenterServiceHandler.java | 85 ++++---- .../ControlCenterServiceReceiver.java | 163 ++++++++------ .../receivers/GlobalApplicationReceiver.java | 120 +++++++---- .../services/ControlCenterService.java | 38 ++-- .../powerbell/threads/RemindThread.java | 166 ++++++++------- 8 files changed, 405 insertions(+), 373 deletions(-) diff --git a/powerbell/build.properties b/powerbell/build.properties index 916bc3f..a7edfad 100644 --- a/powerbell/build.properties +++ b/powerbell/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Fri Dec 19 10:40:58 GMT 2025 +#Fri Dec 19 10:59:14 GMT 2025 stageCount=10 libraryProject= baseVersion=15.14 publishVersion=15.14.9 -buildCount=43 +buildCount=44 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 7fc64a0..7b10ec6 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java @@ -28,11 +28,9 @@ import cc.winboll.studio.powerbell.activities.BatteryReportActivity; import cc.winboll.studio.powerbell.activities.ClearRecordActivity; import cc.winboll.studio.powerbell.activities.SettingsActivity; import cc.winboll.studio.powerbell.activities.WinBoLLActivity; -import cc.winboll.studio.powerbell.models.AppConfigBean; import cc.winboll.studio.powerbell.models.BackgroundBean; import cc.winboll.studio.powerbell.models.ControlCenterServiceBean; import cc.winboll.studio.powerbell.services.ControlCenterService; -import cc.winboll.studio.powerbell.threads.RemindThread; import cc.winboll.studio.powerbell.unittest.MainUnitTestActivity; import cc.winboll.studio.powerbell.utils.AppConfigUtils; import cc.winboll.studio.powerbell.utils.BackgroundSourceUtils; @@ -42,24 +40,24 @@ import cc.winboll.studio.powerbell.views.MainContentView; /** * @Author ZhanGSKen&豆包大模型 - * @Date 2025/12/17 13:14 - * @Describe 主活动类:应用核心页面,管理电池监控、背景设置、服务控制等核心功能 - * 适配:Java7 | API30 | 小米手机,优化性能与稳定性,杜绝内存泄漏 - * 核心规则:UI开关直接联动服务启停,本地配置与服务状态实时同步 + * @Date 2025/12/19 20:26 + * @Describe 应用核心主活动 + * 功能:管理电池监控、背景设置、服务启停、权限申请等核心功能 + * 适配:Java7 | API30 | 内存泄漏防护 | 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 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_START_REMIND_THREAD = 3; - private static final int MSG_UPDATE_SERVICE_SWITCH = 4; + private static final int MSG_UPDATE_SERVICE_SWITCH = 3; // ======================== 静态成员(全局共享,严格管控生命周期)======================== private static MainActivity sMainActivity; @@ -95,8 +93,9 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV @Override protected void onCreate(Bundle savedInstanceState) { - LogUtils.d(TAG, "onCreate: start"); + LogUtils.d(TAG, "onCreate: 页面启动,开始初始化流程"); super.onCreate(savedInstanceState); + // 优先初始化全局Handler,避免消息丢失 initGlobalHandler(); // 布局与核心流程初始化 @@ -106,45 +105,41 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV initCriticalView(); initCoreUtilsAsync(); loadNonCriticalViewDelayed(); - LogUtils.d(TAG, "onCreate: end"); } @Override protected void onPostCreate(Bundle savedInstanceState) { - LogUtils.d(TAG, "onPostCreate: start"); super.onPostCreate(savedInstanceState); + LogUtils.d(TAG, "onPostCreate: 发起权限申请"); mPermissionUtils.startPermissionRequest(this); - LogUtils.d(TAG, "onPostCreate: end"); } @Override protected void onResume() { - LogUtils.d(TAG, "onResume: start"); super.onResume(); + LogUtils.d(TAG, "onResume: 恢复页面状态"); // 恢复背景与服务开关UI if (sGlobalHandler != null) { sGlobalHandler.sendEmptyMessage(MSG_LOAD_BACKGROUND); sGlobalHandler.sendEmptyMessage(MSG_UPDATE_SERVICE_SWITCH); - LogUtils.d(TAG, "onResume: send MSG_LOAD_BACKGROUND & MSG_UPDATE_SERVICE_SWITCH"); + LogUtils.d(TAG, "onResume: 发送背景加载与服务开关更新消息"); } // 恢复广告 if (mADsBannerView != null) { mADsBannerView.resumeADs(this); } - LogUtils.d(TAG, "onResume: end"); } @Override protected void onPause() { - LogUtils.d(TAG, "onPause: start"); super.onPause(); - LogUtils.d(TAG, "onPause: end"); + LogUtils.d(TAG, "onPause: 页面暂停"); } @Override protected void onDestroy() { - LogUtils.d(TAG, "onDestroy: start"); super.onDestroy(); + LogUtils.d(TAG, "onDestroy: 开始释放资源"); // 释放广告资源 if (mADsBannerView != null) { mADsBannerView.releaseAdResources(); @@ -155,17 +150,18 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV mMainContentView.releaseResources(); mMainContentView = null; } - // 销毁Handler + // 销毁Handler,防止内存泄漏 if (sGlobalHandler != null) { sGlobalHandler.removeCallbacksAndMessages(null); sGlobalHandler = null; + LogUtils.d(TAG, "onDestroy: 全局Handler已销毁"); } - // 释放Drawable,防止内存泄漏 + // 释放Drawable,清空回调 if (mFrameDrawable != null) { mFrameDrawable.setCallback(null); mFrameDrawable = null; } - // 置空所有引用 + // 置空所有引用,帮助GC回收 sMainActivity = null; mPermissionUtils = null; mAppConfigUtils = null; @@ -175,24 +171,25 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV mApplication = null; mToolbar = null; mAdsViewStub = null; - LogUtils.d(TAG, "onDestroy: end"); + LogUtils.d(TAG, "onDestroy: 所有资源释放完成"); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - LogUtils.d(TAG, "onActivityResult: requestCode=" + requestCode + ", resultCode=" + resultCode); super.onActivityResult(requestCode, resultCode, data); + LogUtils.d(TAG, "onActivityResult: requestCode=" + requestCode + ", resultCode=" + resultCode); mPermissionUtils.handlePermissionRequest(this, requestCode, resultCode, data); // 背景设置完成后重新加载 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: start"); + LogUtils.d(TAG, "onCreateOptionsMenu: 初始化菜单"); mMenu = menu; AESThemeUtil.inflateMenu(this, menu); if (App.isDebugging()) { @@ -200,7 +197,6 @@ 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: end"); return true; } @@ -250,7 +246,7 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV @Override public void onBackPressed() { moveTaskToBack(true); - LogUtils.d(TAG, "onBackPressed: app move to background"); + LogUtils.d(TAG, "onBackPressed: 应用退至后台"); } @Override @@ -260,23 +256,22 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV // ======================== 核心初始化方法 ======================== private void initPermissionUtils() { - LogUtils.d(TAG, "initPermissionUtils: start"); + LogUtils.d(TAG, "initPermissionUtils: 初始化权限工具类"); mPermissionUtils = PermissionUtils.getInstance(); - LogUtils.d(TAG, "initPermissionUtils: end"); } private void initGlobalHandler() { - LogUtils.d(TAG, "initGlobalHandler: start"); + LogUtils.d(TAG, "initGlobalHandler: 初始化全局Handler"); if (sGlobalHandler == null) { sGlobalHandler = new Handler() { @Override public void handleMessage(Message msg) { // 校验Activity状态,避免销毁后操作UI if (sMainActivity == null || sMainActivity.isFinishing() || sMainActivity.isDestroyed()) { - LogUtils.w(TAG, "handleMessage: Activity destroyed, skip msg what=" + msg.what); + LogUtils.w(TAG, "handleMessage: Activity已销毁,跳过消息 what=" + msg.what); return; } - LogUtils.d(TAG, "handleMessage: receive msg what=" + msg.what); + LogUtils.d(TAG, "handleMessage: 处理消息 what=" + msg.what); switch (msg.what) { case MSG_RELOAD_APPCONFIG: sMainActivity.updateViewData(); @@ -290,30 +285,24 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV sMainActivity.reloadBackground(); sMainActivity.setMainLayoutBackgroundColor(); break; - case MSG_START_REMIND_THREAD: - AppConfigBean configBean = (AppConfigBean) msg.obj; - LogUtils.d(TAG, "MSG_START_REMIND_THREAD not yet."); - break; case MSG_UPDATE_SERVICE_SWITCH: sMainActivity.updateServiceSwitchUI(); break; } } }; - LogUtils.d(TAG, "initGlobalHandler: handler created"); + LogUtils.d(TAG, "initGlobalHandler: 全局Handler创建成功"); } - LogUtils.d(TAG, "initGlobalHandler: end"); } private void initMainContentView() { - LogUtils.d(TAG, "initMainContentView: start"); + LogUtils.d(TAG, "initMainContentView: 初始化核心视图"); View rootView = findViewById(android.R.id.content); mMainContentView = new MainContentView(this, rootView, this); - LogUtils.d(TAG, "initMainContentView: MainContentView created"); } private void initCriticalView() { - LogUtils.d(TAG, "initCriticalView: start"); + LogUtils.d(TAG, "initCriticalView: 初始化关键视图组件"); sMainActivity = this; mToolbar = findViewById(R.id.toolbar); setSupportActionBar(mToolbar); @@ -321,15 +310,14 @@ 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: end"); } private void initCoreUtilsAsync() { - LogUtils.d(TAG, "initCoreUtilsAsync: start"); + LogUtils.d(TAG, "initCoreUtilsAsync: 异步初始化核心工具类"); new Thread(new Runnable() { @Override public void run() { - LogUtils.d(TAG, "initCoreUtilsAsync: async thread start"); + LogUtils.d(TAG, "initCoreUtilsAsync: 异步线程启动"); mApplication = (App) getApplication(); mAppConfigUtils = AppConfigUtils.getInstance(getApplicationContext()); mBgSourceUtils = BackgroundSourceUtils.getInstance(getActivity()); @@ -339,7 +327,7 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV if (mServiceControlBean == null) { mServiceControlBean = new ControlCenterServiceBean(false); ControlCenterServiceBean.saveBean(getApplicationContext(), mServiceControlBean); - LogUtils.d(TAG, "initCoreUtilsAsync: create default service config (disabled)"); + LogUtils.d(TAG, "initCoreUtilsAsync: 本地无配置,创建默认禁用配置"); } // 根据配置启停服务 @@ -350,7 +338,7 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV @Override public void run() { ControlCenterService.startControlCenterService(getApplicationContext()); - LogUtils.d(TAG, "initCoreUtilsAsync: start service by config"); + LogUtils.d(TAG, "initCoreUtilsAsync: 配置启用服务,启动服务"); } }); } else if (!isServiceEnable && isServiceAlive) { @@ -358,7 +346,7 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV @Override public void run() { ControlCenterService.stopControlCenterService(getApplicationContext()); - LogUtils.d(TAG, "initCoreUtilsAsync: stop service by config"); + LogUtils.d(TAG, "initCoreUtilsAsync: 配置禁用服务,停止服务"); } }); } @@ -368,7 +356,7 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV @Override public void run() { if (isFinishing() || isDestroyed()) { - LogUtils.w(TAG, "initCoreUtilsAsync: Activity destroyed, skip UI update"); + LogUtils.w(TAG, "initCoreUtilsAsync: Activity已销毁,跳过UI更新"); return; } // 加载框架背景 @@ -382,14 +370,13 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV sGlobalHandler.sendEmptyMessage(MSG_UPDATE_SERVICE_SWITCH); } }); - LogUtils.d(TAG, "initCoreUtilsAsync: async thread end"); + LogUtils.d(TAG, "initCoreUtilsAsync: 异步线程执行完成"); } }).start(); - LogUtils.d(TAG, "initCoreUtilsAsync: end"); } private void loadNonCriticalViewDelayed() { - LogUtils.d(TAG, "loadNonCriticalViewDelayed: start"); + LogUtils.d(TAG, "loadNonCriticalViewDelayed: 延迟加载非核心视图"); new Handler().postDelayed(new Runnable() { @Override public void run() { @@ -399,38 +386,35 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV loadAdsView(); } }, DELAY_LOAD_NON_CRITICAL); - LogUtils.d(TAG, "loadNonCriticalViewDelayed: end"); } // ======================== 视图操作方法 ======================== private void loadAdsView() { - LogUtils.d(TAG, "loadAdsView: start"); + LogUtils.d(TAG, "loadAdsView: 加载广告视图"); if (mAdsViewStub == null) { - LogUtils.e(TAG, "loadAdsView: AdsViewStub is null"); + LogUtils.e(TAG, "loadAdsView: 广告ViewStub为空"); 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: start"); + LogUtils.d(TAG, "updateViewData: 更新视图数据"); if (mMainContentView == null || mFrameDrawable == null) { - LogUtils.e(TAG, "updateViewData: MainContentView or FrameDrawable is null"); + LogUtils.e(TAG, "updateViewData: 核心视图或框架背景为空,更新失败"); return; } mMainContentView.updateViewData(mFrameDrawable); - LogUtils.d(TAG, "updateViewData: view data updated"); } private void reloadBackground() { - LogUtils.d(TAG, "reloadBackground: start"); + LogUtils.d(TAG, "reloadBackground: 重新加载背景"); if (mMainContentView == null || mBgSourceUtils == null) { - LogUtils.e(TAG, "reloadBackground: MainContentView or BackgroundSourceUtils is null"); + LogUtils.e(TAG, "reloadBackground: 核心视图或背景工具类为空,加载失败"); return; } BackgroundBean currentBgBean = mBgSourceUtils.getCurrentBackgroundBean(); @@ -438,115 +422,86 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV mMainContentView.backgroundView.loadBackgroundBean(currentBgBean); } else { mMainContentView.backgroundView.setBackgroundResource(R.drawable.default_background); + LogUtils.w(TAG, "reloadBackground: 无自定义背景,使用默认背景"); } - LogUtils.d(TAG, "reloadBackground: end"); } private void setMainLayoutBackgroundColor() { - LogUtils.d(TAG, "setMainLayoutBackgroundColor: start"); + LogUtils.d(TAG, "setMainLayoutBackgroundColor: 设置主布局背景色"); if (isFinishing() || isDestroyed() || mMainContentView == null || mBgSourceUtils == null) { - LogUtils.e(TAG, "setMainLayoutBackgroundColor: invalid context"); + LogUtils.e(TAG, "setMainLayoutBackgroundColor: 上下文无效,设置失败"); return; } BackgroundBean currentBgBean = mBgSourceUtils.getCurrentBackgroundBean(); if (currentBgBean != null) { mMainContentView.mainLayout.setBackgroundColor(currentBgBean.getPixelColor()); } - LogUtils.d(TAG, "setMainLayoutBackgroundColor: end"); } private void updateServiceSwitchUI() { - LogUtils.d(TAG, "updateServiceSwitchUI: start"); + LogUtils.d(TAG, "updateServiceSwitchUI: 更新服务开关UI状态"); if (mMainContentView == null || mServiceControlBean == null) { - LogUtils.e(TAG, "updateServiceSwitchUI: MainContentView or ServiceControlBean is null"); + LogUtils.e(TAG, "updateServiceSwitchUI: 核心视图或服务配置为空,更新失败"); return; } boolean configEnabled = mServiceControlBean.isEnableService(); - LogUtils.d(TAG, "updateServiceSwitchUI: config enabled=" + configEnabled); + LogUtils.d(TAG, "updateServiceSwitchUI: 服务配置启用状态=" + configEnabled); mMainContentView.setServiceSwitchEnabled(false); mMainContentView.setServiceSwitchChecked(configEnabled); mMainContentView.setServiceSwitchEnabled(true); - LogUtils.d(TAG, "updateServiceSwitchUI: end"); } // ======================== 服务与线程管理方法 ======================== -// 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; -// } -// if (!mServiceControlBean.isEnableService()) { -// LogUtils.w(TAG, "restartRemindThread: service is disabled, skip"); -// return; -// } -// if (!ServiceUtils.isServiceAlive(getApplicationContext(), ControlCenterService.class.getName())) { -// ControlCenterService.startControlCenterService(getApplicationContext()); -// } -// RemindThread.destroyInstance(); -// ControlCenterService.updateStatus(getApplicationContext(), configBean); -// LogUtils.d(TAG, "restartRemindThread: end"); -// } - private void toggleServiceEnableState(boolean isEnable) { - LogUtils.d(TAG, "toggleServiceEnableState: target state=" + isEnable); + LogUtils.d(TAG, "toggleServiceEnableState: 切换服务状态,目标状态=" + isEnable); if (mServiceControlBean == null) { - LogUtils.e(TAG, "toggleServiceEnableState: ServiceControlBean is null"); + LogUtils.e(TAG, "toggleServiceEnableState: 服务配置为空,切换失败"); return; } mServiceControlBean.setIsEnableService(isEnable); ControlCenterServiceBean.saveBean(getApplicationContext(), mServiceControlBean); - // ========== 核心新增逻辑:UI开关联动服务启停 + 线程销毁 ========== + // UI开关联动服务启停 + 线程销毁 if (isEnable) { // 开启:启动服务 if (!ServiceUtils.isServiceAlive(getApplicationContext(), ControlCenterService.class.getName())) { ControlCenterService.startControlCenterService(getApplicationContext()); - LogUtils.d(TAG, "toggleServiceEnableState: start service success"); + LogUtils.d(TAG, "toggleServiceEnableState: 服务已启动"); } } else { - // 关闭:停止服务 + 销毁线程 + // 关闭:停止服务 ControlCenterService.stopControlCenterService(getApplicationContext()); - LogUtils.d(TAG, "toggleServiceEnableState: stop service + destroy thread success"); + LogUtils.d(TAG, "toggleServiceEnableState: 服务已停止"); } sGlobalHandler.sendEmptyMessage(MSG_UPDATE_SERVICE_SWITCH); - LogUtils.d(TAG, "toggleServiceEnableState: config saved + service state synced"); } // ======================== 页面跳转方法 ======================== private void startAboutActivity() { - LogUtils.d(TAG, "startAboutActivity: start"); + LogUtils.d(TAG, "startAboutActivity: 启动关于页面"); 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: end"); } // ======================== 消息发送方法 ======================== - private void sendRestartRemindThreadMessage() { - LogUtils.d(TAG, "sendRestartRemindThreadMessage: start"); - if (sGlobalHandler == null || mAppConfigUtils == null || mAppConfigUtils.mAppConfigBean == null) { - LogUtils.e(TAG, "sendRestartRemindThreadMessage: invalid context"); - return; - } - Message msg = sGlobalHandler.obtainMessage(MSG_START_REMIND_THREAD); - msg.obj = mAppConfigUtils.mAppConfigBean; - sGlobalHandler.sendMessage(msg); - LogUtils.d(TAG, "sendRestartRemindThreadMessage: msg sent"); + private void notifyServiceAppConfigChange() { + LogUtils.d(TAG, "notifyServiceAppConfigChange: 通知服务配置变更"); + // 预留配置变更通知逻辑 } // ======================== 静态工具方法 ======================== public static void reloadAppConfig() { - LogUtils.d(TAG, "reloadAppConfig: send MSG_RELOAD_APPCONFIG"); + LogUtils.d(TAG, "reloadAppConfig: 发送配置重载消息"); if (sGlobalHandler != null) { sGlobalHandler.sendEmptyMessage(MSG_RELOAD_APPCONFIG); } } public static void sendCurrentBatteryValueMessage(int value) { - LogUtils.d(TAG, "sendCurrentBatteryValueMessage: battery=" + value); + LogUtils.d(TAG, "sendCurrentBatteryValueMessage: 发送当前电量消息,电量=" + value); if (sGlobalHandler != null) { Message msg = sGlobalHandler.obtainMessage(MSG_CURRENTVALUEBATTERY); msg.arg1 = value; @@ -556,9 +511,9 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV // ======================== 辅助工具方法 ======================== private String getRealPathFromUri(Uri contentUri) { - LogUtils.d(TAG, "getRealPathFromUri: uri=" + contentUri); + LogUtils.d(TAG, "getRealPathFromUri: 解析Uri路径,Uri=" + contentUri); if (contentUri == null) { - LogUtils.e(TAG, "getRealPathFromUri: Uri is null"); + LogUtils.e(TAG, "getRealPathFromUri: Uri为空,解析失败"); return null; } String realPath = null; @@ -576,12 +531,12 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV cursor.close(); } } - LogUtils.d(TAG, "getRealPathFromUri: path=" + realPath); + LogUtils.d(TAG, "getRealPathFromUri: 解析完成,路径=" + realPath); return realPath; } private APPInfo genDefaultAppInfo() { - LogUtils.d(TAG, "genDefaultAppInfo: start"); + LogUtils.d(TAG, "genDefaultAppInfo: 生成默认应用信息"); String branchName = "powerbell"; APPInfo appInfo = new APPInfo(); appInfo.setAppName(getString(R.string.app_name)); @@ -594,39 +549,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: end"); return appInfo; } // ======================== MainContentView 事件回调 ======================== @Override public void onChargeReminderSwitchChanged(boolean isChecked) { - LogUtils.d(TAG, "onChargeReminderSwitchChanged: isChecked=" + isChecked); - sendRestartRemindThreadMessage(); + LogUtils.d(TAG, "onChargeReminderSwitchChanged: 充电提醒开关状态=" + isChecked); + notifyServiceAppConfigChange(); } @Override public void onUsageReminderSwitchChanged(boolean isChecked) { - LogUtils.d(TAG, "onUsageReminderSwitchChanged: isChecked=" + isChecked); - sendRestartRemindThreadMessage(); + LogUtils.d(TAG, "onUsageReminderSwitchChanged: 耗电提醒开关状态=" + isChecked); + notifyServiceAppConfigChange(); } @Override public void onServiceSwitchChanged(boolean isChecked) { - LogUtils.d(TAG, "onServiceSwitchChanged: isChecked=" + isChecked); + LogUtils.d(TAG, "onServiceSwitchChanged: 服务总开关状态=" + isChecked); toggleServiceEnableState(isChecked); } @Override public void onChargeReminderProgressChanged(int progress) { - LogUtils.d(TAG, "onChargeReminderProgressChanged: progress=" + progress); - sendRestartRemindThreadMessage(); + LogUtils.d(TAG, "onChargeReminderProgressChanged: 充电提醒阈值=" + progress); + notifyServiceAppConfigChange(); } @Override public void onUsageReminderProgressChanged(int progress) { - LogUtils.d(TAG, "onUsageReminderProgressChanged: progress=" + progress); - sendRestartRemindThreadMessage(); + LogUtils.d(TAG, "onUsageReminderProgressChanged: 耗电提醒阈值=" + progress); + notifyServiceAppConfigChange(); } } diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/ClearRecordActivity.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/ClearRecordActivity.java index efe148b..827813a 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/ClearRecordActivity.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/ClearRecordActivity.java @@ -70,7 +70,7 @@ public class ClearRecordActivity extends WinBoLLActivity implements IWinBoLLActi @Override public void onOHPCommit() { mApplication.clearBatteryHistory(); - sendBroadcast(new Intent(ControlCenterServiceReceiver.ACTION_UPDATE_SERVICENOTIFICATION)); + sendBroadcast(new Intent(ControlCenterServiceReceiver.ACTION_UPDATE_FOREGROUND_NOTIFICATION)); initRecordText(); String szMSG = "The APP battery record is cleaned."; LogUtils.d(TAG, szMSG); diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/handlers/ControlCenterServiceHandler.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/handlers/ControlCenterServiceHandler.java index 02be2dd..8724c47 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/handlers/ControlCenterServiceHandler.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/handlers/ControlCenterServiceHandler.java @@ -2,27 +2,38 @@ package cc.winboll.studio.powerbell.handlers; import android.os.Handler; import android.os.Message; -import java.lang.ref.WeakReference; import cc.winboll.studio.libappbase.LogUtils; -import cc.winboll.studio.powerbell.services.ControlCenterService; import cc.winboll.studio.powerbell.models.NotificationMessage; +import cc.winboll.studio.powerbell.services.ControlCenterService; +import java.lang.ref.WeakReference; /** * @Author ZhanGSKen&豆包大模型 - * @Date 2025/12/17 13:41 - * @Describe 服务通信Handler:弱引用持有服务,避免内存泄漏,通知格式优化为 (+/-)(当前电量)(充电状态) + * @Date 2025/12/19 20:17 + * @Describe 服务通信Handler + * 功能:处理电量提醒消息,构建并发送标准化通知 + * 特性:弱引用防泄漏、参数严格校验、通知格式统一 + * 适配:Java7 | API30 | 小米手机 */ public class ControlCenterServiceHandler extends Handler { - // ================================== 静态常量(置顶统一管理,清晰区分消息类型)================================= + // ================================== 静态常量区(置顶归类,消除魔法值)================================= public static final String TAG = "ControlCenterServiceHandler"; - public static final int MSG_REMIND_TEXT = 1001; // 电量提醒消息(+充电/-耗电) + public static final int MSG_REMIND_TEXT = 1001; // 电量提醒消息标识 - // ================================== 成员变量(弱引用服务,杜绝内存泄漏)================================= + // 提醒类型常量 + private static final String REMIND_TYPE_CHARGE = "+"; + private static final String REMIND_TYPE_USAGE = "-"; + + // 电量范围常量 + private static final int BATTERY_LEVEL_MIN = 0; + private static final int BATTERY_LEVEL_MAX = 100; + + // ================================== 成员变量区(弱引用防泄漏,final保证不可变)================================= private final WeakReference mwrControlCenterService; // ================================== 构造方法(强制传入服务,初始化弱引用)================================= public ControlCenterServiceHandler(ControlCenterService service) { - LogUtils.d(TAG, "初始化Handler,绑定服务实例:" + (service != null ? service.getClass().getSimpleName() : "null")); + LogUtils.d(TAG, "构造Handler | service=" + (service != null ? service.getClass().getSimpleName() : "null")); this.mwrControlCenterService = new WeakReference<>(service); } @@ -30,75 +41,73 @@ public class ControlCenterServiceHandler extends Handler { @Override public void handleMessage(Message msg) { super.handleMessage(msg); - // 解析线程传递的完整数据:obj=提醒类型(+/-),arg1=当前电量,arg2=充电状态(1=充电中,0=未充电) + // 解析消息参数:obj=提醒类型(+/-),arg1=当前电量,arg2=充电状态(1=充电/0=未充电) String remindType = (msg.obj != null) ? (String) msg.obj : ""; int currentBattery = msg.arg1; boolean isCharging = msg.arg2 == 1; - LogUtils.d(TAG, "接收消息,what:" + msg.what + ",类型:" + remindType + ",电量:" + currentBattery + ",充电状态:" + isCharging); - // 弱引用获取服务,避免持有强引用导致内存泄漏 + LogUtils.d(TAG, "接收消息 | what=" + msg.what + " | type=" + remindType + " | battery=" + currentBattery + " | isCharging=" + isCharging); + + // 弱引用获取服务,避免内存泄漏 ControlCenterService service = mwrControlCenterService.get(); if (service == null) { - LogUtils.e(TAG, "服务实例已回收,消息处理失败"); + LogUtils.e(TAG, "服务实例已回收,终止消息处理"); return; } - // 按消息类型分发处理,避免逻辑冗余 + // 按消息类型分发处理 switch (msg.what) { case MSG_REMIND_TEXT: handleRemindMessage(service, remindType, currentBattery, isCharging); break; default: - LogUtils.w(TAG, "未知消息类型,what:" + msg.what); + LogUtils.w(TAG, "未知消息类型 | what=" + msg.what); break; } } - // ================================== 业务辅助方法(重构通知内容,格式:(+/-)(当前电量)(充电状态))================================= + // ================================== 业务辅助方法(构建通知并发送,全链路参数校验)================================= /** - * 处理电量提醒消息,构建带电量+充电状态的通知模型 - * @param service 服务实例(非空,已前置校验) - * @param remindType 提醒类型(+:充电提醒,-:耗电提醒) - * @param currentBattery 当前电量(0-100) - * @param isCharging 充电状态(true=充电中,false=未充电) + * 处理电量提醒消息,构建带电量+充电状态的通知并发送 + * @param service 控制中心服务实例(已校验非空) + * @param remindType 提醒类型(+充电/-耗电) + * @param currentBattery 当前电量(0-100) + * @param isCharging 充电状态 */ private void handleRemindMessage(ControlCenterService service, String remindType, int currentBattery, boolean isCharging) { - LogUtils.d(TAG, "开始处理提醒消息,类型:" + remindType + ",电量:" + currentBattery + ",充电状态:" + isCharging); + LogUtils.d(TAG, "处理提醒消息 | type=" + remindType + " | battery=" + currentBattery + " | isCharging=" + isCharging); - // 1. 前置校验:通知工具类+提醒类型+电量有效性 + // 1. 前置校验:通知工具类+参数有效性 if (service.getNotificationManager() == null) { LogUtils.e(TAG, "通知管理工具类为空,无法发送提醒"); return; } - if (!"+".equals(remindType) && !"-".equals(remindType)) { - LogUtils.w(TAG, "无效提醒类型,跳过发送:" + remindType); + if (!REMIND_TYPE_CHARGE.equals(remindType) && !REMIND_TYPE_USAGE.equals(remindType)) { + LogUtils.w(TAG, "无效提醒类型 | type=" + remindType); return; } - if (currentBattery < 0 || currentBattery > 100) { - LogUtils.w(TAG, "无效当前电量,跳过发送:" + currentBattery); + if (currentBattery < BATTERY_LEVEL_MIN || currentBattery > BATTERY_LEVEL_MAX) { + LogUtils.w(TAG, "无效电量值 | battery=" + currentBattery + ",需在0-100范围内"); return; } - // 2. 构建通知模型,按格式拼接内容(核心优化) + // 2. 构建通知模型,使用String.format统一格式 NotificationMessage remindMsg = new NotificationMessage(); - String chargeStateDesc = isCharging ? "充电中" : "未充电"; // 充电状态文字描述 - if ("+".equals(remindType)) { - // 充电提醒:格式 (+)(当前电量)(充电状态) + String chargeStateDesc = isCharging ? "充电中" : "未充电"; + if (REMIND_TYPE_CHARGE.equals(remindType)) { remindMsg.setTitle("充电提醒"); - remindMsg.setContent("(+) 当前电量" + currentBattery + "%," + chargeStateDesc + ",已达标建议及时断电,保护电池寿命~"); + remindMsg.setContent(String.format("(+) 当前电量%d%%,%s,已达标建议及时断电,保护电池寿命~", currentBattery, chargeStateDesc)); remindMsg.setRemindMSG("charge_remind"); - LogUtils.d(TAG, "构建充电提醒通知,内容:" + remindMsg.getContent()); - } else if ("-".equals(remindType)) { - // 耗电提醒:格式 (-)(当前电量)(充电状态) + } else { remindMsg.setTitle("耗电提醒"); - remindMsg.setContent("(-) 当前电量" + currentBattery + "%," + chargeStateDesc + ",已偏低建议及时充电,避免设备关机~"); + remindMsg.setContent(String.format("(-) 当前电量%d%%,%s,已偏低建议及时充电,避免设备关机~", currentBattery, chargeStateDesc)); remindMsg.setRemindMSG("usage_remind"); - LogUtils.d(TAG, "构建耗电提醒通知,内容:" + remindMsg.getContent()); } + LogUtils.d(TAG, "构建通知完成 | title=" + remindMsg.getTitle() + " | content=" + remindMsg.getContent()); - // 3. 调用服务工具类发送通知,复用现有逻辑 + // 3. 调用工具类发送通知 service.getNotificationManager().showRemindNotification(service, remindMsg); - LogUtils.d(TAG, "提醒通知发送完成,标题:" + remindMsg.getTitle() + ",完整内容:" + remindMsg.getContent()); + LogUtils.d(TAG, "提醒通知发送成功"); } } 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 f8d2fd4..2210347 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 @@ -14,34 +14,38 @@ import cc.winboll.studio.powerbell.utils.NotificationManagerUtils; import java.lang.ref.WeakReference; /** - * 控制中心广播接收器 - * 功能:监听电池状态变化、通知更新、线程启动指令 - * 适配:Java7 | API30 | 小米手机 | 内存泄漏防护 + * @Author ZhanGSKen&豆包大模型 + * @Date 2025/12/19 20:23 + * @Describe 控制中心广播接收器 + * 功能:监听电池状态变化、前台通知更新、配置变更指令 + * 适配:Java7 | API30 | 内存泄漏防护 | 多线程状态同步 */ public class ControlCenterServiceReceiver extends BroadcastReceiver { // ================================== 静态常量区(置顶归类,消除魔法值)================================= public static final String TAG = ControlCenterServiceReceiver.class.getSimpleName(); // 广播Action常量(带包名前缀防冲突) - public static final String ACTION_UPDATE_SERVICENOTIFICATION = "cc.winboll.studio.powerbell.action.UPDATE_SERVICENOTIFICATION"; - public static final String ACTION_START_REMINDTHREAD = "cc.winboll.studio.powerbell.action.START_REMINDTHREAD"; + public static final String ACTION_UPDATE_FOREGROUND_NOTIFICATION = "cc.winboll.studio.powerbell.action.ACTION_UPDATE_SERVICE_FOREGROUND_NOTIFICATION"; + public static final String ACTION_APPCONFIG_CHANGED = "cc.winboll.studio.powerbell.action.ACTION_START_REMIND__NOTIFICATION"; public static final String EXTRA_APP_CONFIG_BEAN = "extra_app_config_bean"; - // 广播优先级常量 + // 广播优先级与电量范围常量 private static final int BROADCAST_PRIORITY = IntentFilter.SYSTEM_HIGH_PRIORITY - 10; + private static final int BATTERY_LEVEL_MIN = 0; + private static final int BATTERY_LEVEL_MAX = 100; // ================================== 成员变量区(弱引用防泄漏,volatile保线程安全)================================= private WeakReference mwrControlCenterService; - private static volatile int sLastBatteryLevel = -1; - private static volatile boolean sIsCharging = false; + private static volatile int sLastBatteryLevel = -1; // 上次电量(多线程可见) + private static volatile boolean sIsCharging = false; // 上次充电状态(多线程可见) - // ================================== 构造方法(初始化弱引用,避免内存泄漏)================================= + // ================================== 构造方法(初始化弱引用,避免服务强引用泄漏)================================= public ControlCenterServiceReceiver(ControlCenterService service) { - LogUtils.d(TAG, "constructor: 初始化广播接收器 | service=" + service); + LogUtils.d(TAG, "构造接收器 | service=" + (service != null ? service.getClass().getSimpleName() : "null")); this.mwrControlCenterService = new WeakReference<>(service); } - // ================================== 广播核心接收逻辑(入口方法,分Action处理)================================= + // ================================== 广播核心接收逻辑(入口方法,分Action分发处理)================================= @Override public void onReceive(Context context, Intent intent) { LogUtils.d(TAG, "onReceive: 接收广播 | context=" + context + " | intent=" + intent + " | action=" + (intent != null ? intent.getAction() : "null")); @@ -63,14 +67,14 @@ public class ControlCenterServiceReceiver extends BroadcastReceiver { // 分Action处理业务逻辑 String action = intent.getAction(); switch (action) { - case ACTION_UPDATE_SERVICENOTIFICATION: - handleUpdateServiceNotification(service); - break; case Intent.ACTION_BATTERY_CHANGED: - handleBatteryStateChanged(context, service, intent); + handleBatteryStateChanged(service, intent); break; - case ACTION_START_REMINDTHREAD: - LogUtils.d(TAG, "onReceive: ACTION_START_REMINDTHREAD 逻辑待实现"); + case ACTION_UPDATE_FOREGROUND_NOTIFICATION: + handleUpdateForegroundNotification(service); + break; + case ACTION_APPCONFIG_CHANGED: + handleNotifyAppConfigUpdate(service); break; default: LogUtils.w(TAG, "onReceive: 未知Action=" + action); @@ -79,44 +83,20 @@ public class ControlCenterServiceReceiver extends BroadcastReceiver { LogUtils.d(TAG, "onReceive: 广播处理完成"); } - // ================================== 业务逻辑方法(按功能拆分,强化容错)================================= - /** - * 处理前台服务通知更新 - * @param service 控制中心服务实例 - */ - private void handleUpdateServiceNotification(ControlCenterService service) { - LogUtils.d(TAG, "handleUpdateServiceNotification: 执行通知更新 | service=" + service); - try { - NotificationManagerUtils notifyUtils = service.getNotificationManager(); - NotificationMessage notifyMsg = service.getForegroundNotifyMsg(); - - // 非空校验+兜底重建 - if (notifyUtils == null || notifyMsg == null) { - LogUtils.e(TAG, "handleUpdateServiceNotification: 通知工具类或消息为空"); - return; - } - - notifyUtils.updateForegroundServiceNotify(notifyMsg); - LogUtils.d(TAG, "handleUpdateServiceNotification: 通知更新成功"); - } catch (Exception e) { - LogUtils.e(TAG, "handleUpdateServiceNotification: 通知更新失败", e); - } - } - + // ================================== 业务处理方法(按功能拆分,强化容错与日志)================================= /** * 处理电池状态变化广播 - * @param context 上下文 * @param service 控制中心服务实例 - * @param intent 广播意图 + * @param intent 电池状态广播意图 */ - private void handleBatteryStateChanged(Context context, ControlCenterService service, Intent intent) { - LogUtils.d(TAG, "handleBatteryStateChanged: 处理电池状态变化 | context=" + context + " | service=" + service); + private void handleBatteryStateChanged(ControlCenterService service, Intent intent) { + LogUtils.d(TAG, "handleBatteryStateChanged: 解析电池状态 | service=" + service); try { - // 1. 获取并校验当前电池状态 - boolean currentCharging = BatteryUtils.isCharging(context); - int currentBatteryLevel = BatteryUtils.getCurrentBattery(context); - currentBatteryLevel = Math.min(Math.max(currentBatteryLevel, 0), 100); - LogUtils.d(TAG, "handleBatteryStateChanged: 当前状态 | 充电=" + currentCharging + " | 电量=" + currentBatteryLevel); + // 1. 解析并校验当前电池状态 + boolean currentCharging = BatteryUtils.isCharging(intent); + int currentBatteryLevel = BatteryUtils.getCurrentBatteryLevel(intent); + currentBatteryLevel = Math.min(Math.max(currentBatteryLevel, BATTERY_LEVEL_MIN), BATTERY_LEVEL_MAX); + LogUtils.d(TAG, "handleBatteryStateChanged: 当前状态 | 充电=" + currentCharging + " | 电量=" + currentBatteryLevel + "%"); // 2. 状态无变化则跳过,减少无效运算 if (currentCharging == sIsCharging && currentBatteryLevel == sLastBatteryLevel) { @@ -124,8 +104,8 @@ public class ControlCenterServiceReceiver extends BroadcastReceiver { return; } - // 3. 加载最新配置(多级兜底) - AppConfigBean latestConfig = loadLatestConfig(context); + // 3. 加载最新配置(三级兜底:本地配置→服务内存配置→默认配置) + AppConfigBean latestConfig = loadLatestConfig(service); if (latestConfig == null) { latestConfig = service.getCurrentConfigBean(); if (latestConfig == null) { @@ -134,29 +114,80 @@ public class ControlCenterServiceReceiver extends BroadcastReceiver { } } - // 4. 同步电池状态到配置,更新服务与线程 + // 4. 同步电池状态到配置,通知服务更新线程 latestConfig.setCurrentBatteryValue(currentBatteryLevel); latestConfig.setIsCharging(currentCharging); service.notifyAppConfigUpdate(latestConfig); - // 5. 缓存最新状态,确保多线程可见 + // 5. 更新静态缓存状态,保证多线程可见 sIsCharging = currentCharging; sLastBatteryLevel = currentBatteryLevel; LogUtils.d(TAG, "handleBatteryStateChanged: 电池状态处理成功"); } catch (Exception e) { - LogUtils.e(TAG, "handleBatteryStateChanged: 电池状态处理失败", e); + LogUtils.e(TAG, "handleBatteryStateChanged: 处理失败", e); } } - // ================================== 内部辅助方法(拆分通用逻辑,统一管理)================================= + /** + * 处理配置变更通知,同步缓存状态到配置 + * @param service 控制中心服务实例 + */ + private void handleNotifyAppConfigUpdate(ControlCenterService service) { + LogUtils.d(TAG, "handleNotifyAppConfigUpdate: 同步缓存状态到配置 | service=" + service); + try { + // 加载最新配置(三级兜底) + AppConfigBean latestConfig = loadLatestConfig(service); + if (latestConfig == null) { + latestConfig = service.getCurrentConfigBean(); + if (latestConfig == null) { + latestConfig = new AppConfigBean(); + LogUtils.w(TAG, "handleNotifyAppConfigUpdate: 配置为空,使用默认配置"); + } + } + + // 同步缓存的电池状态到配置 + latestConfig.setCurrentBatteryValue(sLastBatteryLevel); + latestConfig.setIsCharging(sIsCharging); + service.notifyAppConfigUpdate(latestConfig); + + LogUtils.d(TAG, "handleNotifyAppConfigUpdate: 配置同步成功 | 缓存电量=" + sLastBatteryLevel + "% | 充电状态=" + sIsCharging); + } catch (Exception e) { + LogUtils.e(TAG, "handleNotifyAppConfigUpdate: 处理失败", e); + } + } + + /** + * 处理前台服务通知更新 + * @param service 控制中心服务实例 + */ + private void handleUpdateForegroundNotification(ControlCenterService service) { + LogUtils.d(TAG, "handleUpdateForegroundNotification: 更新前台通知 | service=" + service); + try { + NotificationManagerUtils notifyUtils = service.getNotificationManager(); + NotificationMessage notifyMsg = service.getForegroundNotifyMsg(); + + // 非空校验,避免空指针 + if (notifyUtils == null || notifyMsg == null) { + LogUtils.e(TAG, "handleUpdateForegroundNotification: 通知工具类或消息为空"); + return; + } + + notifyUtils.updateForegroundServiceNotify(notifyMsg); + LogUtils.d(TAG, "handleUpdateForegroundNotification: 前台通知更新成功"); + } catch (Exception e) { + LogUtils.e(TAG, "handleUpdateForegroundNotification: 处理失败", e); + } + } + + // ================================== 内部辅助方法(通用逻辑拆分,统一管理)================================= /** * 加载最新应用配置 * @param context 上下文 * @return 最新配置实例,失败返回null */ private AppConfigBean loadLatestConfig(Context context) { - LogUtils.d(TAG, "loadLatestConfig: 加载最新配置 | context=" + context); + LogUtils.d(TAG, "loadLatestConfig: 读取本地配置 | context=" + context); try { if (context == null) { LogUtils.e(TAG, "loadLatestConfig: 上下文为空"); @@ -170,10 +201,10 @@ public class ControlCenterServiceReceiver extends BroadcastReceiver { } configUtils.reloadAllConfig(); - LogUtils.d(TAG, "loadLatestConfig: 配置加载成功"); + LogUtils.d(TAG, "loadLatestConfig: 本地配置加载成功"); return configUtils.mAppConfigBean; } catch (Exception e) { - LogUtils.e(TAG, "loadLatestConfig: 配置加载失败", e); + LogUtils.e(TAG, "loadLatestConfig: 加载失败", e); return null; } } @@ -184,7 +215,7 @@ public class ControlCenterServiceReceiver extends BroadcastReceiver { * @param context 上下文 */ public void registerAction(Context context) { - LogUtils.d(TAG, "registerAction: 注册广播 | context=" + context); + LogUtils.d(TAG, "registerAction: 注册广播接收器 | context=" + context); if (context == null) { LogUtils.e(TAG, "registerAction: 上下文为空,注册失败"); return; @@ -195,15 +226,15 @@ public class ControlCenterServiceReceiver extends BroadcastReceiver { unregisterAction(context); IntentFilter filter = new IntentFilter(); - filter.addAction(ACTION_UPDATE_SERVICENOTIFICATION); - filter.addAction(ACTION_START_REMINDTHREAD); filter.addAction(Intent.ACTION_BATTERY_CHANGED); + filter.addAction(ACTION_UPDATE_FOREGROUND_NOTIFICATION); + filter.addAction(ACTION_APPCONFIG_CHANGED); filter.setPriority(BROADCAST_PRIORITY); context.registerReceiver(this, filter); LogUtils.d(TAG, "registerAction: 广播注册成功"); } catch (Exception e) { - LogUtils.e(TAG, "registerAction: 广播注册失败", e); + LogUtils.e(TAG, "registerAction: 注册失败", e); } } @@ -212,7 +243,7 @@ public class ControlCenterServiceReceiver extends BroadcastReceiver { * @param context 上下文 */ public void unregisterAction(Context context) { - LogUtils.d(TAG, "unregisterAction: 注销广播 | context=" + context); + LogUtils.d(TAG, "unregisterAction: 注销广播接收器 | context=" + context); if (context == null) { LogUtils.e(TAG, "unregisterAction: 上下文为空,注销失败"); return; @@ -224,7 +255,7 @@ public class ControlCenterServiceReceiver extends BroadcastReceiver { } catch (IllegalArgumentException e) { LogUtils.w(TAG, "unregisterAction: 广播未注册,跳过注销"); } catch (Exception e) { - LogUtils.e(TAG, "unregisterAction: 广播注销失败", e); + LogUtils.e(TAG, "unregisterAction: 注销失败", e); } } @@ -234,7 +265,7 @@ public class ControlCenterServiceReceiver extends BroadcastReceiver { */ public void release() { LogUtils.d(TAG, "release: 释放广播接收器资源"); - // 清空弱引用 + // 清空弱引用,帮助GC回收 if (mwrControlCenterService != null) { mwrControlCenterService.clear(); mwrControlCenterService = null; diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/receivers/GlobalApplicationReceiver.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/receivers/GlobalApplicationReceiver.java index c28bfc8..761edef 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/receivers/GlobalApplicationReceiver.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/receivers/GlobalApplicationReceiver.java @@ -10,35 +10,49 @@ import cc.winboll.studio.powerbell.MainActivity; import cc.winboll.studio.powerbell.utils.AppConfigUtils; import cc.winboll.studio.powerbell.utils.BatteryUtils; +/** + * @Author ZhanGSKen&豆包大模型 + * @Date 2025/12/19 20:13 + * @Describe 全局应用广播接收器 + * 功能:监听系统电池状态变化,同步状态到配置工具类,通知页面更新 + * 适配:Java7 | API30 | 内存泄漏防护 + */ public class GlobalApplicationReceiver extends BroadcastReceiver { - + // ================================== 静态常量区(置顶归类,消除魔法值)================================= public static final String TAG = "GlobalApplicationReceiver"; + private static final int BATTERY_LEVEL_MIN = 0; + private static final int BATTERY_LEVEL_MAX = 100; - private AppConfigUtils mAppConfigUtils; + // ================================== 静态成员变量(线程安全,volatile保证多线程可见性)================================= + private static volatile int sLastBatteryLevel = -1; // 历史电量(0-100) + private static volatile boolean sLastIsCharging = false; // 历史充电状态 + + // ================================== 成员变量区(按功能分层)================================= private App mGlobalApplication; - // 存储历史电池状态,用于判断变化(优化命名,明确语义) - private static volatile int sLastBatteryLevel = -1; // 历史电量(0-100) - private static volatile boolean sLastIsCharging = false; // 历史充电状态 - // 当前Receiver实例(优化命名,避免歧义) + private AppConfigUtils mAppConfigUtils; private GlobalApplicationReceiver mCurrentReceiver; - // 构造方法(强化参数校验,避免空指针) + // ================================== 构造方法(强化参数校验,初始化核心依赖)================================= public GlobalApplicationReceiver(App globalApplication) { + LogUtils.d(TAG, "构造接收器 | App=" + globalApplication); if (globalApplication == null) { - LogUtils.e(TAG, "GlobalApplicationReceiver: App instance is null"); + LogUtils.e(TAG, "构造失败:App实例为空"); throw new IllegalArgumentException("App cannot be null"); } this.mCurrentReceiver = this; this.mGlobalApplication = globalApplication; this.mAppConfigUtils = App.getAppConfigUtils(mGlobalApplication); + LogUtils.d(TAG, "构造完成:AppConfigUtils=" + mAppConfigUtils); } + // ================================== 广播核心接收逻辑(入口方法,过滤电池状态广播)================================= @Override public void onReceive(Context context, Intent intent) { - LogUtils.d(TAG, "onReceive: enter, action=" + intent.getAction()); - // 双重空指针防护(context/intent/action 均校验) + LogUtils.d(TAG, "onReceive: 接收广播 | context=" + context + " | intent=" + intent + " | action=" + (intent != null ? intent.getAction() : "null")); + + // 基础参数校验 if (context == null || intent == null || intent.getAction() == null) { - LogUtils.e(TAG, "onReceive: invalid params (context/intent is null)"); + LogUtils.e(TAG, "onReceive: 参数无效,终止处理"); return; } @@ -46,99 +60,119 @@ public class GlobalApplicationReceiver extends BroadcastReceiver { if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) { handleBatteryStateChanged(context, intent); } - LogUtils.d(TAG, "onReceive: exit"); + + LogUtils.d(TAG, "onReceive: 广播处理完成"); } + // ================================== 业务逻辑方法(处理电池状态变化,同步配置+通知页面)================================= /** - * 处理电池状态变化(核心逻辑:复用 BatteryUtils,优化状态同步) + * 处理电池状态变化广播 + * @param context 上下文 + * @param intent 电池状态广播意图 */ private void handleBatteryStateChanged(Context context, Intent intent) { - // 1. 用 BatteryUtils 解析当前电池状态(复用工具类,避免重复代码) - boolean currentIsCharging = BatteryUtils.isCharging(context); // 调用工具类判断充电状态 - int currentBatteryLevel = BatteryUtils.getCurrentBattery(context); // 调用工具类获取电量(0-100) - currentBatteryLevel = Math.min(Math.max(currentBatteryLevel, 0), 100); // 二次校验,确保范围有效 + LogUtils.d(TAG, "handleBatteryStateChanged: 解析电池状态 | intent=" + intent); + // 1. 解析当前电池状态(复用工具类,二次校验电量范围) + boolean currentIsCharging = BatteryUtils.isCharging(intent); + int currentBatteryLevel = BatteryUtils.getCurrentBatteryLevel(intent); + currentBatteryLevel = Math.min(Math.max(currentBatteryLevel, BATTERY_LEVEL_MIN), BATTERY_LEVEL_MAX); + LogUtils.d(TAG, "handleBatteryStateChanged: 当前状态 | 充电=" + currentIsCharging + " | 电量=" + currentBatteryLevel + "%"); - LogUtils.d(TAG, "handleBatteryStateChanged: current - charging=" + currentIsCharging + ", level=" + currentBatteryLevel); - - // 2. 状态无变化,直接跳过(避免无效运算) + // 2. 状态无变化则跳过,减少无效运算 if (currentIsCharging == sLastIsCharging && currentBatteryLevel == sLastBatteryLevel) { - LogUtils.d(TAG, "handleBatteryStateChanged: no state change, skip"); + LogUtils.d(TAG, "handleBatteryStateChanged: 状态无变化,跳过处理"); return; } - // 3. 同步最新状态到配置工具类(确保配置实时更新) + // 3. 同步最新状态到配置工具类 if (mAppConfigUtils != null) { if (currentIsCharging != sLastIsCharging) { - mAppConfigUtils.setCharging(currentIsCharging); // 同步充电状态 + mAppConfigUtils.setCharging(currentIsCharging); + LogUtils.d(TAG, "handleBatteryStateChanged: 同步充电状态 | " + currentIsCharging); } if (currentBatteryLevel != sLastBatteryLevel) { - mAppConfigUtils.setCurrentBatteryValue(currentBatteryLevel); // 同步当前电量 + mAppConfigUtils.setCurrentBatteryValue(currentBatteryLevel); + LogUtils.d(TAG, "handleBatteryStateChanged: 同步电量 | " + currentBatteryLevel + "%"); } } else { - LogUtils.e(TAG, "handleBatteryStateChanged: AppConfigUtils is null, sync failed"); + LogUtils.e(TAG, "handleBatteryStateChanged: AppConfigUtils为空,同步失败"); } - // 4. 电池状态变化后的业务逻辑(保留原有逻辑,强化空指针防护) - // 取消旧提醒(若后续需要启用,可调用 NotificationHelper.cancelRemindNotification(context)) + // 4. 执行状态变化后的业务逻辑 // 记录电量变化时间 if (App.getAppCacheUtils(context) != null) { App.getAppCacheUtils(context).addChangingTime(currentBatteryLevel); + LogUtils.d(TAG, "handleBatteryStateChanged: 记录电量变化时间"); } - // 发送电量更新消息到MainActivity + // 通知MainActivity更新电量 MainActivity.sendCurrentBatteryValueMessage(currentBatteryLevel); + LogUtils.d(TAG, "handleBatteryStateChanged: 发送电量更新消息到MainActivity"); - // 5. 更新历史状态缓存(volatile 保证多线程可见性) + // 5. 更新历史状态缓存 sLastIsCharging = currentIsCharging; sLastBatteryLevel = currentBatteryLevel; - LogUtils.d(TAG, "handleBatteryStateChanged: sync success, update last state"); + LogUtils.d(TAG, "handleBatteryStateChanged: 更新历史状态完成"); } - // 注册广播(优化容错,避免重复注册) + // ================================== 广播注册/注销(强化容错,避免重复操作)================================= + /** + * 注册广播接收器 + */ public void registerAction() { + LogUtils.d(TAG, "registerAction: 注册广播"); if (mGlobalApplication == null || mCurrentReceiver == null) { - LogUtils.e(TAG, "registerAction: App/receiver is null, register failed"); + LogUtils.e(TAG, "注册失败:App或Receiver实例为空"); return; } try { - // 先注销再注册,避免重复注册导致异常 + // 先注销再注册,避免重复注册异常 unregisterAction(); IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_BATTERY_CHANGED); mGlobalApplication.registerReceiver(mCurrentReceiver, filter); - LogUtils.d(TAG, "registerAction: broadcast receiver registered success"); + LogUtils.d(TAG, "registerAction: 广播注册成功"); } catch (Exception e) { - LogUtils.e(TAG, "registerAction: register failed", e); + LogUtils.e(TAG, "registerAction: 注册失败", e); } } - // 新增:注销广播(避免内存泄漏,供外部调用) + /** + * 注销广播接收器 + */ public void unregisterAction() { + LogUtils.d(TAG, "unregisterAction: 注销广播"); if (mGlobalApplication == null || mCurrentReceiver == null) { - LogUtils.e(TAG, "unregisterAction: App/receiver is null, unregister failed"); + LogUtils.e(TAG, "注销失败:App或Receiver实例为空"); return; } try { mGlobalApplication.unregisterReceiver(mCurrentReceiver); - LogUtils.d(TAG, "unregisterAction: broadcast receiver unregistered success"); + LogUtils.d(TAG, "unregisterAction: 广播注销成功"); } catch (IllegalArgumentException e) { - LogUtils.w(TAG, "unregisterAction: receiver not registered, skip"); + LogUtils.w(TAG, "unregisterAction: 广播未注册,跳过注销"); } catch (Exception e) { - LogUtils.e(TAG, "unregisterAction: unregister failed", e); + LogUtils.e(TAG, "unregisterAction: 注销失败", e); } } - // 新增:主动释放资源(供App销毁时调用,彻底防泄漏) + // ================================== 资源释放方法(主动释放,彻底避免内存泄漏)================================= + /** + * 释放接收器资源,供App销毁时调用 + */ public void release() { - LogUtils.d(TAG, "release: receiver release resources"); + LogUtils.d(TAG, "release: 释放接收器资源"); + // 注销广播 unregisterAction(); + // 置空引用,帮助GC回收 mGlobalApplication = null; mAppConfigUtils = null; mCurrentReceiver = null; - // 重置静态缓存 + // 重置静态状态缓存 sLastBatteryLevel = -1; sLastIsCharging = false; + LogUtils.d(TAG, "release: 资源释放完成"); } } 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 5314755..1cd0f25 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/services/ControlCenterService.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/services/ControlCenterService.java @@ -21,22 +21,24 @@ import java.io.Serializable; import java.util.List; /** - * 电池提醒核心服务 + * @Author ZhanGSKen&豆包大模型 + * @Date 2025/12/19 20:21 + * @Describe 电池提醒核心服务 * 功能:管理前台服务生命周期、控制提醒线程启停、处理配置更新 * 适配:Java7 | API30 | 前台服务超时防护 | 电池优化忽略引导 - * @Author ZhanGSKen&豆包大模型 - * @Date 2025/12/17 15:48 */ public class ControlCenterService extends Service { // ================================== 静态常量区(置顶归类,消除魔法值)================================= public static final String TAG = "ControlCenterService"; - // 服务指令常量(带包名前缀防冲突) + // 服务指令Action常量(带包名前缀防冲突) 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 static final int SERVICE_RETURN_STICKY = START_STICKY; // ================================== 成员变量区(按功能分层,volatile保证多线程可见性)================================= // 服务控制配置 @@ -46,11 +48,11 @@ public class ControlCenterService extends Service { private NotificationManagerUtils mNotificationManager; private AppConfigBean mCurrentConfigBean; private NotificationMessage mForegroundNotifyMsg; - // 服务状态标记 + // 服务状态标记(volatile保证多线程可见性) private static volatile boolean isServiceRunning; private static volatile boolean mIsDestroyed; - // ================================== 服务生命周期方法(按执行顺序排列)================================= + // ================================== 服务生命周期方法(按执行顺序排列:onCreate→onStartCommand→onBind→onDestroy)================================= @Override public void onCreate() { super.onCreate(); @@ -68,19 +70,25 @@ public class ControlCenterService extends Service { runCoreServiceLogic(); int returnFlag = (mServiceControlBean != null && mServiceControlBean.isEnableService()) - ? START_STICKY + ? SERVICE_RETURN_STICKY : super.onStartCommand(intent, flags, startId); - LogUtils.d(TAG, "onStartCommand: 处理完成 | 返回策略=" + (returnFlag == START_STICKY ? "START_STICKY" : "DEFAULT")); + LogUtils.d(TAG, "onStartCommand: 处理完成 | 返回策略=" + (returnFlag == SERVICE_RETURN_STICKY ? "START_STICKY" : "DEFAULT")); return returnFlag; } + @Override + public IBinder onBind(Intent intent) { + LogUtils.d(TAG, "onBind: 绑定请求 | intent=" + intent); + return null; + } + @Override public void onDestroy() { LogUtils.d(TAG, "onDestroy: 服务销毁流程启动"); super.onDestroy(); - // 资源释放顺序:前台服务 → 线程 → Handler → 通知 → 引用 + // 资源释放顺序:前台服务 → 线程 → Handler → 通知 → 引用(避免内存泄漏) stopForegroundService(); RemindThread.stopRemindThreadSafely(); destroyHandler(); @@ -97,12 +105,6 @@ public class ControlCenterService extends Service { LogUtils.d(TAG, "onDestroy: 服务销毁完成"); } - @Override - public IBinder onBind(Intent intent) { - LogUtils.d(TAG, "onBind: 绑定请求 | intent=" + intent); - return null; - } - // ================================== 核心业务逻辑(独立抽取,统一调用)================================= /** * 服务核心运行逻辑,在onCreate/onStartCommand复用 @@ -133,7 +135,7 @@ public class ControlCenterService extends Service { } } - // ================================== 前台通知管理(优先执行,防止5秒超时)================================= + // ================================== 前台通知管理(优先执行,防止API26+前台服务5秒超时)================================= /** * 立即初始化前台通知,防止API26+前台服务超时异常 * @return true=成功 false=失败 @@ -210,7 +212,7 @@ public class ControlCenterService extends Service { } } - // ================================== 业务组件初始化与销毁================================= + // ================================== 业务组件初始化与销毁(Handler/线程等)================================= /** * 初始化Handler等核心业务组件 */ @@ -312,7 +314,7 @@ public class ControlCenterService extends Service { /** * 外部更新配置并触发线程重启 - * @param context 上下文 + * @param context 上下文 * @param configBean 新配置 */ public static void updateStatus(Context context, AppConfigBean configBean) { 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 5904bb0..c0c55ed 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,10 +8,11 @@ import cc.winboll.studio.powerbell.models.AppConfigBean; import java.lang.ref.WeakReference; /** - * 提醒线程(单例模式) - * 功能:统一管理充电/耗电提醒逻辑,发送提醒时携带当前电量+充电状态 - * 适配:Java7 | API30 | 小米手机 - * 特性:线程安全、内存泄漏防护、配置参数校验 + * @Author ZhanGSKen&豆包大模型 + * @Date 2025/12/19 20:28 + * @Describe 提醒线程(线程安全单例) + * 功能:管理充电/耗电提醒逻辑,触发条件时向Handler发送提醒消息 + * 适配:Java7 | API30 | 内存泄漏防护 | 多线程状态同步 * 对外接口:{@link #startRemindThread(Context, ControlCenterServiceHandler, AppConfigBean)}、{@link #stopRemindThreadSafely()} */ public class RemindThread extends Thread { @@ -26,19 +27,19 @@ public class RemindThread extends Thread { // 状态常量 private static final int INVALID_BATTERY_VALUE = -1; - // ================================== 单例核心(线程安全,双重校验锁)================================= + // ================================== 单例核心(双重校验锁,保证线程安全)================================= private static volatile RemindThread sInstance; // ================================== 成员变量区(按功能分层,volatile保证多线程可见性)================================= - // 弱引用依赖(防内存泄漏) + // 弱引用依赖(防内存泄漏,ApplicationContext 避免 Activity 引用) private Context mContext; private WeakReference mwrControlCenterServiceHandler; - // 线程状态标记 + // 线程状态标记(volatile 确保多线程可见) private volatile boolean isExist; private volatile boolean isReminding; - // 业务配置参数 + // 业务配置参数(volatile 确保配置变更实时生效) private volatile boolean isEnableChargeReminder; private volatile boolean isEnableUsageReminder; private volatile long sleepTime; @@ -47,60 +48,57 @@ public class RemindThread extends Thread { private volatile int quantityOfElectricity; private volatile boolean isCharging; - // 并发安全锁 + // 并发安全锁(保护线程状态变更) private final Object mLock = new Object(); // ================================== 私有构造器(单例专用,禁止外部实例化)================================= private RemindThread(Context context, ControlCenterServiceHandler handler) { - LogUtils.d(TAG, "构造线程实例 | threadName=" + getName() + " | threadId=" + getId()); + LogUtils.d(TAG, "创建线程实例 | threadId=" + getId() + " | threadName=" + getName()); this.mContext = context.getApplicationContext(); this.mwrControlCenterServiceHandler = new WeakReference<>(handler); resetThreadStateInternal(); } - // ================================== 单例获取方法(核心,统一管理单例创建)================================= + // ================================== 单例获取方法(核心,双重校验锁)================================= /** - * 私有单例获取方法,双重校验锁保证线程安全 - * @param context 上下文 - * @param handler 服务处理器 + * 获取单例实例,保证全局唯一 + * @param context 上下文(使用ApplicationContext) + * @param handler 服务处理器 * @return 唯一的 RemindThread 实例 */ private static RemindThread getInstance(Context context, ControlCenterServiceHandler handler) { - LogUtils.d(TAG, "getInstance: 获取单例 | context=" + context + " | handler=" + handler); if (sInstance == null) { synchronized (RemindThread.class) { if (sInstance == null) { sInstance = new RemindThread(context, handler); - LogUtils.d(TAG, "getInstance: 新建单例成功 | threadId=" + sInstance.getId()); + LogUtils.d(TAG, "单例创建成功 | threadId=" + sInstance.getId()); } } } return sInstance; } - // ================================== 对外公开静态接口(全部基于单例实现)================================= + // ================================== 对外公开静态接口(基于单例,统一线程管理)================================= /** - * 启动提醒线程(基于单例操作,确保全局唯一) + * 启动提醒线程,同步最新配置 * @param context 上下文(非空) * @param handler 服务处理器(非空) * @param config 应用配置Bean(非空) - * @return true: isReminding为真/线程启动成功;false: 入参非法/启动失败 + * @return true: 启动成功/已在运行;false: 入参非法 */ public static boolean startRemindThread(Context context, ControlCenterServiceHandler handler, AppConfigBean config) { - LogUtils.d(TAG, "startRemindThread: 调用 | context=" + context + " | handler=" + handler + " | config=" + config); - // 入参校验 + LogUtils.d(TAG, "请求启动线程 | context=" + context + " | handler=" + handler + " | config=" + config); + // 入参严格校验 if (context == null || handler == null || config == null) { - LogUtils.e(TAG, "startRemindThread: 入参为空,启动失败"); + LogUtils.e(TAG, "启动失败:入参为空"); return false; } - // 获取单例 RemindThread instance = getInstance(context, handler); - - // 已在提醒状态,同步配置后返回 + // 已在提醒状态,仅同步配置 if (instance.isReminding) { instance.setAppConfigBean(config); - LogUtils.d(TAG, "startRemindThread: 线程已在提醒状态,同步最新配置 | threadId=" + instance.getId()); + LogUtils.d(TAG, "线程已在运行,同步最新配置 | threadId=" + instance.getId()); return true; } @@ -109,28 +107,28 @@ public class RemindThread extends Thread { if (!instance.isRunning()) { instance.isExist = false; instance.start(); - LogUtils.d(TAG, "startRemindThread: 线程启动成功 | threadId=" + instance.getId()); + LogUtils.d(TAG, "线程启动成功 | threadId=" + instance.getId()); return true; } else { - LogUtils.d(TAG, "startRemindThread: 线程已在运行 | threadId=" + instance.getId()); + LogUtils.d(TAG, "线程已在运行状态 | threadId=" + instance.getId()); return false; } } /** - * 安全停止线程(基于单例操作,优雅销毁唯一实例) + * 安全停止线程,优雅销毁单例 */ public static void stopRemindThreadSafely() { - LogUtils.d(TAG, "stopRemindThreadSafely: 调用 | sInstance=" + (sInstance != null)); + LogUtils.d(TAG, "请求安全停止线程 | 单例存在=" + (sInstance != null)); synchronized (RemindThread.class) { if (sInstance == null) { - LogUtils.w(TAG, "stopRemindThreadSafely: 线程实例为空,无需停止"); + LogUtils.w(TAG, "停止失败:线程实例为空"); return; } // 线程未运行,直接销毁 if (!sInstance.isRunning()) { - LogUtils.d(TAG, "stopRemindThreadSafely: 线程未运行,直接销毁 | threadId=" + sInstance.getId()); + LogUtils.d(TAG, "线程未运行,直接销毁 | threadId=" + sInstance.getId()); destroyInstance(); return; } @@ -138,41 +136,39 @@ public class RemindThread extends Thread { // 标记退出,等待线程自然结束 sInstance.isExist = true; sInstance.isReminding = false; - LogUtils.d(TAG, "stopRemindThreadSafely: 标记线程退出 | threadId=" + sInstance.getId()); + LogUtils.d(TAG, "标记线程退出,等待结束 | threadId=" + sInstance.getId()); try { sInstance.join(THREAD_JOIN_TIMEOUT); } catch (InterruptedException e) { Thread.currentThread().interrupt(); - LogUtils.e(TAG, "stopRemindThreadSafely: 等待线程退出被中断", e); + LogUtils.e(TAG, "等待线程退出被中断", e); } - // 销毁单例 + // 销毁单例释放资源 destroyInstance(); - LogUtils.d(TAG, "stopRemindThreadSafely: 线程安全销毁完成"); + LogUtils.d(TAG, "线程安全销毁完成"); } } // ================================== 私有单例管理方法================================= /** - * 销毁单例,安全释放资源 + * 销毁单例,释放所有资源 */ private static void destroyInstance() { - LogUtils.d(TAG, "destroyInstance: 开始销毁单例 | sInstance=" + (sInstance != null)); synchronized (RemindThread.class) { if (sInstance != null) { - // 终止线程并释放资源 sInstance.isExist = true; sInstance.isReminding = false; + // 中断存活线程 if (sInstance.isAlive()) { sInstance.interrupt(); - LogUtils.d(TAG, "destroyInstance: 线程已中断 | threadId=" + sInstance.getId()); + LogUtils.d(TAG, "中断存活线程 | threadId=" + sInstance.getId()); } + // 释放线程内部资源 sInstance.releaseResourcesInternal(); sInstance = null; - LogUtils.d(TAG, "destroyInstance: 单例销毁完成"); - } else { - LogUtils.w(TAG, "destroyInstance: 单例已为空,跳过销毁"); + LogUtils.d(TAG, "单例销毁完成"); } } } @@ -180,74 +176,73 @@ public class RemindThread extends Thread { // ================================== 线程核心运行逻辑================================= @Override public void run() { - LogUtils.d(TAG, "run: 线程启动 | threadId=" + Thread.currentThread().getId() + " | state=" + getState()); + LogUtils.d(TAG, "线程进入运行 | threadId=" + getId() + " | 状态=" + getState()); - // 初始化提醒状态(加锁保护) + // 初始化提醒状态(加锁保护,避免多线程竞争) synchronized (mLock) { if (!isExist && !isReminding) { isReminding = true; - LogUtils.d(TAG, "run: 初始化提醒状态成功 | isReminding=true"); + LogUtils.d(TAG, "提醒状态初始化成功 | isReminding=true"); } else { - LogUtils.d(TAG, "run: 线程退出条件满足 | isExist=" + isExist + " | isReminding=" + isReminding); + LogUtils.d(TAG, "线程退出条件满足 | isExist=" + isExist + " | isReminding=" + isReminding); cleanThreadStateInternal(); return; } } - // 核心检测循环 - LogUtils.d(TAG, "run: 进入电量检测循环 | sleepTime=" + sleepTime + "ms"); + // 核心电量检测循环 + LogUtils.d(TAG, "进入电量检测循环 | 休眠时间=" + sleepTime + "ms"); while (!isExist) { try { // 快速退出判断 if (isExist) break; - // 电量有效性校验 + // 电量有效性校验(非0-100视为无效) if (quantityOfElectricity < 0 || quantityOfElectricity > 100) { - LogUtils.w(TAG, "run: 电量无效,退出循环 | currentBattery=" + quantityOfElectricity); + LogUtils.w(TAG, "电量无效,退出循环 | 当前电量=" + quantityOfElectricity); break; } // 充电提醒触发逻辑 if (isCharging && isEnableChargeReminder && quantityOfElectricity >= chargeReminderValue) { - LogUtils.d(TAG, "run: 触发充电提醒 | battery=" + quantityOfElectricity + " ≥ threshold=" + chargeReminderValue); + LogUtils.d(TAG, "触发充电提醒 | 当前电量=" + quantityOfElectricity + " ≥ 阈值=" + chargeReminderValue); sendNotificationMessageInternal("+", quantityOfElectricity, isCharging); } else if (!isCharging && isEnableUsageReminder && quantityOfElectricity <= usageReminderValue) { - LogUtils.d(TAG, "run: 触发耗电提醒 | battery=" + quantityOfElectricity + " ≤ threshold=" + usageReminderValue); + LogUtils.d(TAG, "触发耗电提醒 | 当前电量=" + quantityOfElectricity + " ≤ 阈值=" + usageReminderValue); sendNotificationMessageInternal("-", quantityOfElectricity, isCharging); } - // 安全休眠 + // 安全休眠,保留中断标记 safeSleepInternal(sleepTime); } catch (Exception e) { - LogUtils.e(TAG, "run: 线程运行异常,休眠重试", e); + LogUtils.e(TAG, "循环运行异常,休眠重试", e); safeSleepInternal(sleepTime); } } // 循环退出,清理状态 cleanThreadStateInternal(); - LogUtils.d(TAG, "run: 线程循环退出 | threadId=" + Thread.currentThread().getId()); + LogUtils.d(TAG, "线程运行结束 | threadId=" + getId()); } // ================================== 内部业务辅助方法================================= /** - * 发送提醒消息(内部方法,弱引用Handler防泄漏) + * 发送提醒消息到Handler(弱引用避免内存泄漏) * @param type 提醒类型:+充电/-耗电 * @param battery 当前电量 * @param isCharging 充电状态 */ private void sendNotificationMessageInternal(String type, int battery, boolean isCharging) { - LogUtils.d(TAG, "sendNotificationMessageInternal: 调用 | type=" + type + " | battery=" + battery + " | isCharging=" + isCharging); - // 前置校验 + // 前置状态校验 if (isExist || !isReminding) { - LogUtils.d(TAG, "sendNotificationMessageInternal: 线程退出或提醒关闭,跳过发送"); + LogUtils.d(TAG, "消息发送跳过:线程已退出或提醒关闭"); return; } - // 获取Handler并发送消息 + // 获取弱引用的Handler ControlCenterServiceHandler handler = mwrControlCenterServiceHandler.get(); if (handler == null) { - LogUtils.w(TAG, "sendNotificationMessageInternal: Handler已回收,发送失败"); + LogUtils.w(TAG, "消息发送失败:Handler已被回收"); return; } @@ -258,23 +253,26 @@ public class RemindThread extends Thread { try { handler.sendMessage(message); - LogUtils.d(TAG, "sendNotificationMessageInternal: 提醒消息发送成功"); + LogUtils.d(TAG, "提醒消息发送成功 | 类型=" + type + " | 电量=" + battery); } catch (Exception e) { - LogUtils.e(TAG, "sendNotificationMessageInternal: 消息发送异常", e); - if (message != null) message.recycle(); + LogUtils.e(TAG, "消息发送异常", e); + // 异常时回收Message,避免内存泄漏 + if (message != null) { + message.recycle(); + } } } /** - * 安全休眠(保留中断标记,确保线程可退出) - * @param millis 休眠时长 + * 安全休眠,响应线程中断 + * @param millis 休眠时长(ms) */ private void safeSleepInternal(long millis) { try { Thread.sleep(millis); } catch (InterruptedException e) { Thread.currentThread().interrupt(); - LogUtils.w(TAG, "safeSleepInternal: 休眠被中断,线程准备退出"); + LogUtils.w(TAG, "休眠被中断,线程准备退出"); } } @@ -282,11 +280,11 @@ public class RemindThread extends Thread { * 重置线程初始状态(构造器专用) */ private void resetThreadStateInternal() { - LogUtils.d(TAG, "resetThreadStateInternal: 重置线程初始状态"); - // 状态标记 + LogUtils.d(TAG, "重置线程初始状态"); + // 状态标记初始化 isExist = false; isReminding = false; - // 配置参数 + // 配置参数初始化 isEnableChargeReminder = false; isEnableUsageReminder = false; sleepTime = DEFAULT_SLEEP_TIME; @@ -297,31 +295,32 @@ public class RemindThread extends Thread { } /** - * 清理线程运行状态(退出循环专用) + * 清理线程运行状态(循环退出时调用) */ private void cleanThreadStateInternal() { - LogUtils.d(TAG, "cleanThreadStateInternal: 清理线程运行状态"); + LogUtils.d(TAG, "清理线程运行状态"); isReminding = false; isExist = true; quantityOfElectricity = INVALID_BATTERY_VALUE; + // 中断当前线程(如果存活) if (isAlive()) { interrupt(); } } /** - * 同步应用配置(参数范围校验,确保有效性) + * 同步应用配置,校验参数有效性 * @param config 应用配置Bean */ public void setAppConfigBean(AppConfigBean config) { - LogUtils.d(TAG, "setAppConfigBean: 调用 | config=" + config); + LogUtils.d(TAG, "同步应用配置 | config=" + config); if (config == null) { - LogUtils.e(TAG, "setAppConfigBean: 配置Bean为空,同步失败"); + LogUtils.e(TAG, "配置同步失败:配置Bean为空"); quantityOfElectricity = INVALID_BATTERY_VALUE; return; } - // 配置参数同步+范围校验 + // 配置参数同步 + 范围校验(确保参数合法) isEnableChargeReminder = config.isEnableChargeReminder(); isEnableUsageReminder = config.isEnableUsageReminder(); chargeReminderValue = Math.min(Math.max(config.getChargeReminderValue(), 0), 100); @@ -332,19 +331,22 @@ public class RemindThread extends Thread { isCharging = config.isCharging(); isReminding = isEnableChargeReminder || isEnableUsageReminder; - LogUtils.d(TAG, "setAppConfigBean: 配置同步完成 | sleepTime=" + sleepTime + "ms | isReminding=" + isReminding + " | currentBattery=" + quantityOfElectricity); + LogUtils.d(TAG, "配置同步完成 | 休眠时间=" + sleepTime + "ms | 提醒开启=" + isReminding + " | 当前电量=" + quantityOfElectricity); } /** - * 释放线程资源(内部方法,防内存泄漏) + * 释放线程内部资源,杜绝内存泄漏 */ private void releaseResourcesInternal() { - LogUtils.d(TAG, "releaseResourcesInternal: 释放线程资源"); + LogUtils.d(TAG, "释放线程内部资源"); + // 释放上下文引用 mContext = null; + // 清空WeakReference if (mwrControlCenterServiceHandler != null) { mwrControlCenterServiceHandler.clear(); mwrControlCenterServiceHandler = null; } + // 清理线程状态 cleanThreadStateInternal(); } @@ -354,13 +356,13 @@ public class RemindThread extends Thread { */ private boolean isRunning() { boolean running = !isExist && isAlive(); - LogUtils.d(TAG, "isRunning: 线程运行状态=" + running + " | isExist=" + isExist + " | isAlive=" + isAlive()); + LogUtils.d(TAG, "线程运行状态判断 | 运行中=" + running + " | 退出标记=" + isExist + " | 存活=" + isAlive()); return running; } // ================================== Getter/Setter(按需开放)================================= public void setIsExist(boolean isExist) { - LogUtils.d(TAG, "setIsExist: 调用 | isExist=" + isExist); + LogUtils.d(TAG, "设置线程退出标记 | isExist=" + isExist); this.isExist = isExist; }