重置通知架构为旧式方法,用线程启动法。过程顺便整理代码。
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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&豆包大模型<zhangsken@qq.com>
|
||||
* @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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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&豆包大模型<zhangsken@qq.com>
|
||||
* @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<ControlCenterService> 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, "提醒通知发送成功");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,34 +14,38 @@ import cc.winboll.studio.powerbell.utils.NotificationManagerUtils;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
* 控制中心广播接收器
|
||||
* 功能:监听电池状态变化、通知更新、线程启动指令
|
||||
* 适配:Java7 | API30 | 小米手机 | 内存泄漏防护
|
||||
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
|
||||
* @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<ControlCenterService> 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;
|
||||
|
||||
@@ -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&豆包大模型<zhangsken@qq.com>
|
||||
* @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: 资源释放完成");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,22 +21,24 @@ import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 电池提醒核心服务
|
||||
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
|
||||
* @Date 2025/12/19 20:21
|
||||
* @Describe 电池提醒核心服务
|
||||
* 功能:管理前台服务生命周期、控制提醒线程启停、处理配置更新
|
||||
* 适配:Java7 | API30 | 前台服务超时防护 | 电池优化忽略引导
|
||||
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
|
||||
* @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) {
|
||||
|
||||
@@ -8,10 +8,11 @@ import cc.winboll.studio.powerbell.models.AppConfigBean;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
* 提醒线程(单例模式)
|
||||
* 功能:统一管理充电/耗电提醒逻辑,发送提醒时携带当前电量+充电状态
|
||||
* 适配:Java7 | API30 | 小米手机
|
||||
* 特性:线程安全、内存泄漏防护、配置参数校验
|
||||
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
|
||||
* @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<ControlCenterServiceHandler> 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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user