diff --git a/powerbell/build.properties b/powerbell/build.properties index 3c6f611..c39157b 100644 --- a/powerbell/build.properties +++ b/powerbell/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Thu Dec 25 07:32:14 GMT 2025 +#Thu Dec 25 07:58:57 GMT 2025 stageCount=30 libraryProject= baseVersion=15.14 publishVersion=15.14.29 -buildCount=36 +buildCount=42 baseBetaVersion=15.14.30 diff --git a/powerbell/src/main/AndroidManifest.xml b/powerbell/src/main/AndroidManifest.xml index c7d9479..a48c386 100644 --- a/powerbell/src/main/AndroidManifest.xml +++ b/powerbell/src/main/AndroidManifest.xml @@ -198,7 +198,6 @@ android:priority="1000" android:enabled="true" android:exported="false" - android:process=".controlcenterservice" android:foregroundServiceType="dataSync"> + android:process=".assistant"> diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/App.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/App.java index 22bc9e8..5cc82a6 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/App.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/App.java @@ -18,6 +18,8 @@ import cc.winboll.studio.powerbell.views.MemoryCachedBackgroundView; * 应用全局入口类(适配Android API 30,基于Java 7编写) * 核心策略:极致强制缓存 - 无论内存紧张程度,永不自动清理任何缓存(Bitmap/视图控件/路径记录) * @Author 豆包&ZhanGSKen + * @Version 1.0.0 + * @Date 2025-12-25 */ public class App extends GlobalApplication { // ===================== 常量定义区(按功能分类排序) ===================== @@ -35,6 +37,7 @@ public class App extends GlobalApplication { // 缓存防护常量 private static final String CACHE_PROTECT_TAG = "FORCE_CACHE_PROTECT"; + private static final int INVALID_BATTERY_VALUE = -1; // ===================== 静态属性区(按工具类优先级排序) ===================== // 数据配置工具 @@ -42,11 +45,13 @@ public class App extends GlobalApplication { private static AppCacheUtils sAppCacheUtils; // 全局Bitmap缓存工具(极致强制保持:一旦初始化,永不销毁) - public static BackgroundSourceUtils sBackgroundSourceUtils; + public static BackgroundSourceUtils sBackgroundSourceUtils; public static BitmapCacheUtils sBitmapCacheUtils; // 全局视图控件缓存工具(极致强制保持:一旦初始化,永不销毁) - public static MemoryCachedBackgroundView sMemoryCachedBackgroundView; + // 核心修改:改为私有静态,通过实例方法获取,避免全局通用暴露 + private static MemoryCachedBackgroundView sMemoryCachedBackgroundView; + public static volatile int sQuantityOfElectricity = INVALID_BATTERY_VALUE; // ===================== 成员属性区(按生命周期关联度排序) ===================== // 全局广播接收器 @@ -54,7 +59,7 @@ public class App extends GlobalApplication { // 通知管理工具 private static NotificationManagerUtils sNotificationManagerUtils; - private static App sApp; + private static App sApp; // ===================== 公共静态方法区(工具类实例获取) ===================== /** @@ -62,7 +67,7 @@ public class App extends GlobalApplication { */ public static AppConfigUtils getAppConfigUtils(Context context) { LogUtils.d(TAG, String.format("getAppConfigUtils() 调用 | 传入Context类型=%s", - context != null ? context.getClass().getSimpleName() : "null")); + context != null ? context.getClass().getSimpleName() : "null")); if (sAppConfigUtils == null) { sAppConfigUtils = AppConfigUtils.getInstance(context); LogUtils.d(TAG, "getAppConfigUtils():AppConfigUtils实例已初始化"); @@ -75,7 +80,7 @@ public class App extends GlobalApplication { */ public static AppCacheUtils getAppCacheUtils(Context context) { LogUtils.d(TAG, String.format("getAppCacheUtils() 调用 | 传入Context类型=%s", - context != null ? context.getClass().getSimpleName() : "null")); + context != null ? context.getClass().getSimpleName() : "null")); if (sAppCacheUtils == null) { sAppCacheUtils = AppCacheUtils.getInstance(context); LogUtils.d(TAG, "getAppCacheUtils():AppCacheUtils实例已初始化"); @@ -83,6 +88,13 @@ public class App extends GlobalApplication { return sAppCacheUtils; } + /** + * 获取应用单例实例 + */ + public static App getInstance() { + return sApp; + } + // ===================== 公共成员方法区(业务功能) ===================== /** * 清除电池历史数据 @@ -116,11 +128,22 @@ public class App extends GlobalApplication { LogUtils.w(TAG, String.format("%s 手动清理缓存完成(部分缓存实例仍可能保留在内存中)", CACHE_PROTECT_TAG)); } + /** + * 获取视图控件缓存实例(非通用:仅通过App实例调用,避免全局直接访问) + */ + public MemoryCachedBackgroundView getMemoryCachedBackgroundView() { + LogUtils.d(TAG, "getMemoryCachedBackgroundView() 调用 | 视图控件缓存实例获取"); + if (sMemoryCachedBackgroundView == null) { + LogUtils.w(TAG, "getMemoryCachedBackgroundView():视图控件缓存实例未初始化,返回null"); + } + return sMemoryCachedBackgroundView; + } + // ===================== 生命周期方法区(按执行顺序排序) ===================== @Override public void onCreate() { super.onCreate(); - sApp = this; + sApp = this; LogUtils.d(TAG, "onCreate() 应用启动,开始初始化"); // 初始化调试模式 @@ -129,7 +152,7 @@ public class App extends GlobalApplication { // 初始化基础工具 initBaseTools(); - //App.notifyMessage(TAG, "onCreate() 应用启动中。。。"); + //App.notifyMessage(TAG, "onCreate() 应用启动中。。。"); // 初始化工具类实例(核心:极致强制缓存,永不销毁) initUtils(); // 初始化广播接收器 @@ -162,7 +185,7 @@ public class App extends GlobalApplication { super.onTrimMemory(level); // 极致强制缓存:禁止任何缓存清理操作,仅记录日志 LogUtils.w(TAG, String.format("%s onTrimMemory() 调用 | 内存等级level=%d | 极致强制保持所有缓存", - CACHE_PROTECT_TAG, level)); + CACHE_PROTECT_TAG, level)); // 记录详细缓存状态,不执行任何清理 logDetailedCacheStatus(); } @@ -194,22 +217,22 @@ public class App extends GlobalApplication { */ private void initUtils() { LogUtils.d(TAG, "initUtils() 开始初始化工具类,启用极致强制缓存策略"); - //App.notifyMessage(TAG, "initUtils() 开始初始化工具类,启用极致强制缓存策略"); + //App.notifyMessage(TAG, "initUtils() 开始初始化工具类,启用极致强制缓存策略"); sAppConfigUtils = getAppConfigUtils(this); sAppCacheUtils = getAppCacheUtils(this); - sBackgroundSourceUtils = BackgroundSourceUtils.getInstance(this); - sBackgroundSourceUtils.loadSettings(); + sBackgroundSourceUtils = BackgroundSourceUtils.getInstance(this); + sBackgroundSourceUtils.loadSettings(); // 极致强制初始化Bitmap缓存工具(必初始化,永不销毁) sBitmapCacheUtils = BitmapCacheUtils.getInstance(); LogUtils.d(TAG, "initUtils() Bitmap缓存工具已初始化(极致强制保持,永不销毁)"); // 极致强制初始化视图控件缓存工具(必初始化,永不销毁) sMemoryCachedBackgroundView = MemoryCachedBackgroundView.getLastInstance(this); - if(sMemoryCachedBackgroundView == null) { - App.notifyMessage(TAG, "sMemoryCachedBackgroundView == null"); - sMemoryCachedBackgroundView = MemoryCachedBackgroundView.getInstance(this, sBackgroundSourceUtils.getCurrentBackgroundBean(), true); - } + if (sMemoryCachedBackgroundView == null) { + //App.notifyMessage(TAG, "sMemoryCachedBackgroundView == null"); + sMemoryCachedBackgroundView = MemoryCachedBackgroundView.getInstance(this, sBackgroundSourceUtils.getCurrentBackgroundBean(), true); + } LogUtils.d(TAG, "initUtils() 视图控件缓存工具已初始化(极致强制保持,永不销毁)"); } @@ -267,7 +290,7 @@ public class App extends GlobalApplication { LogUtils.d(TAG, String.format("%s Bitmap缓存数量=%d", CACHE_PROTECT_TAG, cacheCount)); } catch (Exception e) { LogUtils.d(TAG, String.format("%s Bitmap缓存数量获取失败(不影响缓存)| 异常信息=%s", - CACHE_PROTECT_TAG, e.getMessage())); + CACHE_PROTECT_TAG, e.getMessage())); } } // 视图控件缓存状态 @@ -280,11 +303,11 @@ public class App extends GlobalApplication { LogUtils.d(TAG, "logDetailedCacheStatus() 详细缓存状态记录完成,所有缓存均极致强制保持"); } - public static void notifyMessage(String title, String content) { - if (isDebugging() && sApp != null && sNotificationManagerUtils != null) { - NotificationMessage message = new NotificationMessage(title, content, ""); - sNotificationManagerUtils.showMessageNotification(sApp, message); - } - } + public static void notifyMessage(String title, String content) { + if (isDebugging() && sApp != null && sNotificationManagerUtils != null) { + NotificationMessage message = new NotificationMessage(title, content, ""); + sNotificationManagerUtils.showMessageNotification(sApp, message); + } + } } diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/receivers/ControlCenterServiceReceiver.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/receivers/ControlCenterServiceReceiver.java index 319aa81..32b1435 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/receivers/ControlCenterServiceReceiver.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/receivers/ControlCenterServiceReceiver.java @@ -5,10 +5,10 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import cc.winboll.studio.libappbase.LogUtils; +import cc.winboll.studio.powerbell.App; import cc.winboll.studio.powerbell.models.AppConfigBean; import cc.winboll.studio.powerbell.models.NotificationMessage; import cc.winboll.studio.powerbell.services.ControlCenterService; -import cc.winboll.studio.powerbell.threads.RemindThread; import cc.winboll.studio.powerbell.utils.AppConfigUtils; import cc.winboll.studio.powerbell.utils.BatteryUtils; import cc.winboll.studio.powerbell.utils.NotificationManagerUtils; @@ -142,7 +142,7 @@ public class ControlCenterServiceReceiver extends BroadcastReceiver { latestConfig.getChargeReminderValue(), latestConfig.getUsageReminderValue())); // 同步缓存的电池状态到配置 - RemindThread.sQuantityOfElectricity = sLastBatteryLevel; + App.sQuantityOfElectricity = sLastBatteryLevel; latestConfig.setIsCharging(sIsCharging); service.notifyAppConfigUpdate(latestConfig); diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/threads/RemindThread.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/threads/RemindThread.java index c38adb3..ad05f6f 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/threads/RemindThread.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/threads/RemindThread.java @@ -3,6 +3,7 @@ package cc.winboll.studio.powerbell.threads; import android.content.Context; import android.os.Message; import cc.winboll.studio.libappbase.LogUtils; +import cc.winboll.studio.powerbell.App; import cc.winboll.studio.powerbell.handlers.ControlCenterServiceHandler; import cc.winboll.studio.powerbell.models.AppConfigBean; import java.lang.ref.WeakReference; @@ -26,7 +27,6 @@ public class RemindThread extends Thread { private static final long THREAD_JOIN_TIMEOUT = 1000L; // 状态常量 - private static final int INVALID_BATTERY_VALUE = -1; private static final int BATTERY_LEVEL_MIN = 0; private static final int BATTERY_LEVEL_MAX = 100; @@ -55,7 +55,6 @@ public class RemindThread extends Thread { private volatile long sleepTime; private volatile int chargeReminderValue; private volatile int usageReminderValue; - public static volatile int sQuantityOfElectricity = INVALID_BATTERY_VALUE; private volatile boolean isCharging; // ====================== 私有构造器(禁止外部实例化) ====================== @@ -170,21 +169,21 @@ public class RemindThread extends Thread { if (isExist) break; // 电量有效性校验(非0-100视为无效),退出电量提醒线程 - if (sQuantityOfElectricity < BATTERY_LEVEL_MIN || sQuantityOfElectricity > BATTERY_LEVEL_MAX) { - LogUtils.w(TAG, String.format("电量无效,退出电量提醒线程 | 当前电量=%d | threadId=%d", sQuantityOfElectricity, getId())); + if (App.sQuantityOfElectricity < BATTERY_LEVEL_MIN || App.sQuantityOfElectricity > BATTERY_LEVEL_MAX) { + LogUtils.w(TAG, String.format("电量无效,退出电量提醒线程 | 当前电量=%d | threadId=%d", App.sQuantityOfElectricity, getId())); break; } // 充电/耗电提醒触发逻辑 - boolean chargeRemindTrigger = isCharging && isEnableChargeReminder && sQuantityOfElectricity >= chargeReminderValue; - boolean usageRemindTrigger = !isCharging && isEnableUsageReminder && sQuantityOfElectricity <= usageReminderValue; + boolean chargeRemindTrigger = isCharging && isEnableChargeReminder && App.sQuantityOfElectricity >= chargeReminderValue; + boolean usageRemindTrigger = !isCharging && isEnableUsageReminder && App.sQuantityOfElectricity <= usageReminderValue; if (chargeRemindTrigger) { - LogUtils.d(TAG, String.format("触发充电提醒 | 当前电量=%d ≥ 阈值=%d | threadId=%d", sQuantityOfElectricity, chargeReminderValue, getId())); - sendNotificationMessageInternal(REMIND_TYPE_CHARGE, sQuantityOfElectricity, isCharging); + LogUtils.d(TAG, String.format("触发充电提醒 | 当前电量=%d ≥ 阈值=%d | threadId=%d", App.sQuantityOfElectricity, chargeReminderValue, getId())); + sendNotificationMessageInternal(REMIND_TYPE_CHARGE, App.sQuantityOfElectricity, isCharging); } else if (usageRemindTrigger) { - LogUtils.d(TAG, String.format("触发耗电提醒 | 当前电量=%d ≤ 阈值=%d | threadId=%d", sQuantityOfElectricity, usageReminderValue, getId())); - sendNotificationMessageInternal(REMIND_TYPE_USAGE, sQuantityOfElectricity, isCharging); + LogUtils.d(TAG, String.format("触发耗电提醒 | 当前电量=%d ≤ 阈值=%d | threadId=%d", App.sQuantityOfElectricity, usageReminderValue, getId())); + sendNotificationMessageInternal(REMIND_TYPE_USAGE, App.sQuantityOfElectricity, isCharging); } else { LogUtils.d(TAG, String.format("未有合适类型提醒,退出提醒线程 | threadId=%d", getId())); break; @@ -194,7 +193,7 @@ public class RemindThread extends Thread { safeSleepInternal(sleepTime); } catch (Exception e) { - LogUtils.e(TAG, String.format("循环运行异常,退出电量提醒线程 | 当前电量=%d | threadId=%d", sQuantityOfElectricity, getId()), e); + LogUtils.e(TAG, String.format("循环运行异常,退出电量提醒线程 | 当前电量=%d | threadId=%d", App.sQuantityOfElectricity, getId()), e); break; } } @@ -283,7 +282,6 @@ public class RemindThread extends Thread { LogUtils.d(TAG, String.format("cleanThreadStateInternal() 调用 | threadId=%d", getId())); isReminding = false; isExist = true; - sQuantityOfElectricity = INVALID_BATTERY_VALUE; // 中断当前线程(如果存活) if (isAlive()) { interrupt(); @@ -300,7 +298,6 @@ public class RemindThread extends Thread { LogUtils.d(TAG, String.format("setAppConfigBean() 调用 | config=%s | threadId=%d", config, getId())); if (config == null) { LogUtils.e(TAG, String.format("配置同步失败:配置Bean为空 | threadId=%d", getId())); - sQuantityOfElectricity = INVALID_BATTERY_VALUE; return; } @@ -315,7 +312,7 @@ public class RemindThread extends Thread { isCharging = config.isCharging(); LogUtils.d(TAG, String.format("配置同步完成 | 休眠时间=%dms | 充电提醒=%b | 耗电提醒=%b | 当前电量=%d | 充电阈值=%d | 耗电阈值=%d | threadId=%d", - sleepTime, isEnableChargeReminder, isEnableUsageReminder, sQuantityOfElectricity, chargeReminderValue, usageReminderValue, getId())); + sleepTime, isEnableChargeReminder, isEnableUsageReminder, App.sQuantityOfElectricity, chargeReminderValue, usageReminderValue, getId())); } /** @@ -348,7 +345,7 @@ public class RemindThread extends Thread { ", isReminding=" + isReminding + ", chargeThreshold=" + chargeReminderValue + ", usageThreshold=" + usageReminderValue + - ", currentBattery=" + sQuantityOfElectricity + + ", currentBattery=" + App.sQuantityOfElectricity + ", isCharging=" + isCharging + ", sleepTime=" + sleepTime + "ms" + '}'; diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/AppConfigUtils.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/AppConfigUtils.java index 53e9c63..6081bbb 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/AppConfigUtils.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/AppConfigUtils.java @@ -249,12 +249,12 @@ public class AppConfigUtils { LogUtils.d(TAG, String.format("setCurrentBatteryValue() 调用 | 传入电量=%d", value)); int calibratedValue = Math.min(Math.max(value, MIN_REMINDER_VALUE), MAX_REMINDER_VALUE); - if (calibratedValue == RemindThread.sQuantityOfElectricity) { + if (calibratedValue == App.sQuantityOfElectricity) { LogUtils.d(TAG, "setCurrentBatteryValue():电池电量无变化,无需操作"); return; } - RemindThread.sQuantityOfElectricity = calibratedValue; + App.sQuantityOfElectricity = calibratedValue; LogUtils.d(TAG, String.format("setCurrentBatteryValue() 成功 | 电池电量=%d%%", calibratedValue)); } @@ -263,7 +263,7 @@ public class AppConfigUtils { * @return 当前电池电量(0-100) */ public int getCurrentBatteryValue() { - int value = RemindThread.sQuantityOfElectricity; + int value = App.sQuantityOfElectricity; LogUtils.d(TAG, String.format("getCurrentBatteryValue():获取电池电量=%d%%", value)); return value; } diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/views/MainContentView.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/views/MainContentView.java index e1a6a40..3d76b4d 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/views/MainContentView.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/views/MainContentView.java @@ -154,11 +154,11 @@ public class MainContentView { mainLayout = (RelativeLayout) rootView.findViewById(R.id.activitymainRelativeLayout1); mllBackgroundView = (LinearLayout) rootView.findViewById(R.id.ll_backgroundview); - backgroundView = App.sMemoryCachedBackgroundView.getLastInstance(mContext); + backgroundView = App.getInstance().getMemoryCachedBackgroundView().getLastInstance(mContext); if (backgroundView == null) { App.sBackgroundSourceUtils.loadSettings(); BackgroundBean backgroundBean = App.sBackgroundSourceUtils.getCurrentBackgroundBean(); - backgroundView = App.sMemoryCachedBackgroundView.getInstance(mContext, backgroundBean, true); + backgroundView = App.getInstance().getMemoryCachedBackgroundView().getInstance(mContext, backgroundBean, true); } if (backgroundView.getParent() != null) { ((ViewGroup) backgroundView.getParent()).removeView(backgroundView); diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/views/MemoryCachedBackgroundView.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/views/MemoryCachedBackgroundView.java index 46377a2..4fce16d 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/views/MemoryCachedBackgroundView.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/views/MemoryCachedBackgroundView.java @@ -65,7 +65,7 @@ public class MemoryCachedBackgroundView extends BackgroundView { sCachedView.loadByBackgroundBean(bean, isReload); saveLastLoadImagePath(context, getBackgroundBeanImagePath(bean)); LogUtils.d(TAG, String.format("getInstance: 已更新当前缓存实例,旧实例路径=%s(强制保持)", getBackgroundBeanImagePath(bean))); - App.notifyMessage(TAG, String.format("getInstance: 已更新当前缓存实例,旧实例路径=%s(强制保持)", getBackgroundBeanImagePath(bean))); + //App.notifyMessage(TAG, String.format("getInstance: 已更新当前缓存实例,旧实例路径=%s(强制保持)", getBackgroundBeanImagePath(bean))); return sCachedView; } @@ -96,10 +96,10 @@ public class MemoryCachedBackgroundView extends BackgroundView { //App.notifyMessage(TAG, String.format("lastPath : %s", lastPath)); if (lastPath.equals(sCachedImagePath) && sCachedView != null) { LogUtils.d(TAG, String.format("getLastInstance: 使用最后路径缓存实例 | 路径=%s", lastPath)); - App.notifyMessage(TAG, String.format("getLastInstance: 使用最后路径缓存实例 | 路径=%s", lastPath)); + //App.notifyMessage(TAG, String.format("getLastInstance: 使用最后路径缓存实例 | 路径=%s", lastPath)); return sCachedView; } - App.notifyMessage(TAG, "getLastInstance 返回 null"); + //App.notifyMessage(TAG, "getLastInstance 返回 null"); return null; }