源码整理

This commit is contained in:
2025-12-20 13:23:07 +08:00
parent 9c1e9dc75b
commit 23beabe99b
5 changed files with 184 additions and 104 deletions

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Fri Dec 19 19:04:54 GMT 2025
#Sat Dec 20 05:22:35 GMT 2025
stageCount=10
libraryProject=
baseVersion=15.14
publishVersion=15.14.9
buildCount=49
buildCount=51
baseBetaVersion=15.14.10

View File

@@ -20,13 +20,11 @@ import cc.winboll.studio.libaes.utils.DevelopUtils;
import cc.winboll.studio.libaes.utils.WinBoLLActivityManager;
import cc.winboll.studio.libaes.views.ADsBannerView;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.ToastUtils;
import cc.winboll.studio.powerbell.activities.BackgroundSettingsActivity;
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;
@@ -38,9 +36,7 @@ import cc.winboll.studio.powerbell.utils.ServiceUtils;
import cc.winboll.studio.powerbell.views.MainContentView;
/**
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
* @Date 2025/12/19 20:26
* @Describe 应用核心主活动
* 应用核心主活动
* 功能:管理电池监控、背景设置、服务启停、权限申请等核心功能
* 适配Java7 | API30 | 内存泄漏防护 | UI与服务状态实时同步
*/
@@ -50,7 +46,7 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV
// 请求码常量
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;
@@ -92,7 +88,7 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV
@Override
protected void onCreate(Bundle savedInstanceState) {
LogUtils.d(TAG, "onCreate: 页面启动,开始初始化流程");
LogUtils.d(TAG, "onCreate: 页面启动,开始初始化流程 | savedInstanceState=" + savedInstanceState);
super.onCreate(savedInstanceState);
// 优先初始化全局Handler避免消息丢失
@@ -126,6 +122,7 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV
// 恢复广告
if (mADsBannerView != null) {
mADsBannerView.resumeADs(this);
LogUtils.d(TAG, "onResume: 广告视图恢复展示");
}
}
@@ -143,11 +140,13 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV
if (mADsBannerView != null) {
mADsBannerView.releaseAdResources();
mADsBannerView = null;
LogUtils.d(TAG, "onDestroy: 广告资源已释放");
}
// 释放核心视图
if (mMainContentView != null) {
mMainContentView.releaseResources();
mMainContentView = null;
LogUtils.d(TAG, "onDestroy: 核心视图资源已释放");
}
// 销毁Handler防止内存泄漏
if (sGlobalHandler != null) {
@@ -159,6 +158,7 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV
if (mFrameDrawable != null) {
mFrameDrawable.setCallback(null);
mFrameDrawable = null;
LogUtils.d(TAG, "onDestroy: 框架背景Drawable已释放");
}
// 置空所有引用帮助GC回收
sMainActivity = null;
@@ -176,7 +176,7 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
LogUtils.d(TAG, "onActivityResult: requestCode=" + requestCode + ", resultCode=" + resultCode);
LogUtils.d(TAG, "onActivityResult: requestCode=" + requestCode + " | resultCode=" + resultCode + " | data=" + data);
mPermissionUtils.handlePermissionRequest(this, requestCode, resultCode, data);
// 背景设置完成后重新加载
if (requestCode == REQUEST_READ_MEDIA_IMAGES && sGlobalHandler != null) {
@@ -194,6 +194,7 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV
if (App.isDebugging()) {
DevelopUtils.inflateMenu(this, menu);
getMenuInflater().inflate(R.menu.toolbar_unittest, mMenu);
LogUtils.d(TAG, "onCreateOptionsMenu: 调试模式,加载单元测试菜单");
}
getMenuInflater().inflate(R.menu.toolbar_main, mMenu);
return true;
@@ -201,7 +202,7 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV
@Override
public boolean onOptionsItemSelected(MenuItem item) {
LogUtils.d(TAG, "onOptionsItemSelected: itemId=" + item.getItemId());
LogUtils.d(TAG, "onOptionsItemSelected: 菜单点击 | itemId=" + item.getItemId());
if (AESThemeUtil.onAppThemeItemSelected(this, item)) {
recreate();
return true;
@@ -212,21 +213,27 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV
switch (item.getItemId()) {
case R.id.action_settings:
startActivity(new Intent(this, SettingsActivity.class));
LogUtils.d(TAG, "onOptionsItemSelected: 跳转设置页面");
break;
case R.id.action_battery_report:
startActivity(new Intent(this, BatteryReportActivity.class));
LogUtils.d(TAG, "onOptionsItemSelected: 跳转电池报告页面");
break;
case R.id.action_clearrecord:
startActivity(new Intent(this, ClearRecordActivity.class));
LogUtils.d(TAG, "onOptionsItemSelected: 跳转记录清理页面");
break;
case R.id.action_changepicture:
startActivityForResult(new Intent(this, BackgroundSettingsActivity.class), REQUEST_READ_MEDIA_IMAGES);
LogUtils.d(TAG, "onOptionsItemSelected: 跳转背景设置页面 | requestCode=" + REQUEST_READ_MEDIA_IMAGES);
break;
case R.id.action_unittestactivity:
startActivity(new Intent(this, MainUnitTestActivity.class));
LogUtils.d(TAG, "onOptionsItemSelected: 跳转单元测试页面");
break;
case R.id.action_about:
startAboutActivity();
LogUtils.d(TAG, "onOptionsItemSelected: 跳转关于页面");
break;
default:
return super.onOptionsItemSelected(item);
@@ -239,6 +246,7 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV
super.setupToolbar();
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
LogUtils.d(TAG, "setupToolbar: 隐藏返回按钮");
}
}
@@ -267,10 +275,10 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV
public void handleMessage(Message msg) {
// 校验Activity状态避免销毁后操作UI
if (sMainActivity == null || sMainActivity.isFinishing() || sMainActivity.isDestroyed()) {
LogUtils.w(TAG, "handleMessage: Activity已销毁跳过消息 what=" + msg.what);
LogUtils.w(TAG, "handleMessage: Activity已销毁跳过消息 | what=" + msg.what);
return;
}
LogUtils.d(TAG, "handleMessage: 处理消息 what=" + msg.what);
LogUtils.d(TAG, "handleMessage: 处理消息 | what=" + msg.what);
switch (msg.what) {
case MSG_RELOAD_APPCONFIG:
sMainActivity.updateViewData();
@@ -278,6 +286,7 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV
case MSG_CURRENTVALUEBATTERY:
if (sMainActivity.mMainContentView != null) {
sMainActivity.mMainContentView.updateCurrentBattery(msg.arg1);
LogUtils.d(TAG, "handleMessage: 更新当前电量 | value=" + msg.arg1);
}
break;
case MSG_LOAD_BACKGROUND:
@@ -307,6 +316,7 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV
setSupportActionBar(mToolbar);
if (mToolbar != null) {
mToolbar.setTitleTextAppearance(this, R.style.Toolbar_TitleText);
LogUtils.d(TAG, "initCriticalView: Toolbar样式设置完成");
}
mAdsViewStub = findViewById(R.id.stub_ads_banner);
}
@@ -316,7 +326,7 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV
new Thread(new Runnable() {
@Override
public void run() {
LogUtils.d(TAG, "initCoreUtilsAsync: 异步线程启动");
LogUtils.d(TAG, "initCoreUtilsAsync: 异步线程启动 | threadId=" + Thread.currentThread().getId());
mApplication = (App) getApplication();
mAppConfigUtils = AppConfigUtils.getInstance(getApplicationContext());
mBgSourceUtils = BackgroundSourceUtils.getInstance(getActivity());
@@ -332,6 +342,7 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV
// 根据配置启停服务
final boolean isServiceEnable = mServiceControlBean.isEnableService();
final boolean isServiceAlive = ServiceUtils.isServiceAlive(getApplicationContext(), ControlCenterService.class.getName());
LogUtils.d(TAG, "initCoreUtilsAsync: 服务配置状态 | isServiceEnable=" + isServiceEnable + " | isServiceAlive=" + isServiceAlive);
if (isServiceEnable && !isServiceAlive) {
runOnUiThread(new Runnable() {
@Override
@@ -358,7 +369,7 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV
LogUtils.w(TAG, "initCoreUtilsAsync: Activity已销毁跳过UI更新");
return;
}
// 加载框架背景
// 加载框架背景适配API23+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mFrameDrawable = getResources().getDrawable(R.drawable.bg_frame, getTheme());
} else {
@@ -375,11 +386,12 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV
}
private void loadNonCriticalViewDelayed() {
LogUtils.d(TAG, "loadNonCriticalViewDelayed: 延迟加载非核心视图");
LogUtils.d(TAG, "loadNonCriticalViewDelayed: 延迟加载非核心视图 | 延迟时长=" + DELAY_LOAD_NON_CRITICAL + "ms");
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
if (isFinishing() || isDestroyed()) {
LogUtils.w(TAG, "loadNonCriticalViewDelayed: Activity已销毁跳过广告加载");
return;
}
loadAdsView();
@@ -391,7 +403,7 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV
private void loadAdsView() {
LogUtils.d(TAG, "loadAdsView: 加载广告视图");
if (mAdsViewStub == null) {
LogUtils.e(TAG, "loadAdsView: 广告ViewStub为空");
LogUtils.e(TAG, "loadAdsView: 广告ViewStub为空,加载失败");
return;
}
if (mADsBannerView == null) {
@@ -408,6 +420,7 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV
return;
}
mMainContentView.updateViewData(mFrameDrawable);
LogUtils.d(TAG, "updateViewData: 视图数据更新完成");
}
private void reloadBackground() {
@@ -419,6 +432,7 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV
BackgroundBean currentBgBean = mBgSourceUtils.getCurrentBackgroundBean();
if (currentBgBean != null) {
mMainContentView.backgroundView.loadBackgroundBean(currentBgBean);
LogUtils.d(TAG, "reloadBackground: 加载自定义背景成功");
} else {
mMainContentView.backgroundView.setBackgroundResource(R.drawable.default_background);
LogUtils.w(TAG, "reloadBackground: 无自定义背景,使用默认背景");
@@ -434,6 +448,7 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV
BackgroundBean currentBgBean = mBgSourceUtils.getCurrentBackgroundBean();
if (currentBgBean != null) {
mMainContentView.mainLayout.setBackgroundColor(currentBgBean.getPixelColor());
LogUtils.d(TAG, "setMainLayoutBackgroundColor: 主布局背景色设置完成 | color=" + currentBgBean.getPixelColor());
}
}
@@ -448,19 +463,21 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV
mMainContentView.setServiceSwitchEnabled(false);
mMainContentView.setServiceSwitchChecked(configEnabled);
mMainContentView.setServiceSwitchEnabled(true);
LogUtils.d(TAG, "updateServiceSwitchUI: 服务开关UI状态更新完成");
}
// ======================== 服务与线程管理方法 ========================
private void toggleServiceEnableState(boolean isEnable) {
LogUtils.d(TAG, "toggleServiceEnableState: 切换服务状态目标状态=" + isEnable);
LogUtils.d(TAG, "toggleServiceEnableState: 切换服务状态 | 目标状态=" + isEnable);
if (mServiceControlBean == null) {
LogUtils.e(TAG, "toggleServiceEnableState: 服务配置为空,切换失败");
return;
}
mServiceControlBean.setIsEnableService(isEnable);
ControlCenterServiceBean.saveBean(getApplicationContext(), mServiceControlBean);
LogUtils.d(TAG, "toggleServiceEnableState: 服务配置已保存");
// UI开关联动服务启停 + 线程销毁
// UI开关联动服务启停
if (isEnable) {
// 开启:启动服务
if (!ServiceUtils.isServiceAlive(getApplicationContext(), ControlCenterService.class.getName())) {
@@ -488,8 +505,8 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV
// ======================== 消息发送方法 ========================
private void notifyServiceAppConfigChange() {
LogUtils.d(TAG, "notifyServiceAppConfigChange: 通知服务配置变更");
ControlCenterService.updateStatus(this);
reloadAppConfig();
ControlCenterService.updateStatus(this);
reloadAppConfig();
}
// ======================== 静态工具方法 ========================
@@ -497,18 +514,23 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV
LogUtils.d(TAG, "reloadAppConfig: 发送配置重载消息");
if (sGlobalHandler != null) {
sGlobalHandler.sendEmptyMessage(MSG_RELOAD_APPCONFIG);
} else {
LogUtils.w(TAG, "reloadAppConfig: 全局Handler为空消息发送失败");
}
}
public static void sendCurrentBatteryValueMessage(int value) {
LogUtils.d(TAG, "sendCurrentBatteryValueMessage: 发送当前电量消息电量=" + value);
LogUtils.d(TAG, "sendCurrentBatteryValueMessage: 发送当前电量消息 | 电量=" + value);
if (sGlobalHandler != null) {
Message msg = sGlobalHandler.obtainMessage(MSG_CURRENTVALUEBATTERY);
msg.arg1 = value;
sGlobalHandler.sendMessage(msg);
} else {
LogUtils.w(TAG, "sendCurrentBatteryValueMessage: 全局Handler为空消息发送失败");
}
}
// ======================== 辅助工具方法 ========================
private APPInfo genDefaultAppInfo() {
LogUtils.d(TAG, "genDefaultAppInfo: 生成默认应用信息");
String branchName = "powerbell";
@@ -529,31 +551,31 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV
// ======================== MainContentView 事件回调 ========================
@Override
public void onChargeReminderSwitchChanged(boolean isChecked) {
LogUtils.d(TAG, "onChargeReminderSwitchChanged: 充电提醒开关状态=" + isChecked);
LogUtils.d(TAG, "onChargeReminderSwitchChanged: 充电提醒开关状态变更 | isChecked=" + isChecked);
notifyServiceAppConfigChange();
}
@Override
public void onUsageReminderSwitchChanged(boolean isChecked) {
LogUtils.d(TAG, "onUsageReminderSwitchChanged: 耗电提醒开关状态=" + isChecked);
LogUtils.d(TAG, "onUsageReminderSwitchChanged: 耗电提醒开关状态变更 | isChecked=" + isChecked);
notifyServiceAppConfigChange();
}
@Override
public void onServiceSwitchChanged(boolean isChecked) {
LogUtils.d(TAG, "onServiceSwitchChanged: 服务总开关状态=" + isChecked);
LogUtils.d(TAG, "onServiceSwitchChanged: 服务总开关状态变更 | isChecked=" + isChecked);
toggleServiceEnableState(isChecked);
}
@Override
public void onChargeReminderProgressChanged(int progress) {
LogUtils.d(TAG, "onChargeReminderProgressChanged: 充电提醒阈值=" + progress);
LogUtils.d(TAG, "onChargeReminderProgressChanged: 充电提醒阈值变更 | progress=" + progress);
notifyServiceAppConfigChange();
}
@Override
public void onUsageReminderProgressChanged(int progress) {
LogUtils.d(TAG, "onUsageReminderProgressChanged: 耗电提醒阈值=" + progress);
LogUtils.d(TAG, "onUsageReminderProgressChanged: 耗电提醒阈值变更 | progress=" + progress);
notifyServiceAppConfigChange();
}
}

View File

@@ -8,9 +8,7 @@ import cc.winboll.studio.powerbell.services.ControlCenterService;
import java.lang.ref.WeakReference;
/**
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
* @Date 2025/12/19 20:17
* @Describe 服务通信Handler
* 服务通信Handler
* 功能:处理电量提醒消息,构建并发送标准化通知
* 特性:弱引用防泄漏、参数严格校验、通知格式统一
* 适配Java7 | API30 | 小米手机
@@ -33,7 +31,7 @@ public class ControlCenterServiceHandler extends Handler {
// ================================== 构造方法(强制传入服务,初始化弱引用)=================================
public ControlCenterServiceHandler(ControlCenterService service) {
LogUtils.d(TAG, "构造Handler | service=" + (service != null ? service.getClass().getSimpleName() : "null"));
LogUtils.d(TAG, "ControlCenterServiceHandler: 构造方法执行 | service=" + (service != null ? service.getClass().getSimpleName() : "null"));
this.mwrControlCenterService = new WeakReference<>(service);
}
@@ -46,12 +44,12 @@ public class ControlCenterServiceHandler extends Handler {
int currentBattery = msg.arg1;
boolean isCharging = msg.arg2 == 1;
LogUtils.d(TAG, "接收消息 | what=" + msg.what + " | type=" + remindType + " | battery=" + currentBattery + " | isCharging=" + isCharging);
LogUtils.d(TAG, "handleMessage: 接收消息 | what=" + msg.what + " | type=" + remindType + " | battery=" + currentBattery + " | isCharging=" + isCharging);
// 弱引用获取服务,避免内存泄漏
ControlCenterService service = mwrControlCenterService.get();
if (service == null) {
LogUtils.e(TAG, "服务实例已回收,终止消息处理");
LogUtils.e(TAG, "handleMessage: 服务实例已被GC回收,终止消息处理");
return;
}
@@ -61,7 +59,7 @@ public class ControlCenterServiceHandler extends Handler {
handleRemindMessage(service, remindType, currentBattery, isCharging);
break;
default:
LogUtils.w(TAG, "未知消息类型 | what=" + msg.what);
LogUtils.w(TAG, "handleMessage: 未知消息类型,忽略处理 | what=" + msg.what);
break;
}
}
@@ -75,19 +73,19 @@ public class ControlCenterServiceHandler extends Handler {
* @param isCharging 充电状态
*/
private void handleRemindMessage(ControlCenterService service, String remindType, int currentBattery, boolean isCharging) {
LogUtils.d(TAG, "处理提醒消息 | type=" + remindType + " | battery=" + currentBattery + " | isCharging=" + isCharging);
LogUtils.d(TAG, "handleRemindMessage: 开始处理提醒消息 | type=" + remindType + " | battery=" + currentBattery + " | isCharging=" + isCharging);
// 1. 前置校验:通知工具类+参数有效性
if (service.getNotificationManager() == null) {
LogUtils.e(TAG, "通知管理工具类为空,无法发送提醒");
LogUtils.e(TAG, "handleRemindMessage: 通知管理工具类未初始化,无法发送提醒");
return;
}
if (!REMIND_TYPE_CHARGE.equals(remindType) && !REMIND_TYPE_USAGE.equals(remindType)) {
LogUtils.w(TAG, "无效提醒类型 | type=" + remindType);
LogUtils.w(TAG, "handleRemindMessage: 提醒类型无效,忽略 | type=" + remindType + " | 允许值:" + REMIND_TYPE_CHARGE + "/" + REMIND_TYPE_USAGE);
return;
}
if (currentBattery < BATTERY_LEVEL_MIN || currentBattery > BATTERY_LEVEL_MAX) {
LogUtils.w(TAG, "无效电量值 | battery=" + currentBattery + "需在0-100范围内");
LogUtils.w(TAG, "handleRemindMessage: 电量值超出范围,忽略 | battery=" + currentBattery + " | 允许范围:" + BATTERY_LEVEL_MIN + "-" + BATTERY_LEVEL_MAX);
return;
}
@@ -103,11 +101,12 @@ public class ControlCenterServiceHandler extends Handler {
remindMsg.setContent(String.format("(-) 当前电量%d%%%s已偏低建议及时充电避免设备关机", currentBattery, chargeStateDesc));
remindMsg.setRemindMSG("usage_remind");
}
LogUtils.d(TAG, "构建通知完成 | title=" + remindMsg.getTitle() + " | content=" + remindMsg.getContent());
LogUtils.d(TAG, "handleRemindMessage: 通知模型构建完成 | title=" + remindMsg.getTitle() + " | content=" + remindMsg.getContent());
// 3. 调用工具类发送通知
// 3. 直接调用通知工具类发送,不校验返回结果
LogUtils.d(TAG, "handleRemindMessage: 调用通知工具类发送提醒 | remindMSG=" + remindMsg.getRemindMSG());
service.getNotificationManager().showRemindNotification(service, remindMsg);
LogUtils.d(TAG, "提醒通知发送成功");
LogUtils.d(TAG, "handleRemindMessage: 提醒通知发送流程执行完毕");
}
}

View File

@@ -5,101 +5,167 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Build;
import android.os.IBinder;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.powerbell.App;
import cc.winboll.studio.powerbell.services.ControlCenterService;
import cc.winboll.studio.powerbell.utils.AppConfigUtils;
import cc.winboll.studio.powerbell.utils.ServiceUtils;
/**
* 电池提醒核心服务进程守护类
* 功能:监听主服务 {@link ControlCenterService} 存活状态,异常断开时自动重启并绑定
* 适配Java7 | API30 | 前台服务启动规则 | 服务绑定稳定性保障
*/
public class AssistantService extends Service {
private final static String TAG = "AssistantService";
// ================================== 静态常量区(置顶归类,消除魔法值)=================================
private static final String TAG = "AssistantService";
// 服务返回策略常量(统一定义,避免魔法值)
private static final int SERVICE_RETURN_STICKY = START_STICKY;
//MyBinder mMyBinder;
MyServiceConnection mMyServiceConnection;
volatile boolean mIsThreadAlive;
AppConfigUtils mAppConfigUtils;
@Override
public IBinder onBind(Intent intent) {
//return mMyBinder;
return null;
}
// ================================== 成员变量区按功能分层volatile保证多线程可见性=================================
private MyServiceConnection mMyServiceConnection;
private volatile boolean mIsThreadAlive;
private AppConfigUtils mAppConfigUtils;
// ================================== 服务生命周期方法按执行顺序排列onCreate→onStartCommand→onBind→onDestroy=================================
@Override
public void onCreate() {
//LogUtils.d(TAG, "onCreate");
super.onCreate();
mAppConfigUtils = App.getAppConfigUtils(this);
LogUtils.d(TAG, "onCreate: 守护服务启动 | 进程ID=" + android.os.Process.myPid());
//mMyBinder = new MyBinder();
// 初始化配置工具类,添加空指针防护
mAppConfigUtils = App.getAppConfigUtils(this);
if (mAppConfigUtils == null) {
LogUtils.e(TAG, "onCreate: AppConfigUtils初始化失败守护服务无法工作");
stopSelf();
return;
}
// 初始化服务连接对象
if (mMyServiceConnection == null) {
mMyServiceConnection = new MyServiceConnection();
LogUtils.d(TAG, "onCreate: ServiceConnection初始化完成");
}
// 设置运行参数
// 初始化运行状态,执行核心守护逻辑
mIsThreadAlive = false;
run();
LogUtils.d(TAG, "onCreate: 守护服务初始化完成 | 服务启用状态=" + mAppConfigUtils.isServiceEnabled());
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//LogUtils.d(TAG, "call onStartCommand(...)");
LogUtils.d(TAG, "onStartCommand: 守护服务触发重启 | intent=" + intent + " | flags=" + flags + " | startId=" + startId);
// 配置工具类为空时,直接返回非粘性策略
if (mAppConfigUtils == null) {
LogUtils.e(TAG, "onStartCommand: AppConfigUtils未初始化终止服务");
stopSelf();
return START_NOT_STICKY;
}
run();
return START_STICKY;
int returnFlag = mAppConfigUtils.isServiceEnabled() ? SERVICE_RETURN_STICKY : super.onStartCommand(intent, flags, startId);
LogUtils.d(TAG, "onStartCommand: 处理完成 | 返回策略=" + (returnFlag == SERVICE_RETURN_STICKY ? "START_STICKY" : "DEFAULT"));
return returnFlag;
}
/*class MyBinder extends IMyAidlInterface.Stub {
@Override
public String getServiceName() {
return AssistantService.class.getSimpleName();
}
}*/
@Override
public IBinder onBind(Intent intent) {
LogUtils.d(TAG, "onBind: 服务绑定请求 | intent=" + intent);
return null;
}
@Override
public void onDestroy() {
//LogUtils.d(TAG, "onDestroy");
mIsThreadAlive = false;
super.onDestroy();
LogUtils.d(TAG, "onDestroy: 守护服务销毁流程启动");
// 重置运行状态,终止守护逻辑
mIsThreadAlive = false;
// 解绑主服务,添加异常捕获防止重复解绑崩溃
if (mMyServiceConnection != null) {
try {
unbindService(mMyServiceConnection);
LogUtils.d(TAG, "onDestroy: 已成功解绑ControlCenterService");
} catch (IllegalArgumentException e) {
LogUtils.w(TAG, "onDestroy: 解绑服务失败,服务未绑定 | " + e.getMessage());
}
mMyServiceConnection = null;
}
// 置空工具类引用帮助GC回收
mAppConfigUtils = null;
LogUtils.d(TAG, "onDestroy: 守护服务销毁完成");
}
// 运行服务内容
//
void run() {
//LogUtils.d(TAG, "run");
// ================================== 核心业务逻辑(守护主服务存活)=================================
/**
* 执行守护逻辑:检查主服务状态,按需唤醒并绑定
* 前置条件mAppConfigUtils 必须初始化完成
*/
private void run() {
LogUtils.d(TAG, "run: 执行守护逻辑 | 配置启用=" + mAppConfigUtils.isServiceEnabled() + " | 线程存活=" + mIsThreadAlive);
if (mAppConfigUtils.isServiceEnabled()) {
if (mIsThreadAlive == false) {
// 设置运行状态
if (!mIsThreadAlive) {
mIsThreadAlive = true;
// 唤醒和绑定主进程
wakeupAndBindMain();
}
} else {
LogUtils.d(TAG, "run: 服务未启用,跳过守护逻辑");
// 服务未启用时,重置线程状态
mIsThreadAlive = false;
}
}
// 唤醒和绑定主进程
//
void wakeupAndBindMain() {
if (ServiceUtils.isServiceAlive(getApplicationContext(), ControlCenterService.class.getName()) == false) {
//LogUtils.d(TAG, "wakeupAndBindMain() Wakeup... ControlCenterService");
startForegroundService(new Intent(AssistantService.this, ControlCenterService.class));
/**
* 唤醒主服务并建立绑定,确保主服务持续运行
* 适配 API26+ 前台服务启动规则,避免系统限制导致启动失败
*/
private void wakeupAndBindMain() {
// 检查主服务存活状态
boolean isMainServiceAlive = ServiceUtils.isServiceAlive(getApplicationContext(), ControlCenterService.class.getName());
LogUtils.d(TAG, "wakeupAndBindMain: 主服务存活状态=" + isMainServiceAlive);
// 主服务未存活时按需启动区分API版本
if (!isMainServiceAlive) {
Intent mainServiceIntent = new Intent(AssistantService.this, ControlCenterService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(mainServiceIntent);
LogUtils.d(TAG, "wakeupAndBindMain: API26+ 以前台服务方式启动主服务");
} else {
startService(mainServiceIntent);
LogUtils.d(TAG, "wakeupAndBindMain: 以普通服务方式启动主服务");
}
}
//LogUtils.d(TAG, "wakeupAndBindMain() Bind... ControlCenterService");
bindService(new Intent(AssistantService.this, ControlCenterService.class), mMyServiceConnection, Context.BIND_IMPORTANT);
// 绑定主服务,监听连接状态,添加结果日志
Intent bindIntent = new Intent(AssistantService.this, ControlCenterService.class);
boolean bindResult = bindService(bindIntent, mMyServiceConnection, Context.BIND_IMPORTANT);
LogUtils.d(TAG, "wakeupAndBindMain: 绑定主服务结果=" + bindResult + " | 绑定标记=BIND_IMPORTANT");
}
// 主进程与守护进程连接时需要用到此类
//
class MyServiceConnection implements ServiceConnection {
// ================================== 内部类(服务连接状态监听)=================================
/**
* 服务连接状态监听器
* 主服务连接成功时记录状态,断开时自动重连
*/
private class MyServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//LogUtils.d(TAG, "call onServiceConnected(...)");
LogUtils.d(TAG, "onServiceConnected: 主服务连接成功 | 组件名=" + name.getClassName() + " | Binder=" + service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
//LogUtils.d(TAG, "call onServiceDisconnected(...)");
if (mAppConfigUtils.isServiceEnabled()) {
LogUtils.d(TAG, "onServiceDisconnected: 主服务连接断开 | 组件名=" + name.getClassName());
// 主服务断开且配置启用时,重新唤醒绑定
if (mAppConfigUtils != null && mAppConfigUtils.isServiceEnabled()) {
LogUtils.d(TAG, "onServiceDisconnected: 尝试重新唤醒并绑定主服务");
wakeupAndBindMain();
}
}
}
}

View File

@@ -9,22 +9,19 @@ import android.os.Build;
import android.os.IBinder;
import android.os.PowerManager;
import android.provider.Settings;
import java.util.List;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.ToastUtils;
import cc.winboll.studio.powerbell.handlers.ControlCenterServiceHandler;
import cc.winboll.studio.powerbell.models.AppConfigBean;
import cc.winboll.studio.powerbell.models.ControlCenterServiceBean;
import cc.winboll.studio.powerbell.models.NotificationMessage;
import cc.winboll.studio.powerbell.receivers.ControlCenterServiceReceiver;
import cc.winboll.studio.powerbell.threads.RemindThread;
import cc.winboll.studio.powerbell.utils.NotificationManagerUtils;
import java.io.Serializable;
import java.util.List;
import cc.winboll.studio.powerbell.receivers.ControlCenterServiceReceiver;
/**
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
* @Date 2025/12/19 20:21
* @Describe 电池提醒核心服务
* 电池提醒核心服务
* 功能:管理前台服务生命周期、控制提醒线程启停、处理配置更新
* 适配Java7 | API30 | 前台服务超时防护 | 电池优化忽略引导
*/
@@ -32,10 +29,6 @@ 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;
// 服务状态标记常量
@@ -315,8 +308,7 @@ public class ControlCenterService extends Service {
/**
* 外部更新配置并触发线程重启
* @param context 上下文
* @param configBean 新配置
* @param context 上下文
*/
public static void updateStatus(Context context) {
LogUtils.d(TAG, "updateStatus: 外部更新配置 | context=" + context);
@@ -329,6 +321,7 @@ public class ControlCenterService extends Service {
intent.setAction(ControlCenterServiceReceiver.ACTION_APPCONFIG_CHANGED);
intent.setPackage(context.getPackageName());
context.sendBroadcast(intent);
LogUtils.d(TAG, "updateStatus: 配置更新广播已发送 | action=" + ControlCenterServiceReceiver.ACTION_APPCONFIG_CHANGED);
}
/**
@@ -357,7 +350,7 @@ public class ControlCenterService extends Service {
intent.setData(Uri.parse("package:" + packageName));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(intent);
LogUtils.d(TAG, "checkIgnoreBatteryOptimization: 已跳转至系统设置页");
LogUtils.d(TAG, "checkIgnoreBatteryOptimization: 已跳转至系统设置页 | package=" + packageName);
}
}
@@ -368,7 +361,7 @@ public class ControlCenterService extends Service {
* @return true=运行中 false=未运行
*/
private static boolean isServiceRunning(Context context, Class<?> serviceClass) {
LogUtils.d(TAG, "isServiceRunning: 检查服务状态 | context=" + context + " | service=" + serviceClass);
LogUtils.d(TAG, "isServiceRunning: 检查服务状态 | context=" + context + " | service=" + serviceClass.getName());
if (context == null || serviceClass == null) {
LogUtils.e(TAG, "isServiceRunning: 参数为空");
return false;
@@ -444,9 +437,9 @@ public class ControlCenterService extends Service {
if (latestConfig != null && mServiceHandler != null) {
mCurrentConfigBean = latestConfig;
RemindThread.startRemindThread(this, mServiceHandler, latestConfig);
LogUtils.d(TAG, "notifyAppConfigUpdate: 配置已同步到线程");
LogUtils.d(TAG, "notifyAppConfigUpdate: 配置已同步到提醒线程");
} else {
LogUtils.e(TAG, "notifyAppConfigUpdate: 参数为空,同步失败");
LogUtils.e(TAG, "notifyAppConfigUpdate: 参数为空,同步失败 | latestConfig=" + latestConfig + " | mServiceHandler=" + mServiceHandler);
}
}