diff --git a/powerbell/build.properties b/powerbell/build.properties index 9053a48..70f689a 100644 --- a/powerbell/build.properties +++ b/powerbell/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Sun Dec 21 13:40:20 HKT 2025 +#Sun Dec 21 09:35:54 GMT 2025 stageCount=16 libraryProject= baseVersion=15.14 publishVersion=15.14.15 -buildCount=0 +buildCount=5 baseBetaVersion=15.14.16 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 0cc2dd7..459ff8b 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/App.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/App.java @@ -9,220 +9,330 @@ 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.BackgroundBean; 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 java.io.File; +import java.util.concurrent.TimeUnit; +/** + * 应用全局入口类(适配Android API 30,基于Java 7编写) + */ public class App extends GlobalApplication { + // ===================== 常量定义区 ===================== public static final String TAG = "App"; + // 组件跳转常量 public static final String COMPONENT_EN1 = "cc.winboll.studio.powerbell.MainActivityEN1"; public static final String COMPONENT_CN1 = "cc.winboll.studio.powerbell.MainActivityCN1"; public static final String COMPONENT_CN2 = "cc.winboll.studio.powerbell.MainActivityCN2"; + + // 动作跳转常量 public static final String ACTION_SWITCHTO_EN1 = "cc.winboll.studio.powerbell.App.ACTION_SWITCHTO_EN1"; public static final String ACTION_SWITCHTO_CN1 = "cc.winboll.studio.powerbell.App.ACTION_SWITCHTO_CN1"; public static final String ACTION_SWITCHTO_CN2 = "cc.winboll.studio.powerbell.App.ACTION_SWITCHTO_CN2"; - // 内存紧张通知常量 + // 内存紧张通知文案常量 private static final String TRIM_MEMORY_NOTIFY_TITLE = "应用使用时内存紧张提醒"; private static final String TRIM_MEMORY_NOTIFY_CONTENT = "由于本应用使用时,系统通知内存紧张程度级别较高,图片缓存功能暂时不启用。"; - // 数据配置存储工具 - static AppConfigUtils _mAppConfigUtils; - static AppCacheUtils _mAppCacheUtils; - // 全局 Bitmap 缓存工具(常驻内存) - public static BitmapCacheUtils _mBitmapCacheUtils; + // 定时任务间隔常量(分钟) + private static final long TIMER_INTERVAL_MINUTES = 1; - GlobalApplicationReceiver mReceiver; - static String szTempDir = ""; - // 通知工具类实例(用于发送内存紧张通知) + // ===================== 静态属性区 ===================== + // 数据配置工具 + private static AppConfigUtils sAppConfigUtils; + private static AppCacheUtils sAppCacheUtils; + // 全局Bitmap缓存工具 + public static BitmapCacheUtils sBitmapCacheUtils; + // 临时文件夹路径 + private static String sTempDirPath = ""; + + // 定时任务静态属性(全局唯一) + private static Handler sTimerHandler; + private static Runnable sTimerRunnable; + private static boolean sIsTimerRunning = false; + + // ===================== 成员属性区 ===================== + // 全局广播接收器 + private GlobalApplicationReceiver mGlobalReceiver; + // 通知管理工具 private NotificationManagerUtils mNotificationManager; + // ===================== 公共方法区 ===================== + /** + * 获取临时文件夹路径 + */ public static String getTempDirPath() { - return szTempDir; + return sTempDirPath; } + /** + * 获取应用配置工具实例 + */ + public static AppConfigUtils getAppConfigUtils(Context context) { + LogUtils.d(TAG, "getAppConfigUtils() 调用,传入Context:" + context.getClass().getSimpleName()); + if (sAppConfigUtils == null) { + sAppConfigUtils = AppConfigUtils.getInstance(context); + LogUtils.d(TAG, "getAppConfigUtils():AppConfigUtils实例已初始化"); + } + return sAppConfigUtils; + } + + /** + * 获取应用缓存工具实例 + */ + public static AppCacheUtils getAppCacheUtils(Context context) { + LogUtils.d(TAG, "getAppCacheUtils() 调用,传入Context:" + context.getClass().getSimpleName()); + if (sAppCacheUtils == null) { + sAppCacheUtils = AppCacheUtils.getInstance(context); + LogUtils.d(TAG, "getAppCacheUtils():AppCacheUtils实例已初始化"); + } + return sAppCacheUtils; + } + + /** + * 清除电池历史数据 + */ + public void clearBatteryHistory() { + LogUtils.d(TAG, "clearBatteryHistory() 调用"); + sAppCacheUtils.clearBatteryHistory(); + } + + // ===================== 生命周期方法区 ===================== @Override public void onCreate() { super.onCreate(); + LogUtils.d(TAG, "onCreate() 应用启动,开始初始化"); + + // 初始化调试模式 setIsDebugging(BuildConfig.DEBUG); + LogUtils.d(TAG, "onCreate() 调试模式:" + BuildConfig.DEBUG); - // 初始化活动窗口管理 - WinBoLLActivityManager.init(this); - // 初始化 Toast 框架 - ToastUtils.init(this); + // 初始化基础工具 + initBaseTools(); + // 初始化临时文件夹 + initTempDir(); + // 初始化工具类实例 + initUtils(); + // 初始化广播接收器 + initReceiver(); + // 启动定时任务 + initTimerTask(); - // 临时文件夹初始化(保持原有逻辑) - File picturesDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); - File powerBellDir = new File(picturesDir, "PowerBell"); - if (!powerBellDir.exists()) { - powerBellDir.mkdirs(); - } - szTempDir = powerBellDir.getAbsolutePath(); - - // 设置数据配置存储工具 - _mAppConfigUtils = getAppConfigUtils(this); - _mAppCacheUtils = getAppCacheUtils(this); - // 初始化全局 Bitmap 缓存工具 - _mBitmapCacheUtils = BitmapCacheUtils.getInstance(); - - // 初始化通知工具类(使用整理后的 NotificationManagerUtils) - mNotificationManager = new NotificationManagerUtils(this); - LogUtils.d(TAG, "onCreate: 通知工具类初始化完成"); - - mReceiver = new GlobalApplicationReceiver(this); - mReceiver.registerAction(); - - // 异步预加载背景图(保持原有逻辑) - new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { - @Override - public void run() { - new Thread(new Runnable() { - @Override - public void run() { - try { - BackgroundSourceUtils bgSourceUtils = BackgroundSourceUtils.getInstance(App.this); - if (bgSourceUtils == null) { - LogUtils.e(TAG, "preloadBitmap: BackgroundSourceUtils 实例为空"); - return; - } - BackgroundBean bgBean = bgSourceUtils.getCurrentBackgroundBean(); - if (bgBean == null || !bgBean.isUseBackgroundFile()) { - LogUtils.d(TAG, "preloadBitmap: 无有效背景文件,跳过预加载"); - return; - } - String bgPath = bgBean.isUseBackgroundScaledCompressFile() - ? bgBean.getBackgroundScaledCompressFilePath() - : bgBean.getBackgroundFilePath(); - if (_mBitmapCacheUtils != null) { - _mBitmapCacheUtils.cacheBitmap(bgPath); - LogUtils.d(TAG, "preloadBitmap: 应用启动时预加载成功 - " + bgPath); - } else { - LogUtils.e(TAG, "preloadBitmap: 全局 BitmapCacheUtils 未初始化"); - } - } catch (Exception e) { - LogUtils.e(TAG, "preloadBitmap: 预加载失败 - " + e.getMessage()); - } - } - }).start(); - } - }, 1000); - } - - // 保持原有方法不变 - public static AppConfigUtils getAppConfigUtils(Context context) { - if (_mAppConfigUtils == null) { - _mAppConfigUtils = AppConfigUtils.getInstance(context); - } - return _mAppConfigUtils; - } - - public static AppCacheUtils getAppCacheUtils(Context context) { - if (_mAppCacheUtils == null) { - _mAppCacheUtils = AppCacheUtils.getInstance(context); - } - return _mAppCacheUtils; - } - - public void clearBatteryHistory() { - _mAppCacheUtils.clearBatteryHistory(); + LogUtils.d(TAG, "onCreate() 应用初始化完成"); } @Override public void onTerminate() { super.onTerminate(); + LogUtils.d(TAG, "onTerminate() 应用终止,开始释放资源"); + + // 释放Toast工具 ToastUtils.release(); - // 释放通知工具类资源,避免内存泄漏 + // 释放通知工具 + releaseNotificationManager(); + // 停止定时任务 + stopTimerTask(); + + LogUtils.d(TAG, "onTerminate() 应用资源释放完成"); + } + + @Override + public void onTrimMemory(int level) { + super.onTrimMemory(level); + LogUtils.d(TAG, "onTrimMemory() 调用,内存等级level:" + level); + + // 初始化通知工具(若未初始化) + if (mNotificationManager == null) { + mNotificationManager = new NotificationManagerUtils(this); + LogUtils.d(TAG, "onTrimMemory():NotificationManagerUtils实例已初始化"); + } + + // 内存紧张等级判断 + if (level > ComponentCallbacks2.TRIM_MEMORY_MODERATE) { + sendTrimMemoryNotification(level); + } else { + sBitmapCacheUtils = BitmapCacheUtils.getInstance(); + LogUtils.d(TAG, "onTrimMemory():Bitmap缓存已启用"); + } + } + + // ===================== 私有初始化方法区 ===================== + /** + * 初始化基础工具(Activity管理、Toast) + */ + private void initBaseTools() { + LogUtils.d(TAG, "initBaseTools() 开始初始化基础工具"); + WinBoLLActivityManager.init(this); + ToastUtils.init(this); + LogUtils.d(TAG, "initBaseTools() 基础工具初始化完成"); + } + + /** + * 初始化临时文件夹(适配API 30外部存储访问) + */ + private void initTempDir() { + LogUtils.d(TAG, "initTempDir() 开始初始化临时文件夹"); + File picturesDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); + File powerBellDir = new File(picturesDir, "PowerBell"); + if (!powerBellDir.exists()) { + boolean isMkSuccess = powerBellDir.mkdirs(); + LogUtils.d(TAG, "initTempDir() 文件夹创建结果:" + isMkSuccess); + } + sTempDirPath = powerBellDir.getAbsolutePath(); + LogUtils.d(TAG, "initTempDir() 临时文件夹路径:" + sTempDirPath); + } + + /** + * 初始化工具类实例 + */ + private void initUtils() { + LogUtils.d(TAG, "initUtils() 开始初始化工具类"); + sAppConfigUtils = getAppConfigUtils(this); + sAppCacheUtils = getAppCacheUtils(this); + sBitmapCacheUtils = BitmapCacheUtils.getInstance(); + mNotificationManager = new NotificationManagerUtils(this); + LogUtils.d(TAG, "initUtils() 工具类初始化完成"); + } + + /** + * 初始化广播接收器 + */ + private void initReceiver() { + LogUtils.d(TAG, "initReceiver() 开始初始化广播接收器"); + mGlobalReceiver = new GlobalApplicationReceiver(this); + mGlobalReceiver.registerAction(); + LogUtils.d(TAG, "initReceiver() 广播接收器注册完成"); + } + + /** + * 初始化定时任务(全局唯一实例) + */ + private void initTimerTask() { + LogUtils.d(TAG, "initTimerTask() 开始初始化定时任务,当前运行状态:" + sIsTimerRunning); + + // 已运行则直接返回 + if (sIsTimerRunning) { + LogUtils.d(TAG, "initTimerTask() 定时任务已在运行,无需重复启动"); + return; + } + + // 初始化Handler + if (sTimerHandler == null) { + sTimerHandler = new Handler(Looper.getMainLooper()); + LogUtils.d(TAG, "initTimerTask() 定时任务Handler已初始化"); + } + + // 初始化Runnable + if (sTimerRunnable == null) { + sTimerRunnable = new Runnable() { + @Override + public void run() { + try { + LogUtils.d(TAG, "定时任务执行,间隔:" + TIMER_INTERVAL_MINUTES + "分钟"); + sBitmapCacheUtils = BitmapCacheUtils.getInstance(); + LogUtils.d(TAG, "定时任务:Bitmap缓存已重新初始化"); + } catch (Exception e) { + LogUtils.e(TAG, "定时任务执行异常:" + e.getMessage()); + } finally { + if (sIsTimerRunning) { + long delayMillis = TimeUnit.MINUTES.toMillis(TIMER_INTERVAL_MINUTES); + sTimerHandler.postDelayed(this, delayMillis); + LogUtils.d(TAG, "定时任务已预约下次执行,延迟:" + delayMillis + "ms"); + } + } + } + }; + LogUtils.d(TAG, "initTimerTask() 定时任务Runnable已初始化"); + } + + // 启动任务 + sTimerHandler.post(sTimerRunnable); + sIsTimerRunning = true; + LogUtils.d(TAG, "initTimerTask() 定时任务已启动,间隔:" + TIMER_INTERVAL_MINUTES + "分钟"); + } + + // ===================== 私有工具方法区 ===================== + /** + * 停止定时任务 + */ + private void stopTimerTask() { + LogUtils.d(TAG, "stopTimerTask() 开始停止定时任务"); + if (sTimerHandler != null && sTimerRunnable != null) { + sTimerHandler.removeCallbacks(sTimerRunnable); + sIsTimerRunning = false; + LogUtils.d(TAG, "stopTimerTask() 定时任务已停止,运行状态重置为false"); + } else { + LogUtils.d(TAG, "stopTimerTask() 定时任务未初始化,无需停止"); + } + } + + /** + * 释放通知管理工具资源 + */ + private void releaseNotificationManager() { + LogUtils.d(TAG, "releaseNotificationManager() 开始释放通知工具"); if (mNotificationManager != null) { mNotificationManager.release(); mNotificationManager = null; - LogUtils.d(TAG, "onTerminate: 通知工具类资源已释放"); + LogUtils.d(TAG, "releaseNotificationManager() 通知工具资源已释放"); + } else { + LogUtils.d(TAG, "releaseNotificationManager() 通知工具未初始化,无需释放"); } } - @Override - public void onTrimMemory(int level) { - super.onTrimMemory(level); - LogUtils.d(TAG, "onTrimMemory: 内存等级变化 | level=" + getTrimMemoryLevelDesc(level)); - - // 仅在中等及以上内存紧张等级发送通知,避免频繁打扰 - if (mNotificationManager == null) { - mNotificationManager = new NotificationManagerUtils(this); - } - if (level > ComponentCallbacks2.TRIM_MEMORY_MODERATE) { - sendTrimMemoryNotification(level); - } else { - // 再次缓存 Bitmap 缓存工具 - _mBitmapCacheUtils = BitmapCacheUtils.getInstance(); - LogUtils.d(TAG, "Bitmap 缓存启用中。"); - } - } - /** - * 发送内存紧张通知(完全复用 NotificationManagerUtils 的 showRemindNotification 方法) + * 发送内存紧张通知 */ private void sendTrimMemoryNotification(int level) { - LogUtils.d(TAG, "sendTrimMemoryNotification: 准备发送内存紧张通知"); - // 构建通知消息体 + LogUtils.d(TAG, "sendTrimMemoryNotification() 调用,内存等级level:" + level); NotificationMessage message = new NotificationMessage(); message.setTitle(TRIM_MEMORY_NOTIFY_TITLE); - message.setContent(String.format("%s [ 缓存紧张级别描述: Level %d | %s ]",TRIM_MEMORY_NOTIFY_CONTENT, level, getTrimMemoryLevelDesc(level))); - // 使用整理后的 NotificationManagerUtils 发送通知(复用提醒渠道配置) + String content = String.format("%s [ 缓存紧张级别描述: Level %d | %s ]", + TRIM_MEMORY_NOTIFY_CONTENT, level, getTrimMemoryLevelDesc(level)); + message.setContent(content); mNotificationManager.showConfigNotification(this, message); - LogUtils.d(TAG, "sendTrimMemoryNotification: 通知已通过 NotificationManagerUtils 发送"); + LogUtils.d(TAG, "sendTrimMemoryNotification() 内存紧张通知已发送,内容:" + content); } - /** - * 转换内存等级为可读描述,便于日志调试 - * 排序规则:按 ComponentCallbacks2 枚举数值从高到低排列(数值越高,内存越紧张) - */ - /** - * 转换内存等级为可读描述,便于日志调试 - * 排序规则:按 ComponentCallbacks2 枚举实际数值(10进制)从高到低排列 - * 数值来源:接口中定义的 16进制(注释10进制)数值 - */ - private String getTrimMemoryLevelDesc(int level) { - switch (level) { - // 数值 80(0x50):应用内存完全紧张(补充接口中实际存在的枚举项) - case ComponentCallbacks2.TRIM_MEMORY_COMPLETE: - return "TRIM_MEMORY_COMPLETE(应用内存完全紧张)"; - // 数值 60(0x3c):中等内存紧张 - case ComponentCallbacks2.TRIM_MEMORY_MODERATE: - return "MODERATE(中等内存紧张)"; - // 数值 40(0x28):应用进入后台 - case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND: - return "BACKGROUND(应用进入后台)"; - // 数值 20(0x14):应用UI隐藏 - case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN: - return "BACKGROUND(应用UI隐藏)"; - // 数值 15(0xf):应用运行时关键级紧张 - case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL: - return "RUNNING_CRITICAL(应用运行关键级紧张)"; - // 数值 10(0xa):应用运行时低内存 - case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW: - return "RUNNING_LOW(应用运行低内存)"; - // 数值 5(0x5):应用运行时中等紧张 - case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE: - return "RUNNING_MODERATE(应用运行中等内存紧张)"; - - // 以下为注释备用项(接口中未提供,按你的原有注释保留) - // 数值 100:内存极度紧张(系统可能强制杀死应用) - // case ComponentCallbacks2.TRIM_MEMORY_URGENT: - // return "URGENT(内存极度紧张)"; - // 数值 20:用户正在离开应用(如按Home键) - // case ComponentCallbacks2.TRIM_MEMORY_USER_LEAVING: - // return "USER_LEAVING(用户正在离开应用)"; - - // 未知等级 - default: - return "UNKNOWN(" + level + ")"; - } - } + /** + * 转换内存等级为可读描述 + */ + private String getTrimMemoryLevelDesc(int level) { + LogUtils.d(TAG, "getTrimMemoryLevelDesc() 调用,传入level:" + level); + String desc; + switch (level) { + case ComponentCallbacks2.TRIM_MEMORY_COMPLETE: + desc = "TRIM_MEMORY_COMPLETE(应用内存完全紧张)"; + break; + case ComponentCallbacks2.TRIM_MEMORY_MODERATE: + desc = "MODERATE(中等内存紧张)"; + break; + case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND: + desc = "BACKGROUND(应用进入后台)"; + break; + case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN: + desc = "BACKGROUND(应用UI隐藏)"; + break; + case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL: + desc = "RUNNING_CRITICAL(应用运行关键级紧张)"; + break; + case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW: + desc = "RUNNING_LOW(应用运行低内存)"; + break; + case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE: + desc = "RUNNING_MODERATE(应用运行中等内存紧张)"; + break; + default: + desc = "UNKNOWN(" + level + ")"; + break; + } + LogUtils.d(TAG, "getTrimMemoryLevelDesc() 内存等级描述结果:" + desc); + return desc; + } } diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/views/BackgroundView.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/views/BackgroundView.java index dec7eb1..016ebc9 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/views/BackgroundView.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/views/BackgroundView.java @@ -124,8 +124,8 @@ public class BackgroundView extends RelativeLayout { // 调用带路径判断的loadImage方法 if (isRefresh) { - App._mBitmapCacheUtils.removeCachedBitmap(targetPath); - App._mBitmapCacheUtils.cacheBitmap(targetPath); + App.sBitmapCacheUtils.removeCachedBitmap(targetPath); + App.sBitmapCacheUtils.cacheBitmap(targetPath); } loadImage(targetPath); } @@ -154,7 +154,7 @@ public class BackgroundView extends RelativeLayout { // ======================== 新增:路径判断逻辑 ======================== // 1. 路径未变化:直接使用缓存 if (imagePath.equals(mCurrentCachedPath)) { - Bitmap cachedBitmap = App._mBitmapCacheUtils.getCachedBitmap(imagePath); + Bitmap cachedBitmap = App.sBitmapCacheUtils.getCachedBitmap(imagePath); // 核心修改:判断缓存Bitmap是否为null if (cachedBitmap != null && !cachedBitmap.isRecycled()) { LogUtils.d(TAG, "loadImage: 路径未变,使用缓存 Bitmap"); @@ -174,7 +174,7 @@ public class BackgroundView extends RelativeLayout { // 2. 路径已更新:移除旧缓存,加载新图片并更新缓存 if (!TextUtils.isEmpty(mCurrentCachedPath)) { - App._mBitmapCacheUtils.removeCachedBitmap(mCurrentCachedPath); + App.sBitmapCacheUtils.removeCachedBitmap(mCurrentCachedPath); LogUtils.d(TAG, "loadImage: 路径已更新,移除旧缓存 - " + mCurrentCachedPath); } // ======================== 路径判断逻辑结束 ======================== @@ -194,7 +194,7 @@ public class BackgroundView extends RelativeLayout { } // 缓存新图片,并更新当前缓存路径记录 - App._mBitmapCacheUtils.cacheBitmap(imagePath); + App.sBitmapCacheUtils.cacheBitmap(imagePath); mCurrentCachedPath = imagePath; LogUtils.d(TAG, "loadImage: 加载新图片并更新缓存 - " + imagePath);