From 4fcce7edb3a46cc3161256cf7e11141b3a862dde Mon Sep 17 00:00:00 2001 From: ZhanGSKen Date: Thu, 25 Dec 2025 15:35:12 +0800 Subject: [PATCH] 20251225_153508_537 --- powerbell/build.properties | 4 +- .../java/cc/winboll/studio/powerbell/App.java | 33 ++- .../unittest/MainUnitTest2Activity.java | 2 +- .../powerbell/utils/BitmapCacheUtils.java | 1 + .../utils/NotificationManagerUtils.java | 203 ++++++++++-------- .../powerbell/views/MainContentView.java | 13 +- .../views/MemoryCachedBackgroundView.java | 68 +++--- 7 files changed, 179 insertions(+), 145 deletions(-) diff --git a/powerbell/build.properties b/powerbell/build.properties index 6595fb9..3c6f611 100644 --- a/powerbell/build.properties +++ b/powerbell/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Wed Dec 24 21:23:33 HKT 2025 +#Thu Dec 25 07:32:14 GMT 2025 stageCount=30 libraryProject= baseVersion=15.14 publishVersion=15.14.29 -buildCount=0 +buildCount=36 baseBetaVersion=15.14.30 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 3da4274..22bc9e8 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/App.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/App.java @@ -5,9 +5,11 @@ import cc.winboll.studio.libaes.utils.WinBoLLActivityManager; import cc.winboll.studio.libappbase.GlobalApplication; import cc.winboll.studio.libappbase.LogUtils; import cc.winboll.studio.libappbase.ToastUtils; +import cc.winboll.studio.powerbell.models.NotificationMessage; import cc.winboll.studio.powerbell.receivers.GlobalApplicationReceiver; import cc.winboll.studio.powerbell.utils.AppCacheUtils; import cc.winboll.studio.powerbell.utils.AppConfigUtils; +import cc.winboll.studio.powerbell.utils.BackgroundSourceUtils; import cc.winboll.studio.powerbell.utils.BitmapCacheUtils; import cc.winboll.studio.powerbell.utils.NotificationManagerUtils; import cc.winboll.studio.powerbell.views.MemoryCachedBackgroundView; @@ -40,6 +42,7 @@ public class App extends GlobalApplication { private static AppCacheUtils sAppCacheUtils; // 全局Bitmap缓存工具(极致强制保持:一旦初始化,永不销毁) + public static BackgroundSourceUtils sBackgroundSourceUtils; public static BitmapCacheUtils sBitmapCacheUtils; // 全局视图控件缓存工具(极致强制保持:一旦初始化,永不销毁) @@ -50,7 +53,8 @@ public class App extends GlobalApplication { private GlobalApplicationReceiver mGlobalReceiver; // 通知管理工具 - private NotificationManagerUtils mNotificationManager; + private static NotificationManagerUtils sNotificationManagerUtils; + private static App sApp; // ===================== 公共静态方法区(工具类实例获取) ===================== /** @@ -116,6 +120,7 @@ public class App extends GlobalApplication { @Override public void onCreate() { super.onCreate(); + sApp = this; LogUtils.d(TAG, "onCreate() 应用启动,开始初始化"); // 初始化调试模式 @@ -124,6 +129,7 @@ public class App extends GlobalApplication { // 初始化基础工具 initBaseTools(); + //App.notifyMessage(TAG, "onCreate() 应用启动中。。。"); // 初始化工具类实例(核心:极致强制缓存,永不销毁) initUtils(); // 初始化广播接收器 @@ -179,6 +185,8 @@ public class App extends GlobalApplication { WinBoLLActivityManager.init(this); ToastUtils.init(this); LogUtils.d(TAG, "initBaseTools() 基础工具初始化完成"); + sNotificationManagerUtils = new NotificationManagerUtils(this); + LogUtils.d(TAG, "initBaseTools() 工具类初始化完成,极致强制缓存策略已生效"); } /** @@ -186,19 +194,23 @@ public class App extends GlobalApplication { */ private void initUtils() { LogUtils.d(TAG, "initUtils() 开始初始化工具类,启用极致强制缓存策略"); + //App.notifyMessage(TAG, "initUtils() 开始初始化工具类,启用极致强制缓存策略"); sAppConfigUtils = getAppConfigUtils(this); sAppCacheUtils = getAppCacheUtils(this); + 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); + } LogUtils.d(TAG, "initUtils() 视图控件缓存工具已初始化(极致强制保持,永不销毁)"); - - mNotificationManager = new NotificationManagerUtils(this); - LogUtils.d(TAG, "initUtils() 工具类初始化完成,极致强制缓存策略已生效"); } /** @@ -231,9 +243,9 @@ public class App extends GlobalApplication { */ private void releaseNotificationManager() { LogUtils.d(TAG, "releaseNotificationManager() 开始释放通知工具"); - if (mNotificationManager != null) { - mNotificationManager.release(); - mNotificationManager = null; + if (sNotificationManagerUtils != null) { + sNotificationManagerUtils.release(); + sNotificationManagerUtils = null; LogUtils.d(TAG, "releaseNotificationManager() 通知工具资源已释放"); } else { LogUtils.d(TAG, "releaseNotificationManager() 通知工具未初始化,无需释放"); @@ -267,5 +279,12 @@ 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); + } + } } diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/unittest/MainUnitTest2Activity.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/unittest/MainUnitTest2Activity.java index 7e583d3..27e68aa 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/unittest/MainUnitTest2Activity.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/unittest/MainUnitTest2Activity.java @@ -106,7 +106,7 @@ public class MainUnitTest2Activity extends AppCompatActivity { // 创建MemoryCachedBackgroundView单例并添加到布局 int nCurrentPixelColor = BackgroundSourceUtils.getInstance(this).getCurrentBackgroundBean().getPixelColor(); - mMemoryCachedBackgroundView = MemoryCachedBackgroundView.getInstance(this, nCurrentPixelColor, "", false); + mMemoryCachedBackgroundView = MemoryCachedBackgroundView.getLastInstance(this); mllBackgroundView.addView(mMemoryCachedBackgroundView); LogUtils.d(TAG, "initViewAndEvent:内存缓存背景视图实例创建并添加完成"); diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/BitmapCacheUtils.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/BitmapCacheUtils.java index 8f39cc6..b7b2ac5 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/BitmapCacheUtils.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/BitmapCacheUtils.java @@ -51,6 +51,7 @@ public class BitmapCacheUtils { */ private BitmapCacheUtils() { LogUtils.d(TAG, "【BitmapCacheUtils】单例构造开始"); + //App.notifyMessage(TAG, "【BitmapCacheUtils】单例构造开始"); // 使用 ConcurrentHashMap 保证线程安全,避免手动同步 mHardCacheMap = new ConcurrentHashMap<>(); mRefCountMap = new ConcurrentHashMap<>(); diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/NotificationManagerUtils.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/NotificationManagerUtils.java index 6cfe53b..5e9289a 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/NotificationManagerUtils.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/NotificationManagerUtils.java @@ -22,7 +22,7 @@ import cc.winboll.studio.powerbell.models.NotificationMessage; /** * 通知工具类:统一管理前台服务/电池提醒/应用配置信息通知 * 适配:API19-30 | Java7 | 小米手机 - * 特性:前台服务无铃声、提醒通知系统默认铃声、配置通知低优先级无打扰、API分级适配、内存泄漏防护 + * 特性:前台服务无铃声、提醒通知系统默认铃声、配置通知系统默认铃声无振动、API分级适配、内存泄漏防护 */ public class NotificationManagerUtils { // ================================== 静态常量(置顶统一管理,杜绝魔法值)================================= @@ -48,6 +48,7 @@ public class NotificationManagerUtils { private static final int PENDING_INTENT_REQUEST_CODE_FOREGROUND = 0; private static final int PENDING_INTENT_REQUEST_CODE_REMIND = 1; private static final int PENDING_INTENT_REQUEST_CODE_CONFIG = 2; // 新增:配置通知请求码 + private static int snMessageNotificationID = 10000; // ================================== 成员变量(私有封装,按依赖优先级排序)================================= // 核心上下文(应用级,避免内存泄漏) @@ -59,35 +60,35 @@ public class NotificationManagerUtils { // ================================== 构造方法(初始化核心资源,前置校验)================================= public NotificationManagerUtils(Context context) { - LogUtils.d(TAG, "NotificationManagerUtils: 构造方法执行 | context=" + context); + LogUtils.d(TAG, "NotificationManagerUtils() 构造 | context=" + context); // 前置校验:Context非空 if (context == null) { - LogUtils.e(TAG, "NotificationManagerUtils: 构造失败:context is null"); + LogUtils.e(TAG, "NotificationManagerUtils() 构造失败:context is null"); return; } // 初始化核心资源 this.mContext = context.getApplicationContext(); this.mNotificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); - LogUtils.d(TAG, "NotificationManagerUtils: 核心资源初始化完成 | mContext=" + mContext + " | mNotificationManager=" + mNotificationManager); + LogUtils.d(TAG, "NotificationManagerUtils() 核心资源初始化完成 | mContext=" + mContext + " | mNotificationManager=" + mNotificationManager); // 初始化通知渠道(API26+ 必需) initNotificationChannels(); - LogUtils.d(TAG, "NotificationManagerUtils: 构造完成"); + LogUtils.d(TAG, "NotificationManagerUtils() 构造完成"); } // ================================== 核心初始化方法(通知渠道,API分级适配)================================= /** - * 初始化通知渠道:前台服务渠道(无铃声+无振动)、提醒渠道(系统默认铃声+无振动)、配置信息渠道(低优先级无打扰) + * 初始化通知渠道:前台服务渠道(无铃声+无振动)、提醒渠道(系统默认铃声+无振动)、配置信息渠道(系统默认铃声+无振动) */ private void initNotificationChannels() { - LogUtils.d(TAG, "initNotificationChannels: 执行通知渠道初始化"); + LogUtils.d(TAG, "initNotificationChannels() 执行通知渠道初始化"); // API<26 无渠道机制,直接返回 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { - LogUtils.d(TAG, "initNotificationChannels: API<26,无需创建渠道"); + LogUtils.d(TAG, "initNotificationChannels() API<26,无需创建渠道"); return; } // 通知服务为空,避免空指针 if (mNotificationManager == null) { - LogUtils.e(TAG, "initNotificationChannels: 失败:NotificationManager is null"); + LogUtils.e(TAG, "initNotificationChannels() 失败:NotificationManager is null"); return; } @@ -103,7 +104,7 @@ public class NotificationManagerUtils { foregroundChannel.setSound(null, null); // 强制无铃声 foregroundChannel.setShowBadge(false); foregroundChannel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); - LogUtils.d(TAG, "initNotificationChannels: 前台服务渠道配置完成"); + LogUtils.d(TAG, "initNotificationChannels() 前台服务渠道配置完成"); // 2. 电池提醒渠道(中优先级,系统默认铃声,无振动) NotificationChannel remindChannel = new NotificationChannel( @@ -117,27 +118,27 @@ public class NotificationManagerUtils { remindChannel.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION), Notification.AUDIO_ATTRIBUTES_DEFAULT); remindChannel.setShowBadge(false); remindChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC); - LogUtils.d(TAG, "initNotificationChannels: 电池提醒渠道配置完成"); + LogUtils.d(TAG, "initNotificationChannels() 电池提醒渠道配置完成"); - // 3. 应用配置信息渠道(新增:最低优先级,无铃声无振动,仅提示不打扰) + // 3. 应用配置信息渠道(方案1修复:默认优先级,系统默认铃声,无振动) NotificationChannel configChannel = new NotificationChannel( CHANNEL_ID_CONFIG, "应用配置信息", - NotificationManager.IMPORTANCE_MIN + NotificationManager.IMPORTANCE_DEFAULT ); - configChannel.setDescription("应用配置更新、参数变更等提示,无声音、无振动"); - configChannel.enableLights(false); + configChannel.setDescription("应用配置更新、参数变更等提示,系统默认铃声、无振动"); + configChannel.enableLights(true); configChannel.enableVibration(false); - configChannel.setSound(null, null); + configChannel.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION), Notification.AUDIO_ATTRIBUTES_DEFAULT); configChannel.setShowBadge(false); - configChannel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE); - LogUtils.d(TAG, "initNotificationChannels: 应用配置信息渠道配置完成"); + configChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC); + LogUtils.d(TAG, "initNotificationChannels() 应用配置信息渠道配置完成"); // 注册渠道到系统 mNotificationManager.createNotificationChannel(foregroundChannel); mNotificationManager.createNotificationChannel(remindChannel); mNotificationManager.createNotificationChannel(configChannel); // 注册新增渠道 - LogUtils.d(TAG, "initNotificationChannels: 成功:创建前台服务+电池提醒+应用配置信息渠道"); + LogUtils.d(TAG, "initNotificationChannels() 成功:创建前台服务+电池提醒+应用配置信息渠道"); } // ================================== 对外核心方法(前台服务通知:启动/更新/取消)================================= @@ -145,26 +146,26 @@ public class NotificationManagerUtils { * 启动前台服务通知(API30适配,无铃声) */ public void startForegroundServiceNotify(Service service, NotificationMessage message) { - LogUtils.d(TAG, "startForegroundServiceNotify: 执行 | notifyId=" + NOTIFY_ID_FOREGROUND_SERVICE + " | service=" + service + " | message=" + message); + LogUtils.d(TAG, "startForegroundServiceNotify() 执行 | notifyId=" + NOTIFY_ID_FOREGROUND_SERVICE + " | service=" + service + " | message=" + message); // 前置校验:参数非空 if (service == null || message == null || mNotificationManager == null) { - LogUtils.e(TAG, "startForegroundServiceNotify: 失败:param is null | service=" + service + " | message=" + message + " | mNotificationManager=" + mNotificationManager); + LogUtils.e(TAG, "startForegroundServiceNotify() 失败:param is null | service=" + service + " | message=" + message + " | mNotificationManager=" + mNotificationManager); return; } // 构建前台通知 mForegroundServiceNotify = buildForegroundNotification(message); if (mForegroundServiceNotify == null) { - LogUtils.e(TAG, "startForegroundServiceNotify: 失败:构建通知为空"); + LogUtils.e(TAG, "startForegroundServiceNotify() 失败:构建通知为空"); return; } // 启动前台服务(API30无FOREGROUND_SERVICE_TYPE限制,全版本通用) try { service.startForeground(NOTIFY_ID_FOREGROUND_SERVICE, mForegroundServiceNotify); - LogUtils.d(TAG, "startForegroundServiceNotify: 成功"); + LogUtils.d(TAG, "startForegroundServiceNotify() 成功"); } catch (Exception e) { - LogUtils.e(TAG, "startForegroundServiceNotify: 异常", e); + LogUtils.e(TAG, "startForegroundServiceNotify() 异常", e); } } @@ -172,23 +173,23 @@ public class NotificationManagerUtils { * 更新前台服务通知内容(复用通知ID,保持无铃声) */ public void updateForegroundServiceNotify(NotificationMessage message) { - LogUtils.d(TAG, "updateForegroundServiceNotify: 执行 | notifyId=" + NOTIFY_ID_FOREGROUND_SERVICE + " | message=" + message); + LogUtils.d(TAG, "updateForegroundServiceNotify() 执行 | notifyId=" + NOTIFY_ID_FOREGROUND_SERVICE + " | message=" + message); if (message == null || mNotificationManager == null) { - LogUtils.e(TAG, "updateForegroundServiceNotify: 失败:param is null | message=" + message + " | mNotificationManager=" + mNotificationManager); + LogUtils.e(TAG, "updateForegroundServiceNotify() 失败:param is null | message=" + message + " | mNotificationManager=" + mNotificationManager); return; } mForegroundServiceNotify = buildForegroundNotification(message); if (mForegroundServiceNotify == null) { - LogUtils.e(TAG, "updateForegroundServiceNotify: 失败:构建通知为空"); + LogUtils.e(TAG, "updateForegroundServiceNotify() 失败:构建通知为空"); return; } try { mNotificationManager.notify(NOTIFY_ID_FOREGROUND_SERVICE, mForegroundServiceNotify); - LogUtils.d(TAG, "updateForegroundServiceNotify: 成功"); + LogUtils.d(TAG, "updateForegroundServiceNotify() 成功"); } catch (Exception e) { - LogUtils.e(TAG, "updateForegroundServiceNotify: 异常", e); + LogUtils.e(TAG, "updateForegroundServiceNotify() 异常", e); } } @@ -196,10 +197,10 @@ public class NotificationManagerUtils { * 取消前台服务通知(Service销毁时调用) */ public void cancelForegroundServiceNotify() { - LogUtils.d(TAG, "cancelForegroundServiceNotify: 执行 | notifyId=" + NOTIFY_ID_FOREGROUND_SERVICE); + LogUtils.d(TAG, "cancelForegroundServiceNotify() 执行 | notifyId=" + NOTIFY_ID_FOREGROUND_SERVICE); cancelNotification(NOTIFY_ID_FOREGROUND_SERVICE); mForegroundServiceNotify = null; // 置空释放 - LogUtils.d(TAG, "cancelForegroundServiceNotify: 成功"); + LogUtils.d(TAG, "cancelForegroundServiceNotify() 成功"); } // ================================== 对外核心方法(电池提醒通知:发送)================================= @@ -207,48 +208,70 @@ public class NotificationManagerUtils { * 发送电池提醒通知(系统默认铃声,无振动) */ public void showRemindNotification(Context context, NotificationMessage message) { - LogUtils.d(TAG, "showRemindNotification: 执行 | notifyId=" + NOTIFY_ID_REMIND + " | context=" + context + " | message=" + message); + LogUtils.d(TAG, "showRemindNotification() 执行 | notifyId=" + NOTIFY_ID_REMIND + " | context=" + context + " | message=" + message); if (context == null || message == null || mNotificationManager == null) { - LogUtils.e(TAG, "showRemindNotification: 失败:param is null | context=" + context + " | message=" + message + " | mNotificationManager=" + mNotificationManager); + LogUtils.e(TAG, "showRemindNotification() 失败:param is null | context=" + context + " | message=" + message + " | mNotificationManager=" + mNotificationManager); return; } Notification remindNotify = buildRemindNotification(context, message); if (remindNotify == null) { - LogUtils.e(TAG, "showRemindNotification: 失败:构建通知为空"); + LogUtils.e(TAG, "showRemindNotification() 失败:构建通知为空"); return; } try { mNotificationManager.notify(NOTIFY_ID_REMIND, remindNotify); - LogUtils.d(TAG, "showRemindNotification: 成功"); + LogUtils.d(TAG, "showRemindNotification() 成功"); } catch (Exception e) { - LogUtils.e(TAG, "showRemindNotification: 异常", e); + LogUtils.e(TAG, "showRemindNotification() 异常", e); } } - // ================================== 对外核心方法(应用配置信息通知:发送)================================= - /** - * 发送应用配置信息通知(新增:低优先级无铃声,仅提示不打扰) - */ - public void showConfigNotification(Context context, NotificationMessage message) { - LogUtils.d(TAG, "showConfigNotification: 执行 | notifyId=" + NOTIFY_ID_CONFIG + " | context=" + context + " | message=" + message); + public synchronized void showMessageNotification(Context context, NotificationMessage message) { + snMessageNotificationID++; + LogUtils.d(TAG, "showMessageNotification() 执行 | notifyId=" + snMessageNotificationID + " | context=" + context + " | message=" + message); if (context == null || message == null || mNotificationManager == null) { - LogUtils.e(TAG, "showConfigNotification: 失败:param is null | context=" + context + " | message=" + message + " | mNotificationManager=" + mNotificationManager); + LogUtils.e(TAG, "showMessageNotification() 失败:param is null | context=" + context + " | message=" + message + " | mNotificationManager=" + mNotificationManager); return; } Notification configNotify = buildConfigNotification(context, message); if (configNotify == null) { - LogUtils.e(TAG, "showConfigNotification: 失败:构建通知为空"); + LogUtils.e(TAG, "showMessageNotification() 失败:构建通知为空"); + return; + } + + try { + mNotificationManager.notify(snMessageNotificationID, configNotify); + LogUtils.d(TAG, "showMessageNotification() 成功"); + } catch (Exception e) { + LogUtils.e(TAG, "showMessageNotification() 异常", e); + } + } + + // ================================== 对外核心方法(应用配置信息通知:发送)================================= + /** + * 发送应用配置信息通知(方案1修复:系统默认铃声,无振动) + */ + public void showConfigNotification(Context context, NotificationMessage message) { + LogUtils.d(TAG, "showConfigNotification() 执行 | notifyId=" + NOTIFY_ID_CONFIG + " | context=" + context + " | message=" + message); + if (context == null || message == null || mNotificationManager == null) { + LogUtils.e(TAG, "showConfigNotification() 失败:param is null | context=" + context + " | message=" + message + " | mNotificationManager=" + mNotificationManager); + return; + } + + Notification configNotify = buildConfigNotification(context, message); + if (configNotify == null) { + LogUtils.e(TAG, "showConfigNotification() 失败:构建通知为空"); return; } try { mNotificationManager.notify(NOTIFY_ID_CONFIG, configNotify); - LogUtils.d(TAG, "showConfigNotification: 成功"); + LogUtils.d(TAG, "showConfigNotification() 成功"); } catch (Exception e) { - LogUtils.e(TAG, "showConfigNotification: 异常", e); + LogUtils.e(TAG, "showConfigNotification() 异常", e); } } @@ -257,16 +280,16 @@ public class NotificationManagerUtils { * 取消指定ID的通知 */ public void cancelNotification(int notifyId) { - LogUtils.d(TAG, "cancelNotification: 执行 | notifyId=" + notifyId); + LogUtils.d(TAG, "cancelNotification() 执行 | notifyId=" + notifyId); if (mNotificationManager == null) { - LogUtils.e(TAG, "cancelNotification: 失败:NotificationManager is null"); + LogUtils.e(TAG, "cancelNotification() 失败:NotificationManager is null"); return; } try { mNotificationManager.cancel(notifyId); - LogUtils.d(TAG, "cancelNotification: 成功 | notifyId=" + notifyId); + LogUtils.d(TAG, "cancelNotification() 成功 | notifyId=" + notifyId); } catch (Exception e) { - LogUtils.e(TAG, "cancelNotification: 异常 | notifyId=" + notifyId, e); + LogUtils.e(TAG, "cancelNotification() 异常 | notifyId=" + notifyId, e); } } @@ -274,16 +297,16 @@ public class NotificationManagerUtils { * 取消所有通知(兜底场景使用) */ public void cancelAllNotifications() { - LogUtils.d(TAG, "cancelAllNotifications: 执行"); + LogUtils.d(TAG, "cancelAllNotifications() 执行"); if (mNotificationManager == null) { - LogUtils.e(TAG, "cancelAllNotifications: 失败:NotificationManager is null"); + LogUtils.e(TAG, "cancelAllNotifications() 失败:NotificationManager is null"); return; } try { mNotificationManager.cancelAll(); - LogUtils.d(TAG, "cancelAllNotifications: 成功"); + LogUtils.d(TAG, "cancelAllNotifications() 成功"); } catch (Exception e) { - LogUtils.e(TAG, "cancelAllNotifications: 异常", e); + LogUtils.e(TAG, "cancelAllNotifications() 异常", e); } } @@ -292,30 +315,30 @@ public class NotificationManagerUtils { * 构建前台服务通知(全版本无铃声+无振动) */ private Notification buildForegroundNotification(NotificationMessage message) { - LogUtils.d(TAG, "buildForegroundNotification: 执行 | message=" + message); + LogUtils.d(TAG, "buildForegroundNotification() 执行 | message=" + message); if (message == null || mContext == null) { - LogUtils.e(TAG, "buildForegroundNotification: 失败:param is null | message=" + message + " | mContext=" + mContext); + LogUtils.e(TAG, "buildForegroundNotification() 失败:param is null | message=" + message + " | mContext=" + mContext); return null; } // 内容兜底 String title = message.getTitle() != null && !message.getTitle().isEmpty() ? message.getTitle() : FOREGROUND_NOTIFY_TITLE_DEFAULT; String content = message.getContent() != null && !message.getContent().isEmpty() ? message.getContent() : FOREGROUND_NOTIFY_CONTENT_DEFAULT; - LogUtils.d(TAG, "buildForegroundNotification: 内容兜底完成 | title=" + title + " | content=" + content); + LogUtils.d(TAG, "buildForegroundNotification() 内容兜底完成 | title=" + title + " | content=" + content); Notification.Builder builder; // API分级构建 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // API26+:绑定前台渠道(渠道已配置无铃声) builder = new Notification.Builder(mContext, CHANNEL_ID_FOREGROUND); - LogUtils.d(TAG, "buildForegroundNotification: 使用API26+渠道构建"); + LogUtils.d(TAG, "buildForegroundNotification() 使用API26+渠道构建"); } else { // API<26:直接构建,手动禁用铃声振动 builder = new Notification.Builder(mContext); builder.setSound(null); builder.setVibrate(new long[]{0}); builder.setDefaults(0); - LogUtils.d(TAG, "buildForegroundNotification: 使用API<26手动配置"); + LogUtils.d(TAG, "buildForegroundNotification() 使用API<26手动配置"); } // 通用配置 @@ -332,11 +355,11 @@ public class NotificationManagerUtils { builder.setLargeIcon(getAppIcon(mContext)) .setColor(mContext.getResources().getColor(R.color.colorPrimary)) .setPriority(Notification.PRIORITY_LOW); - LogUtils.d(TAG, "buildForegroundNotification: 补充API21+配置"); + LogUtils.d(TAG, "buildForegroundNotification() 补充API21+配置"); } Notification notification = builder.build(); - LogUtils.d(TAG, "buildForegroundNotification: 成功构建前台通知"); + LogUtils.d(TAG, "buildForegroundNotification() 成功构建前台通知"); return notification; } @@ -345,30 +368,30 @@ public class NotificationManagerUtils { * 构建电池提醒通知(全版本系统默认铃声+无振动) */ private Notification buildRemindNotification(Context context, NotificationMessage message) { - LogUtils.d(TAG, "buildRemindNotification: 执行 | context=" + context + " | message=" + message); + LogUtils.d(TAG, "buildRemindNotification() 执行 | context=" + context + " | message=" + message); if (context == null || message == null) { - LogUtils.e(TAG, "buildRemindNotification: 失败:param is null | context=" + context + " | message=" + message); + LogUtils.e(TAG, "buildRemindNotification() 失败:param is null | context=" + context + " | message=" + message); return null; } // 内容兜底 String title = message.getTitle() != null && !message.getTitle().isEmpty() ? message.getTitle() : REMIND_NOTIFY_TITLE_DEFAULT; String content = message.getContent() != null && !message.getContent().isEmpty() ? message.getContent() : REMIND_NOTIFY_CONTENT_DEFAULT; - LogUtils.d(TAG, "buildRemindNotification: 内容兜底完成 | title=" + title + " | content=" + content); + LogUtils.d(TAG, "buildRemindNotification() 内容兜底完成 | title=" + title + " | content=" + content); Notification.Builder builder; // API分级构建 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // API26+:绑定提醒渠道(渠道已配置默认铃声) builder = new Notification.Builder(context, CHANNEL_ID_REMIND); - LogUtils.d(TAG, "buildRemindNotification: 使用API26+渠道构建"); + LogUtils.d(TAG, "buildRemindNotification() 使用API26+渠道构建"); } else { // API<26:手动配置默认铃声,关闭振动 builder = new Notification.Builder(context); builder.setSound(Settings.System.DEFAULT_NOTIFICATION_URI) // 显式默认铃声 .setVibrate(new long[]{0}) .setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_SOUND); - LogUtils.d(TAG, "buildRemindNotification: 使用API<26手动配置"); + LogUtils.d(TAG, "buildRemindNotification() 使用API<26手动配置"); } // 通用配置 @@ -386,43 +409,43 @@ public class NotificationManagerUtils { builder.setLargeIcon(getAppIcon(context)) .setColor(context.getResources().getColor(R.color.colorPrimary)) .setPriority(Notification.PRIORITY_DEFAULT); - LogUtils.d(TAG, "buildRemindNotification: 补充API21+配置"); + LogUtils.d(TAG, "buildRemindNotification() 补充API21+配置"); } Notification notification = builder.build(); - LogUtils.d(TAG, "buildRemindNotification: 成功构建提醒通知"); + LogUtils.d(TAG, "buildRemindNotification() 成功构建提醒通知"); return notification; } // ================================== 内部辅助方法(通知构建:应用配置信息通知)================================= /** - * 构建应用配置信息通知(新增:全版本无铃声+无振动,低优先级) + * 构建应用配置信息通知(方案1修复:全版本系统默认铃声+无振动) */ private Notification buildConfigNotification(Context context, NotificationMessage message) { - LogUtils.d(TAG, "buildConfigNotification: 执行 | context=" + context + " | message=" + message); + LogUtils.d(TAG, "buildConfigNotification() 执行 | context=" + context + " | message=" + message); if (context == null || message == null) { - LogUtils.e(TAG, "buildConfigNotification: 失败:param is null | context=" + context + " | message=" + message); + LogUtils.e(TAG, "buildConfigNotification() 失败:param is null | context=" + context + " | message=" + message); return null; } // 内容兜底 String title = message.getTitle() != null && !message.getTitle().isEmpty() ? message.getTitle() : CONFIG_NOTIFY_TITLE_DEFAULT; String content = message.getContent() != null && !message.getContent().isEmpty() ? message.getContent() : CONFIG_NOTIFY_CONTENT_DEFAULT; - LogUtils.d(TAG, "buildConfigNotification: 内容兜底完成 | title=" + title + " | content=" + content); + LogUtils.d(TAG, "buildConfigNotification() 内容兜底完成 | title=" + title + " | content=" + content); Notification.Builder builder; // API分级构建 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - // API26+:绑定配置渠道(渠道已配置无铃声) + // API26+:绑定配置渠道(渠道已配置默认铃声) builder = new Notification.Builder(context, CHANNEL_ID_CONFIG); - LogUtils.d(TAG, "buildConfigNotification: 使用API26+渠道构建"); + LogUtils.d(TAG, "buildConfigNotification() 使用API26+渠道构建"); } else { - // API<26:直接构建,手动禁用铃声振动 + // API<26:手动配置默认铃声,关闭振动(方案1修复:保留铃声配置,删除冗余DEFAULT_SOUND) builder = new Notification.Builder(context); - builder.setSound(null); + builder.setSound(Settings.System.DEFAULT_NOTIFICATION_URI); builder.setVibrate(new long[]{0}); - builder.setDefaults(0); - LogUtils.d(TAG, "buildConfigNotification: 使用API<26手动配置"); + builder.setDefaults(Notification.DEFAULT_LIGHTS); + LogUtils.d(TAG, "buildConfigNotification() 使用API<26手动配置"); } // 通用配置 @@ -438,12 +461,12 @@ public class NotificationManagerUtils { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { builder.setLargeIcon(getAppIcon(context)) .setColor(context.getResources().getColor(R.color.colorPrimary)) - .setPriority(Notification.PRIORITY_MIN); // 最低优先级 - LogUtils.d(TAG, "buildConfigNotification: 补充API21+配置"); + .setPriority(Notification.PRIORITY_DEFAULT); + LogUtils.d(TAG, "buildConfigNotification() 补充API21+配置"); } Notification notification = builder.build(); - LogUtils.d(TAG, "buildConfigNotification: 成功构建配置信息通知"); + LogUtils.d(TAG, "buildConfigNotification() 成功构建配置信息通知"); return notification; } @@ -452,20 +475,20 @@ public class NotificationManagerUtils { * 创建跳转MainActivity的PendingIntent,API23+ 添加IMMUTABLE标记(避免安全异常) */ private PendingIntent createJumpPendingIntent(Context context, int requestCode) { - LogUtils.d(TAG, "createJumpPendingIntent: 执行 | requestCode=" + requestCode + " | context=" + context); + LogUtils.d(TAG, "createJumpPendingIntent() 执行 | requestCode=" + requestCode + " | context=" + context); Intent intent = new Intent(context, MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); - LogUtils.d(TAG, "createJumpPendingIntent: 跳转Intent配置完成"); + LogUtils.d(TAG, "createJumpPendingIntent() 跳转Intent配置完成"); // API23+ 必需添加IMMUTABLE,适配API30安全规范 int flags = PendingIntent.FLAG_UPDATE_CURRENT; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { flags |= PendingIntent.FLAG_IMMUTABLE; - LogUtils.d(TAG, "createJumpPendingIntent: 添加FLAG_IMMUTABLE标记(API23+)"); + LogUtils.d(TAG, "createJumpPendingIntent() 添加FLAG_IMMUTABLE标记(API23+)"); } PendingIntent pendingIntent = PendingIntent.getActivity(context, requestCode, intent, flags); - LogUtils.d(TAG, "createJumpPendingIntent: 成功 | requestCode=" + requestCode); + LogUtils.d(TAG, "createJumpPendingIntent() 成功 | requestCode=" + requestCode); return pendingIntent; } @@ -474,14 +497,14 @@ public class NotificationManagerUtils { * 获取APP图标,失败返回默认图标 */ private Bitmap getAppIcon(Context context) { - LogUtils.d(TAG, "getAppIcon: 执行 | context=" + context); + LogUtils.d(TAG, "getAppIcon() 执行 | context=" + context); try { PackageInfo pkgInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); Bitmap appIcon = BitmapFactory.decodeResource(context.getResources(), pkgInfo.applicationInfo.icon); - LogUtils.d(TAG, "getAppIcon: 成功:获取应用图标"); + LogUtils.d(TAG, "getAppIcon() 成功:获取应用图标"); return appIcon; } catch (PackageManager.NameNotFoundException e) { - LogUtils.e(TAG, "getAppIcon: 异常:获取应用图标失败,使用默认图标", e); + LogUtils.e(TAG, "getAppIcon() 异常:获取应用图标失败,使用默认图标", e); return BitmapFactory.decodeResource(context.getResources(), NOTIFICATION_DEFAULT_ICON); } } @@ -491,11 +514,11 @@ public class NotificationManagerUtils { * 释放资源,销毁时调用 */ public void release() { - LogUtils.d(TAG, "release: 执行资源释放"); + LogUtils.d(TAG, "release() 执行资源释放"); cancelForegroundServiceNotify(); mNotificationManager = null; mContext = null; - LogUtils.d(TAG, "release: 成功:所有资源已释放"); + LogUtils.d(TAG, "release() 成功:所有资源已释放"); } // ================================== 对外 getter 方法(仅前台通知实例,只读)================================= 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 2a17c8d..e1a6a40 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 @@ -17,9 +17,11 @@ import android.widget.TextView; import cc.winboll.studio.libappbase.LogUtils; import cc.winboll.studio.powerbell.App; import cc.winboll.studio.powerbell.R; +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.utils.AppConfigUtils; +import cc.winboll.studio.powerbell.utils.BackgroundSourceUtils; /** * 主页面核心视图封装类:统一管理视图绑定、数据更新、事件监听,解耦 Activity 逻辑 @@ -151,13 +153,20 @@ 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.sMemoryCachedBackgroundView.getLastInstance(mContext); + if (backgroundView == null) { + App.sBackgroundSourceUtils.loadSettings(); + BackgroundBean backgroundBean = App.sBackgroundSourceUtils.getCurrentBackgroundBean(); + backgroundView = App.sMemoryCachedBackgroundView.getInstance(mContext, backgroundBean, true); + } if (backgroundView.getParent() != null) { ((ViewGroup) backgroundView.getParent()).removeView(backgroundView); LogUtils.d(TAG, "【bindViews】移除背景视图旧父容器"); } mllBackgroundView.addView(backgroundView); - // 容器布局绑定 + + // 容器布局绑定 llLeftSeekBar = (LinearLayout) rootView.findViewById(R.id.fragmentmainviewLinearLayout1); llRightSeekBar = (LinearLayout) rootView.findViewById(R.id.fragmentmainviewLinearLayout2); // 开关控件绑定 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 be810fe..46377a2 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 @@ -58,36 +58,27 @@ public class MemoryCachedBackgroundView extends BackgroundView { * @param isReload 是否强制重新加载图片(路径匹配时仍刷新) * @return 缓存/新创建的MemoryCachedBackgroundView实例 */ - public static MemoryCachedBackgroundView getInstance(Context context, int bgColor, String imagePath, boolean isReload) { - LogUtils.d(TAG, String.format("getInstance 调用 | 图片路径=%s | 是否重载=%b", imagePath, isReload)); - // 空路径校验 - if (TextUtils.isEmpty(imagePath)) { - LogUtils.e(TAG, "getInstance: 图片路径为空,创建空实例"); - return new MemoryCachedBackgroundView(context); - } - - // 1. 路径匹配缓存 → 判断是否强制重载 - if (imagePath.equals(sCachedImagePath) && sCachedView != null) { - LogUtils.d(TAG, "getInstance: 路径已缓存,当前缓存实例有效"); - if (isReload) { - LogUtils.d(TAG, String.format("getInstance: 强制重载图片 | 路径=%s", imagePath)); - sCachedView.loadImage(bgColor, imagePath, isReload); - } else { - LogUtils.d(TAG, String.format("getInstance: 使用缓存实例,无需重载 | 路径=%s", imagePath)); - } - return sCachedView; - } - - // 2. 路径不匹配/无缓存 → 新建实例并更新静态缓存(核心:保留旧实例,仅更新引用) - LogUtils.d(TAG, String.format("getInstance: 路径未缓存,新建实例(保留旧实例) | 路径=%s", imagePath)); - String oldPath = sCachedImagePath; + public static MemoryCachedBackgroundView getInstance(Context context, BackgroundBean bean, boolean isReload) { + LogUtils.d(TAG, String.format("getInstance 调用 | BackgroundBean=%s | 是否重载=%b", bean.toString(), isReload)); + //App.notifyMessage(TAG, String.format("getInstance 调用 | BackgroundBean=%s | 是否重载=%b", bean.toString(), isReload)); sCachedView = new MemoryCachedBackgroundView(context); - sCachedImagePath = imagePath; - sCachedView.loadImage(bgColor, imagePath, isReload); - LogUtils.d(TAG, String.format("getInstance: 已更新当前缓存实例,旧实例路径=%s(强制保持)", oldPath)); + 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))); return sCachedView; } + static String getBackgroundBeanImagePath(BackgroundBean bean) { + if (bean.isUseBackgroundFile()) { + if (bean.isUseBackgroundScaledCompressFile()) { + return bean.getBackgroundScaledCompressFilePath(); + } + return bean.getBackgroundFilePath(); + } + return ""; + } + // ====================================== 新增功能:获取最后加载的实例(强制缓存版) ====================================== /** * 获取最后一次loadImage的路径对应的实例(强制保持所有实例) @@ -97,28 +88,19 @@ public class MemoryCachedBackgroundView extends BackgroundView { */ public static MemoryCachedBackgroundView getLastInstance(Context context) { LogUtils.d(TAG, "getLastInstance 调用"); + //App.notifyMessage(TAG, "getLastInstance 调用"); // 1. 从SP获取最后加载的路径(强制保持,不自动删除) - String lastPath = getLastLoadImagePath(context); - if (TextUtils.isEmpty(lastPath)) { - LogUtils.e(TAG, "getLastInstance: 无最后加载路径,创建空实例"); - return new MemoryCachedBackgroundView(context); - } - - // 2. 路径匹配当前缓存 → 直接返回 + sCachedImagePath = getLastLoadImagePath(context); + String lastPath = getBackgroundBeanImagePath(App.sBackgroundSourceUtils.getCurrentBackgroundBean()); + //App.notifyMessage(TAG, String.format("sCachedImagePath : %s", sCachedImagePath)); + //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)); return sCachedView; } - - // 3. 路径不匹配 → 新建实例并更新缓存(保留旧实例) - LogUtils.d(TAG, String.format("getLastInstance: 最后路径未缓存,新建实例并加载(保留旧实例) | 路径=%s", lastPath)); - String oldPath = sCachedImagePath; - sCachedView = new MemoryCachedBackgroundView(context); - sCachedImagePath = lastPath; - int nCurrentPixelColor = BackgroundSourceUtils.getInstance(context).getCurrentBackgroundBean().getPixelColor(); - sCachedView.loadImage(nCurrentPixelColor, sCachedImagePath, false); - LogUtils.d(TAG, String.format("getLastInstance: 已更新最后路径实例,旧实例路径=%s(强制保持)", oldPath)); - return sCachedView; + App.notifyMessage(TAG, "getLastInstance 返回 null"); + return null; } // ====================================== 工具方法:SP持久化最后加载路径(强制保持版) ======================================