diff --git a/powerbell/build.properties b/powerbell/build.properties index c803b84..215a307 100644 --- a/powerbell/build.properties +++ b/powerbell/build.properties @@ -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 diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java index 2abfe25..3e08d34 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java @@ -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&豆包大模型 - * @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(); } } diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/handlers/ControlCenterServiceHandler.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/handlers/ControlCenterServiceHandler.java index 8724c47..538f48a 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/handlers/ControlCenterServiceHandler.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/handlers/ControlCenterServiceHandler.java @@ -8,9 +8,7 @@ import cc.winboll.studio.powerbell.services.ControlCenterService; import java.lang.ref.WeakReference; /** - * @Author ZhanGSKen&豆包大模型 - * @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: 提醒通知发送流程执行完毕"); } } diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/services/AssistantService.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/services/AssistantService.java index 09c4b7c..61d41ec 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/services/AssistantService.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/services/AssistantService.java @@ -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(); } } } } + diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/services/ControlCenterService.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/services/ControlCenterService.java index c91d568..7ce33a8 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/services/ControlCenterService.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/services/ControlCenterService.java @@ -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&豆包大模型 - * @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); } }