Compare commits
15 Commits
powerbell-
...
powerbell-
| Author | SHA1 | Date | |
|---|---|---|---|
| 18a5762c15 | |||
| 60de16ab45 | |||
| 6d60d71991 | |||
| 0cfbc43acb | |||
| 20227e29ef | |||
| 2b7007f478 | |||
| 212b8185c8 | |||
| 2ef09e020e | |||
| 6de9b7379b | |||
| 7fba2c8812 | |||
| 20e3a5f974 | |||
| c8333e1e81 | |||
| 6beb56efae | |||
| eb51b2c8f4 | |||
| 36bdd059b0 |
@@ -1,8 +1,8 @@
|
|||||||
#Created by .winboll/winboll_app_build.gradle
|
#Created by .winboll/winboll_app_build.gradle
|
||||||
#Sun Dec 21 09:22:26 HKT 2025
|
#Mon Dec 22 10:04:49 HKT 2025
|
||||||
stageCount=14
|
stageCount=19
|
||||||
libraryProject=
|
libraryProject=
|
||||||
baseVersion=15.14
|
baseVersion=15.14
|
||||||
publishVersion=15.14.13
|
publishVersion=15.14.18
|
||||||
buildCount=0
|
buildCount=0
|
||||||
baseBetaVersion=15.14.14
|
baseBetaVersion=15.14.19
|
||||||
|
|||||||
@@ -4,54 +4,73 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="cc.winboll.studio.powerbell">
|
package="cc.winboll.studio.powerbell">
|
||||||
|
|
||||||
<!-- ====================== 原有权限保留 + 补充核心权限 ====================== -->
|
<!-- 运行前台服务 -->
|
||||||
<!-- 运行前台服务(原有保留,补充 Android 12+ 特殊前台服务权限) -->
|
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
|
|
||||||
|
|
||||||
<!-- 开机启动(原有保留,确保自启广播生效) -->
|
<!-- 运行“specialUse”类型的前台服务 -->
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE"/>
|
||||||
|
|
||||||
|
<!-- 开机启动 -->
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||||
|
|
||||||
<!-- 显示通知(原有保留,前台服务/保活必备) -->
|
<!-- 显示通知 -->
|
||||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
|
||||||
|
|
||||||
<!-- 应用使用统计相关(原有保留,忽略保护权限警告) -->
|
<!-- PACKAGE_USAGE_STATS -->
|
||||||
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"/>
|
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"/>
|
||||||
|
|
||||||
|
<!-- BATTERY_STATS -->
|
||||||
<uses-permission android:name="android.permission.BATTERY_STATS"/>
|
<uses-permission android:name="android.permission.BATTERY_STATS"/>
|
||||||
|
|
||||||
|
<!-- 计算应用存储空间 -->
|
||||||
|
<uses-permission android:name="android.permission.GET_PACKAGE_SIZE"/>
|
||||||
|
|
||||||
|
<!-- 读取您共享存储空间中的内容 -->
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||||
|
|
||||||
|
<!-- 修改或删除您共享存储空间中的内容 -->
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||||
|
|
||||||
|
<!-- MANAGE_EXTERNAL_STORAGE -->
|
||||||
|
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
|
||||||
|
|
||||||
|
<!-- 请求忽略电池优化 -->
|
||||||
|
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
|
||||||
|
|
||||||
|
<!-- 拍摄照片和视频 -->
|
||||||
|
<uses-permission android:name="android.permission.CAMERA"/>
|
||||||
|
|
||||||
<uses-permission
|
<uses-permission
|
||||||
android:name="android.permission.ACCESS_PACKAGE_USAGE_STATS"
|
android:name="android.permission.ACCESS_PACKAGE_USAGE_STATS"
|
||||||
tools:ignore="ProtectedPermissions"/>
|
tools:ignore="ProtectedPermissions"/>
|
||||||
|
|
||||||
<!-- 相机相关(原有保留,补充权限等级声明,避免安装警告) -->
|
|
||||||
<uses-feature
|
<uses-feature
|
||||||
android:name="android.hardware.camera"
|
android:name="android.hardware.camera"
|
||||||
android:required="false"/> <!-- 非核心功能设为非必须,兼容无相机设备 -->
|
android:required="false"/>
|
||||||
|
|
||||||
<uses-feature
|
<uses-feature
|
||||||
android:name="android.hardware.camera.autofocus"
|
android:name="android.hardware.camera.autofocus"
|
||||||
android:required="false"/>
|
android:required="false"/>
|
||||||
<uses-permission android:name="android.permission.CAMERA" /> <!-- 补充相机权限,原有仅声明feature无权限 -->
|
|
||||||
|
|
||||||
<!-- 应用信息相关(原有保留) -->
|
<uses-permission android:name="android.permission.CAMERA"/>
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.GET_PACKAGE_SIZE"/>
|
<uses-permission android:name="android.permission.GET_PACKAGE_SIZE"/>
|
||||||
|
|
||||||
<uses-permission
|
<uses-permission
|
||||||
android:name="android.permission.QUERY_ALL_PACKAGES"
|
android:name="android.permission.QUERY_ALL_PACKAGES"
|
||||||
tools:ignore="QueryAllPackagesPermission"/>
|
tools:ignore="QueryAllPackagesPermission"/>
|
||||||
|
|
||||||
<!-- 新增:文件管理权限(对应 PermissionUtils 全文件管理逻辑) -->
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
|
||||||
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> <!-- API30+ 全文件权限 -->
|
|
||||||
|
|
||||||
<!-- 新增:忽略电池优化权限(对应 PermissionUtils 电池优化逻辑,必须声明) -->
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||||
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
|
||||||
|
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
|
||||||
|
|
||||||
<!-- 新增:API30+ 跳转系统权限页兼容(避免自启/文件权限跳转失败) -->
|
|
||||||
<queries>
|
<queries>
|
||||||
<!-- 全文件管理权限跳转兼容 -->
|
|
||||||
|
|
||||||
<!-- 小米自启权限跳转兼容(精准匹配安全中心包名) -->
|
<package android:name="com.miui.securitycenter"/>
|
||||||
<package android:name="com.miui.securitycenter" />
|
|
||||||
<!-- 电池优化权限跳转兼容 -->
|
|
||||||
|
|
||||||
</queries>
|
</queries>
|
||||||
|
|
||||||
@@ -68,17 +87,17 @@
|
|||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
tools:ignore="GoogleAppIndexingWarning,UnusedAttribute">
|
tools:ignore="GoogleAppIndexingWarning,UnusedAttribute">
|
||||||
|
|
||||||
<!-- ====================== 页面配置(原有保留,优化 exported 安全) ====================== -->
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:launchMode="singleTask">
|
android:launchMode="singleTask">
|
||||||
|
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.CrashActivity"
|
android:name=".activities.CrashActivity"
|
||||||
android:exported="false"/> <!-- 新增:非外部调用,设为 false,提升安全 -->
|
android:exported="false"/>
|
||||||
|
|
||||||
<activity-alias
|
<activity-alias
|
||||||
android:name=".MainActivityEN1"
|
android:name=".MainActivityEN1"
|
||||||
@@ -87,13 +106,19 @@
|
|||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:icon="@drawable/ic_launcher"
|
android:icon="@drawable/ic_launcher"
|
||||||
android:enabled="true">
|
android:enabled="true">
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
|
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.app.shortcuts"
|
android:name="android.app.shortcuts"
|
||||||
android:resource="@xml/shortcutsmainen1"/>
|
android:resource="@xml/shortcutsmainen1"/>
|
||||||
|
|
||||||
</activity-alias>
|
</activity-alias>
|
||||||
|
|
||||||
<activity-alias
|
<activity-alias
|
||||||
@@ -103,13 +128,19 @@
|
|||||||
android:label="@string/app_name_cn1"
|
android:label="@string/app_name_cn1"
|
||||||
android:icon="@drawable/ic_launcher"
|
android:icon="@drawable/ic_launcher"
|
||||||
android:enabled="false">
|
android:enabled="false">
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
|
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.app.shortcuts"
|
android:name="android.app.shortcuts"
|
||||||
android:resource="@xml/shortcutsmaincn1"/>
|
android:resource="@xml/shortcutsmaincn1"/>
|
||||||
|
|
||||||
</activity-alias>
|
</activity-alias>
|
||||||
|
|
||||||
<activity-alias
|
<activity-alias
|
||||||
@@ -119,53 +150,71 @@
|
|||||||
android:label="@string/app_name_cn2"
|
android:label="@string/app_name_cn2"
|
||||||
android:icon="@drawable/ic_launcher"
|
android:icon="@drawable/ic_launcher"
|
||||||
android:enabled="false">
|
android:enabled="false">
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
|
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.app.shortcuts"
|
android:name="android.app.shortcuts"
|
||||||
android:resource="@xml/shortcutsmaincn2"/>
|
android:resource="@xml/shortcutsmaincn2"/>
|
||||||
|
|
||||||
</activity-alias>
|
</activity-alias>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.ClearRecordActivity"
|
android:name=".activities.ClearRecordActivity"
|
||||||
android:parentActivityName="cc.winboll.studio.powerbell.MainActivity"
|
android:parentActivityName="cc.winboll.studio.powerbell.MainActivity"
|
||||||
android:launchMode="singleTask"
|
android:launchMode="singleTask"
|
||||||
android:exported="false"/> <!-- 新增:非外部调用,设为 false -->
|
android:exported="false"/>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.BackgroundSettingsActivity"
|
android:name=".activities.BackgroundSettingsActivity"
|
||||||
android:parentActivityName="cc.winboll.studio.powerbell.MainActivity"
|
android:parentActivityName="cc.winboll.studio.powerbell.MainActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:launchMode="singleTask">
|
android:launchMode="singleTask">
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
|
||||||
<action android:name="android.intent.action.SEND"/>
|
<action android:name="android.intent.action.SEND"/>
|
||||||
|
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
<category android:name="android.intent.category.DEFAULT"/>
|
||||||
|
|
||||||
<data android:mimeType="image/jpeg"/>
|
<data android:mimeType="image/jpeg"/>
|
||||||
|
|
||||||
<data android:mimeType="image/jpg"/>
|
<data android:mimeType="image/jpg"/>
|
||||||
|
|
||||||
<data android:mimeType="image/png"/>
|
<data android:mimeType="image/png"/>
|
||||||
|
|
||||||
<data android:mimeType="image/webp"/>
|
<data android:mimeType="image/webp"/>
|
||||||
|
|
||||||
<data android:mimeType="image/*"/>
|
<data android:mimeType="image/*"/>
|
||||||
|
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<!-- ====================== 广播接收器(优化自启广播,提升保活成功率) ====================== -->
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".receivers.MainReceiver"
|
android:name=".receivers.MainReceiver"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:directBootAware="true">
|
android:directBootAware="true">
|
||||||
<intent-filter android:priority="1000"> <!-- 新增:广播优先级最高,确保优先接收开机广播 -->
|
|
||||||
|
<intent-filter android:priority="1000">
|
||||||
|
|
||||||
<action android:name="android.intent.action.BOOT_COMPLETED"/>
|
<action android:name="android.intent.action.BOOT_COMPLETED"/>
|
||||||
<!-- 补充:充电/解锁广播,增强后台唤醒机会 -->
|
|
||||||
<action android:name="android.intent.action.POWER_CONNECTED"/>
|
<action android:name="android.intent.action.POWER_CONNECTED"/>
|
||||||
|
|
||||||
<action android:name="android.intent.action.USER_PRESENT"/>
|
<action android:name="android.intent.action.USER_PRESENT"/>
|
||||||
|
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<!-- ====================== 服务配置(核心优化:前台服务保活,适配 API29-30) ====================== -->
|
|
||||||
<!-- 核心前台服务:ControlCenterService(保活核心,重点优化) -->
|
|
||||||
<service
|
<service
|
||||||
android:name=".services.ControlCenterService"
|
android:name=".services.ControlCenterService"
|
||||||
android:priority="1000"
|
android:priority="1000"
|
||||||
@@ -173,67 +222,74 @@
|
|||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:process=".controlcenterservice"
|
android:process=".controlcenterservice"
|
||||||
android:foregroundServiceType="dataSync">
|
android:foregroundServiceType="dataSync">
|
||||||
<!-- 新增:Android 12+ 前台服务用途声明(系统强制,否则拦截服务启动) -->
|
|
||||||
<property
|
<property
|
||||||
android:name="android.app.PROPERTY_SPECIAL_USE_FOREGROUND_SERVICE"
|
android:name="android.app.PROPERTY_SPECIAL_USE_FOREGROUND_SERVICE"
|
||||||
android:value="后台核心功能运行、持续保活" /> <!-- 按实际用途填写,不可空 -->
|
android:value="后台核心功能运行、持续保活"/>
|
||||||
|
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<!-- 辅助服务:AssistantService(按需优化,增强稳定性) -->
|
|
||||||
<service
|
<service
|
||||||
android:name=".services.AssistantService"
|
android:name=".services.AssistantService"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:process=".assistantservice"> <!-- 若需前台启动,添加此配置;纯后台可移除 -->
|
android:process=".assistantservice">
|
||||||
|
|
||||||
<property
|
<property
|
||||||
android:name="android.app.PROPERTY_SPECIAL_USE_FOREGROUND_SERVICE"
|
android:name="android.app.PROPERTY_SPECIAL_USE_FOREGROUND_SERVICE"
|
||||||
android:value="辅助核心功能运行" />
|
android:value="辅助核心功能运行"/>
|
||||||
|
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<!-- ====================== 其他配置(原有保留,补充优化) ====================== -->
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.max_aspect"
|
android:name="android.max_aspect"
|
||||||
android:value="4.0"/>
|
android:value="4.0"/>
|
||||||
|
|
||||||
<!-- 所有非外部调用的 Activity,统一设 exported=false,提升安全 -->
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.BatteryReporterActivity"
|
android:name=".activities.BatteryReporterActivity"
|
||||||
android:exported="false"/>
|
android:exported="false"/>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.PixelPickerActivity"
|
android:name=".activities.PixelPickerActivity"
|
||||||
android:exported="false"/>
|
android:exported="false"/>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.BatteryReportActivity"
|
android:name=".activities.BatteryReportActivity"
|
||||||
android:exported="false"/>
|
android:exported="false"/>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".unittest.MainUnitTestActivity"
|
android:name=".unittest.MainUnitTestActivity"
|
||||||
android:exported="false"/>
|
android:exported="false"/>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.ShortcutActionActivity"
|
android:name=".activities.ShortcutActionActivity"
|
||||||
android:exported="false"/>
|
android:exported="false"/>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.SettingsActivity"
|
android:name=".activities.SettingsActivity"
|
||||||
android:exported="false"/>
|
android:exported="false"/>
|
||||||
|
|
||||||
<!-- 文件提供者(原有保留,正常使用) -->
|
|
||||||
<provider
|
<provider
|
||||||
android:name="androidx.core.content.FileProvider"
|
android:name="androidx.core.content.FileProvider"
|
||||||
android:authorities="${applicationId}.fileprovider"
|
android:authorities="${applicationId}.fileprovider"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:grantUriPermissions="true">
|
android:grantUriPermissions="true">
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||||
android:resource="@xml/file_provider"/>
|
android:resource="@xml/file_provider"/>
|
||||||
|
|
||||||
</provider>
|
</provider>
|
||||||
|
|
||||||
<!-- UCrop 第三方页面(原有保留,exported=true 正常) -->
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.yalantis.ucrop.UCropActivity"
|
android:name="com.yalantis.ucrop.UCropActivity"
|
||||||
android:theme="@style/Theme.AppCompat.Light.NoActionBar"
|
android:theme="@style/Theme.AppCompat.Light.NoActionBar"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
|
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<activity android:name="cc.winboll.studio.powerbell.unittest.MainUnitTest2Activity"/>
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
||||||
|
|||||||
@@ -9,220 +9,335 @@ import cc.winboll.studio.libaes.utils.WinBoLLActivityManager;
|
|||||||
import cc.winboll.studio.libappbase.GlobalApplication;
|
import cc.winboll.studio.libappbase.GlobalApplication;
|
||||||
import cc.winboll.studio.libappbase.LogUtils;
|
import cc.winboll.studio.libappbase.LogUtils;
|
||||||
import cc.winboll.studio.libappbase.ToastUtils;
|
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.models.NotificationMessage;
|
||||||
import cc.winboll.studio.powerbell.receivers.GlobalApplicationReceiver;
|
import cc.winboll.studio.powerbell.receivers.GlobalApplicationReceiver;
|
||||||
import cc.winboll.studio.powerbell.utils.AppCacheUtils;
|
import cc.winboll.studio.powerbell.utils.AppCacheUtils;
|
||||||
import cc.winboll.studio.powerbell.utils.AppConfigUtils;
|
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.BitmapCacheUtils;
|
||||||
import cc.winboll.studio.powerbell.utils.NotificationManagerUtils;
|
import cc.winboll.studio.powerbell.utils.NotificationManagerUtils;
|
||||||
|
import cc.winboll.studio.powerbell.views.MemoryCachedBackgroundView;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用全局入口类(适配Android API 30,基于Java 7编写)
|
||||||
|
*/
|
||||||
public class App extends GlobalApplication {
|
public class App extends GlobalApplication {
|
||||||
|
// ===================== 常量定义区 =====================
|
||||||
public static final String TAG = "App";
|
public static final String TAG = "App";
|
||||||
|
|
||||||
|
// 组件跳转常量
|
||||||
public static final String COMPONENT_EN1 = "cc.winboll.studio.powerbell.MainActivityEN1";
|
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_CN1 = "cc.winboll.studio.powerbell.MainActivityCN1";
|
||||||
public static final String COMPONENT_CN2 = "cc.winboll.studio.powerbell.MainActivityCN2";
|
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_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_CN1 = "cc.winboll.studio.powerbell.App.ACTION_SWITCHTO_CN1";
|
||||||
public static final String ACTION_SWITCHTO_CN2 = "cc.winboll.studio.powerbell.App.ACTION_SWITCHTO_CN2";
|
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_TITLE = "应用使用时内存紧张提醒";
|
||||||
private static final String TRIM_MEMORY_NOTIFY_CONTENT = "由于本应用使用时,系统通知内存紧张程度级别较高,图片缓存功能暂时不启用。";
|
private static final String TRIM_MEMORY_NOTIFY_CONTENT = "由于本应用使用时,系统通知内存紧张程度级别较高,图片缓存功能暂时不启用。";
|
||||||
|
|
||||||
// 数据配置存储工具
|
// 定时任务间隔常量(分钟)
|
||||||
static AppConfigUtils _mAppConfigUtils;
|
//private static final long TIMER_INTERVAL_MINUTES = 1;
|
||||||
static AppCacheUtils _mAppCacheUtils;
|
|
||||||
// 全局 Bitmap 缓存工具(常驻内存)
|
|
||||||
public static BitmapCacheUtils _mBitmapCacheUtils;
|
|
||||||
|
|
||||||
GlobalApplicationReceiver mReceiver;
|
// ===================== 静态属性区 =====================
|
||||||
static String szTempDir = "";
|
// 数据配置工具
|
||||||
// 通知工具类实例(用于发送内存紧张通知)
|
private static AppConfigUtils sAppConfigUtils;
|
||||||
|
private static AppCacheUtils sAppCacheUtils;
|
||||||
|
// 全局Bitmap缓存工具
|
||||||
|
public static BitmapCacheUtils sBitmapCacheUtils;
|
||||||
|
// 全局视图控件缓存工具
|
||||||
|
public static MemoryCachedBackgroundView sMemoryCachedBackgroundView;
|
||||||
|
// 临时文件夹路径
|
||||||
|
private static String sTempDirPath = "";
|
||||||
|
|
||||||
|
// 定时任务静态属性(全局唯一)
|
||||||
|
// private static Handler sTimerHandler;
|
||||||
|
// private static Runnable sTimerRunnable;
|
||||||
|
// private static boolean sIsTimerRunning = false;
|
||||||
|
//
|
||||||
|
// ===================== 成员属性区 =====================
|
||||||
|
// 全局广播接收器
|
||||||
|
private GlobalApplicationReceiver mGlobalReceiver;
|
||||||
|
// 通知管理工具
|
||||||
private NotificationManagerUtils mNotificationManager;
|
private NotificationManagerUtils mNotificationManager;
|
||||||
|
|
||||||
|
// ===================== 公共方法区 =====================
|
||||||
|
/**
|
||||||
|
* 获取临时文件夹路径
|
||||||
|
*/
|
||||||
public static String getTempDirPath() {
|
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
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
|
LogUtils.d(TAG, "onCreate() 应用启动,开始初始化");
|
||||||
|
|
||||||
|
// 初始化调试模式
|
||||||
setIsDebugging(BuildConfig.DEBUG);
|
setIsDebugging(BuildConfig.DEBUG);
|
||||||
|
LogUtils.d(TAG, "onCreate() 调试模式:" + BuildConfig.DEBUG);
|
||||||
|
|
||||||
// 初始化活动窗口管理
|
// 初始化基础工具
|
||||||
WinBoLLActivityManager.init(this);
|
initBaseTools();
|
||||||
// 初始化 Toast 框架
|
// 初始化临时文件夹
|
||||||
ToastUtils.init(this);
|
initTempDir();
|
||||||
|
// 初始化工具类实例
|
||||||
|
initUtils();
|
||||||
|
// 初始化广播接收器
|
||||||
|
initReceiver();
|
||||||
|
// 启动定时任务
|
||||||
|
//initTimerTask();
|
||||||
|
|
||||||
// 临时文件夹初始化(保持原有逻辑)
|
LogUtils.d(TAG, "onCreate() 应用初始化完成");
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTerminate() {
|
public void onTerminate() {
|
||||||
super.onTerminate();
|
super.onTerminate();
|
||||||
|
LogUtils.d(TAG, "onTerminate() 应用终止,开始释放资源");
|
||||||
|
|
||||||
|
// 释放Toast工具
|
||||||
ToastUtils.release();
|
ToastUtils.release();
|
||||||
// 释放通知工具类资源,避免内存泄漏
|
// 释放通知工具
|
||||||
if (mNotificationManager != null) {
|
releaseNotificationManager();
|
||||||
mNotificationManager.release();
|
// 停止定时任务
|
||||||
mNotificationManager = null;
|
//stopTimerTask();
|
||||||
LogUtils.d(TAG, "onTerminate: 通知工具类资源已释放");
|
|
||||||
}
|
LogUtils.d(TAG, "onTerminate() 应用资源释放完成");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTrimMemory(int level) {
|
public void onTrimMemory(int level) {
|
||||||
super.onTrimMemory(level);
|
super.onTrimMemory(level);
|
||||||
LogUtils.d(TAG, "onTrimMemory: 内存等级变化 | level=" + getTrimMemoryLevelDesc(level));
|
LogUtils.d(TAG, "onTrimMemory() 调用,内存等级level:" + level);
|
||||||
|
sMemoryCachedBackgroundView.clearAllCache();
|
||||||
// 仅在中等及以上内存紧张等级发送通知,避免频繁打扰
|
sMemoryCachedBackgroundView.getLastInstance(this);
|
||||||
if (mNotificationManager == null) {
|
//
|
||||||
mNotificationManager = new NotificationManagerUtils(this);
|
// // 初始化通知工具(若未初始化)
|
||||||
|
// 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缓存已启用");
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
if (level > ComponentCallbacks2.TRIM_MEMORY_MODERATE) {
|
|
||||||
sendTrimMemoryNotification(level);
|
// ===================== 私有初始化方法区 =====================
|
||||||
|
/**
|
||||||
|
* 初始化基础工具(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, "releaseNotificationManager() 通知工具资源已释放");
|
||||||
} else {
|
} else {
|
||||||
// 再次缓存 Bitmap 缓存工具
|
LogUtils.d(TAG, "releaseNotificationManager() 通知工具未初始化,无需释放");
|
||||||
_mBitmapCacheUtils = BitmapCacheUtils.getInstance();
|
|
||||||
LogUtils.d(TAG, "Bitmap 缓存启用中。");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发送内存紧张通知(完全复用 NotificationManagerUtils 的 showRemindNotification 方法)
|
* 发送内存紧张通知
|
||||||
*/
|
*/
|
||||||
private void sendTrimMemoryNotification(int level) {
|
private void sendTrimMemoryNotification(int level) {
|
||||||
LogUtils.d(TAG, "sendTrimMemoryNotification: 准备发送内存紧张通知");
|
LogUtils.d(TAG, "sendTrimMemoryNotification() 调用,内存等级level:" + level);
|
||||||
// 构建通知消息体
|
|
||||||
NotificationMessage message = new NotificationMessage();
|
NotificationMessage message = new NotificationMessage();
|
||||||
message.setTitle(TRIM_MEMORY_NOTIFY_TITLE);
|
message.setTitle(TRIM_MEMORY_NOTIFY_TITLE);
|
||||||
message.setContent(String.format("%s [ 缓存紧张级别描述: Level %d | %s ]",TRIM_MEMORY_NOTIFY_CONTENT, level, getTrimMemoryLevelDesc(level)));
|
String content = String.format("%s [ 缓存紧张级别描述: Level %d | %s ]",
|
||||||
// 使用整理后的 NotificationManagerUtils 发送通知(复用提醒渠道配置)
|
TRIM_MEMORY_NOTIFY_CONTENT, level, getTrimMemoryLevelDesc(level));
|
||||||
|
message.setContent(content);
|
||||||
mNotificationManager.showConfigNotification(this, message);
|
mNotificationManager.showConfigNotification(this, message);
|
||||||
LogUtils.d(TAG, "sendTrimMemoryNotification: 通知已通过 NotificationManagerUtils 发送");
|
LogUtils.d(TAG, "sendTrimMemoryNotification() 内存紧张通知已发送,内容:" + content);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 转换内存等级为可读描述,便于日志调试
|
* 转换内存等级为可读描述
|
||||||
* 排序规则:按 ComponentCallbacks2 枚举数值从高到低排列(数值越高,内存越紧张)
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* 转换内存等级为可读描述,便于日志调试
|
|
||||||
* 排序规则:按 ComponentCallbacks2 枚举实际数值(10进制)从高到低排列
|
|
||||||
* 数值来源:接口中定义的 16进制(注释10进制)数值
|
|
||||||
*/
|
*/
|
||||||
private String getTrimMemoryLevelDesc(int level) {
|
private String getTrimMemoryLevelDesc(int level) {
|
||||||
|
LogUtils.d(TAG, "getTrimMemoryLevelDesc() 调用,传入level:" + level);
|
||||||
|
String desc;
|
||||||
switch (level) {
|
switch (level) {
|
||||||
// 数值 80(0x50):应用内存完全紧张(补充接口中实际存在的枚举项)
|
|
||||||
case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
|
case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
|
||||||
return "TRIM_MEMORY_COMPLETE(应用内存完全紧张)";
|
desc = "TRIM_MEMORY_COMPLETE(应用内存完全紧张)";
|
||||||
// 数值 60(0x3c):中等内存紧张
|
break;
|
||||||
case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
|
case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
|
||||||
return "MODERATE(中等内存紧张)";
|
desc = "MODERATE(中等内存紧张)";
|
||||||
// 数值 40(0x28):应用进入后台
|
break;
|
||||||
case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND:
|
case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND:
|
||||||
return "BACKGROUND(应用进入后台)";
|
desc = "BACKGROUND(应用进入后台)";
|
||||||
// 数值 20(0x14):应用UI隐藏
|
break;
|
||||||
case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:
|
case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:
|
||||||
return "BACKGROUND(应用UI隐藏)";
|
desc = "BACKGROUND(应用UI隐藏)";
|
||||||
// 数值 15(0xf):应用运行时关键级紧张
|
break;
|
||||||
case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL:
|
case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL:
|
||||||
return "RUNNING_CRITICAL(应用运行关键级紧张)";
|
desc = "RUNNING_CRITICAL(应用运行关键级紧张)";
|
||||||
// 数值 10(0xa):应用运行时低内存
|
break;
|
||||||
case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW:
|
case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW:
|
||||||
return "RUNNING_LOW(应用运行低内存)";
|
desc = "RUNNING_LOW(应用运行低内存)";
|
||||||
// 数值 5(0x5):应用运行时中等紧张
|
break;
|
||||||
case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE:
|
case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE:
|
||||||
return "RUNNING_MODERATE(应用运行中等内存紧张)";
|
desc = "RUNNING_MODERATE(应用运行中等内存紧张)";
|
||||||
|
break;
|
||||||
// 以下为注释备用项(接口中未提供,按你的原有注释保留)
|
|
||||||
// 数值 100:内存极度紧张(系统可能强制杀死应用)
|
|
||||||
// case ComponentCallbacks2.TRIM_MEMORY_URGENT:
|
|
||||||
// return "URGENT(内存极度紧张)";
|
|
||||||
// 数值 20:用户正在离开应用(如按Home键)
|
|
||||||
// case ComponentCallbacks2.TRIM_MEMORY_USER_LEAVING:
|
|
||||||
// return "USER_LEAVING(用户正在离开应用)";
|
|
||||||
|
|
||||||
// 未知等级
|
|
||||||
default:
|
default:
|
||||||
return "UNKNOWN(" + level + ")";
|
desc = "UNKNOWN(" + level + ")";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
LogUtils.d(TAG, "getTrimMemoryLevelDesc() 内存等级描述结果:" + desc);
|
||||||
|
return desc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import android.view.Menu;
|
|||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewStub;
|
import android.view.ViewStub;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
import cc.winboll.studio.libaes.activitys.AboutActivity;
|
import cc.winboll.studio.libaes.activitys.AboutActivity;
|
||||||
import cc.winboll.studio.libaes.models.APPInfo;
|
import cc.winboll.studio.libaes.models.APPInfo;
|
||||||
@@ -28,6 +29,7 @@ import cc.winboll.studio.powerbell.activities.WinBoLLActivity;
|
|||||||
import cc.winboll.studio.powerbell.models.BackgroundBean;
|
import cc.winboll.studio.powerbell.models.BackgroundBean;
|
||||||
import cc.winboll.studio.powerbell.models.ControlCenterServiceBean;
|
import cc.winboll.studio.powerbell.models.ControlCenterServiceBean;
|
||||||
import cc.winboll.studio.powerbell.services.ControlCenterService;
|
import cc.winboll.studio.powerbell.services.ControlCenterService;
|
||||||
|
import cc.winboll.studio.powerbell.unittest.MainUnitTest2Activity;
|
||||||
import cc.winboll.studio.powerbell.unittest.MainUnitTestActivity;
|
import cc.winboll.studio.powerbell.unittest.MainUnitTestActivity;
|
||||||
import cc.winboll.studio.powerbell.utils.AppConfigUtils;
|
import cc.winboll.studio.powerbell.utils.AppConfigUtils;
|
||||||
import cc.winboll.studio.powerbell.utils.BackgroundSourceUtils;
|
import cc.winboll.studio.powerbell.utils.BackgroundSourceUtils;
|
||||||
@@ -210,6 +212,9 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV
|
|||||||
break;
|
break;
|
||||||
case R.id.action_unittestactivity:
|
case R.id.action_unittestactivity:
|
||||||
startActivity(new Intent(this, MainUnitTestActivity.class));
|
startActivity(new Intent(this, MainUnitTestActivity.class));
|
||||||
|
break;
|
||||||
|
case R.id.action_unittest2activity:
|
||||||
|
startActivity(new Intent(this, MainUnitTest2Activity.class));
|
||||||
break;
|
break;
|
||||||
case R.id.action_about:
|
case R.id.action_about:
|
||||||
startAboutActivity();
|
startAboutActivity();
|
||||||
@@ -402,7 +407,7 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV
|
|||||||
}
|
}
|
||||||
BackgroundBean currentBgBean = mBgSourceUtils.getCurrentBackgroundBean();
|
BackgroundBean currentBgBean = mBgSourceUtils.getCurrentBackgroundBean();
|
||||||
if (currentBgBean != null) {
|
if (currentBgBean != null) {
|
||||||
mMainContentView.backgroundView.loadBackgroundBean(currentBgBean);
|
mMainContentView.backgroundView.loadByBackgroundBean(currentBgBean);
|
||||||
} else {
|
} else {
|
||||||
mMainContentView.backgroundView.setBackgroundResource(R.drawable.default_background);
|
mMainContentView.backgroundView.setBackgroundResource(R.drawable.default_background);
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -21,6 +21,7 @@ import java.io.FileInputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import cc.winboll.studio.powerbell.utils.ImageDownloader;
|
import cc.winboll.studio.powerbell.utils.ImageDownloader;
|
||||||
import cc.winboll.studio.powerbell.utils.BackgroundSourceUtils;
|
import cc.winboll.studio.powerbell.utils.BackgroundSourceUtils;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
|
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
|
||||||
@@ -52,7 +53,7 @@ public class NetworkBackgroundDialog extends AlertDialog {
|
|||||||
|
|
||||||
// 按钮点击回调接口(Java7 接口实现)
|
// 按钮点击回调接口(Java7 接口实现)
|
||||||
public interface OnDialogClickListener {
|
public interface OnDialogClickListener {
|
||||||
void onConfirm(String szConfirmFilePath, String previewFileUrl); // 确认按钮点击
|
void onConfirm(String szConfirmFilePath); // 确认按钮点击
|
||||||
void onCancel(); // 取消按钮点击
|
void onCancel(); // 取消按钮点击
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,7 +92,7 @@ public class NetworkBackgroundDialog extends AlertDialog {
|
|||||||
case MSG_IMAGE_LOAD_SUCCESS:
|
case MSG_IMAGE_LOAD_SUCCESS:
|
||||||
// 图片加载成功,获取文件路径并设置背景
|
// 图片加载成功,获取文件路径并设置背景
|
||||||
mDownloadSavedPath = (String) msg.obj;
|
mDownloadSavedPath = (String) msg.obj;
|
||||||
previewBackground(mDownloadSavedPath);
|
mBackgroundView.loadImage(mDownloadSavedPath);
|
||||||
break;
|
break;
|
||||||
case MSG_IMAGE_LOAD_FAILED:
|
case MSG_IMAGE_LOAD_FAILED:
|
||||||
// 图片加载失败,设置默认背景
|
// 图片加载失败,设置默认背景
|
||||||
@@ -139,7 +140,7 @@ public class NetworkBackgroundDialog extends AlertDialog {
|
|||||||
etURL = (EditText) dialogView.findViewById(R.id.et_url);
|
etURL = (EditText) dialogView.findViewById(R.id.et_url);
|
||||||
mBackgroundView = (BackgroundView) dialogView.findViewById(R.id.bv_background_preview);
|
mBackgroundView = (BackgroundView) dialogView.findViewById(R.id.bv_background_preview);
|
||||||
// 加载初始图片
|
// 加载初始图片
|
||||||
mBackgroundView.setBackgroundResource(R.drawable.ic_launcher);
|
mBackgroundView.setBackgroundResource(R.drawable.blank100x100);
|
||||||
// 设置按钮点击事件
|
// 设置按钮点击事件
|
||||||
setButtonClickListeners();
|
setButtonClickListeners();
|
||||||
}
|
}
|
||||||
@@ -168,13 +169,13 @@ public class NetworkBackgroundDialog extends AlertDialog {
|
|||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
LogUtils.d("NetworkBackgroundDialog", "确认按钮点击");
|
LogUtils.d("NetworkBackgroundDialog", "确认按钮点击");
|
||||||
// 确定预览背景资源
|
|
||||||
BackgroundSourceUtils utils = BackgroundSourceUtils.getInstance(mContext);
|
|
||||||
utils.saveFileToPreviewBean(new File(mPreviewFilePath), mPreviewFileUrl);
|
|
||||||
|
|
||||||
dismiss(); // 关闭对话框
|
dismiss(); // 关闭对话框
|
||||||
|
if(TextUtils.isEmpty(mDownloadSavedPath)) {
|
||||||
|
ToastUtils.show("未下载图片。");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (listener != null) {
|
if (listener != null) {
|
||||||
listener.onConfirm(mPreviewFilePath, mPreviewFileUrl);
|
listener.onConfirm(mDownloadSavedPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -207,7 +208,7 @@ public class NetworkBackgroundDialog extends AlertDialog {
|
|||||||
mPreviewFilePath = previewFilePath;
|
mPreviewFilePath = previewFilePath;
|
||||||
BackgroundSourceUtils utils = BackgroundSourceUtils.getInstance(mContext);
|
BackgroundSourceUtils utils = BackgroundSourceUtils.getInstance(mContext);
|
||||||
utils.saveFileToPreviewBean(new File(mPreviewFilePath), mPreviewFileUrl);
|
utils.saveFileToPreviewBean(new File(mPreviewFilePath), mPreviewFileUrl);
|
||||||
mBackgroundView.loadBackgroundBean(utils.getPreviewBackgroundBean());
|
mBackgroundView.loadByBackgroundBean(utils.getPreviewBackgroundBean());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
mBackgroundView.setBackgroundResource(R.drawable.ic_launcher);
|
mBackgroundView.setBackgroundResource(R.drawable.ic_launcher);
|
||||||
@@ -258,6 +259,7 @@ public class NetworkBackgroundDialog extends AlertDialog {
|
|||||||
// 发送消息到主线程,携带图片路径
|
// 发送消息到主线程,携带图片路径
|
||||||
Message successMsg = mUiHandler.obtainMessage(MSG_IMAGE_LOAD_SUCCESS, savePath);
|
Message successMsg = mUiHandler.obtainMessage(MSG_IMAGE_LOAD_SUCCESS, savePath);
|
||||||
mUiHandler.sendMessage(successMsg);
|
mUiHandler.sendMessage(successMsg);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -0,0 +1,257 @@
|
|||||||
|
package cc.winboll.studio.powerbell.unittest;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import cc.winboll.studio.libappbase.LogUtils;
|
||||||
|
import cc.winboll.studio.libappbase.ToastUtils;
|
||||||
|
import cc.winboll.studio.powerbell.MainActivity;
|
||||||
|
import cc.winboll.studio.powerbell.R;
|
||||||
|
import cc.winboll.studio.powerbell.models.BackgroundBean;
|
||||||
|
import cc.winboll.studio.powerbell.utils.FileUtils;
|
||||||
|
import cc.winboll.studio.powerbell.utils.ImageCropUtils;
|
||||||
|
import cc.winboll.studio.powerbell.views.BackgroundView;
|
||||||
|
import cc.winboll.studio.powerbell.views.MemoryCachedBackgroundView;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
|
||||||
|
* @Date 2025/12/22 08:31
|
||||||
|
* @Describe MainUnitTest2Activity
|
||||||
|
*/
|
||||||
|
public class MainUnitTest2Activity extends AppCompatActivity {
|
||||||
|
// ====================== 常量定义 ======================
|
||||||
|
public static final String TAG = "MainUnitTest2Activity";
|
||||||
|
public static final int REQUEST_CROP_IMAGE = 0;
|
||||||
|
private static final String ASSETS_TEST_IMAGE_PATH = "unittest/unittest-miku.png";
|
||||||
|
|
||||||
|
// ====================== 成员变量(移除所有Uri相关) ======================
|
||||||
|
private MemoryCachedBackgroundView mMemoryCachedBackgroundView;
|
||||||
|
private String mAppPrivateDirPath;
|
||||||
|
private File mPrivateTestImageFile; // 仅用File,不用Uri
|
||||||
|
private File mPrivateCropImageFile;
|
||||||
|
BackgroundBean mPreviewBackgroundBean;
|
||||||
|
LinearLayout mllBackgroundView;
|
||||||
|
|
||||||
|
// ====================== 生命周期方法 ======================
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
LogUtils.d(TAG, "=== 页面 onCreate 启动 ===");
|
||||||
|
|
||||||
|
initBaseParams();
|
||||||
|
initViewAndEvent();
|
||||||
|
copyAssetsTestImageToPrivateDir();
|
||||||
|
//loadBackgroundByFile(); // 直接用File加载
|
||||||
|
mPreviewBackgroundBean = new BackgroundBean();
|
||||||
|
mPreviewBackgroundBean.setBackgroundFileName(mPrivateTestImageFile.getName());
|
||||||
|
mPreviewBackgroundBean.setBackgroundFilePath(mPrivateTestImageFile.getAbsolutePath());
|
||||||
|
mPreviewBackgroundBean.setBackgroundScaledCompressFileName(mPrivateCropImageFile.getName());
|
||||||
|
mPreviewBackgroundBean.setBackgroundScaledCompressFilePath(mPrivateCropImageFile.getAbsolutePath());
|
||||||
|
mPreviewBackgroundBean.setIsUseBackgroundFile(true);
|
||||||
|
doubleRefreshPreview();
|
||||||
|
|
||||||
|
ToastUtils.show("单元测试页面启动完成");
|
||||||
|
LogUtils.d(TAG, "=== 页面 onCreate 初始化结束 ===");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
LogUtils.d(TAG, "=== onActivityResult 回调 ===");
|
||||||
|
if (requestCode == REQUEST_CROP_IMAGE) {
|
||||||
|
handleCropResult(resultCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================== 初始化相关方法 ======================
|
||||||
|
private void initBaseParams() {
|
||||||
|
LogUtils.d(TAG, "初始化基础参数:工具类+私有目录+File");
|
||||||
|
|
||||||
|
// 私有目录(无需权限,无UID冲突)
|
||||||
|
mAppPrivateDirPath = getExternalFilesDir(Environment.DIRECTORY_PICTURES).getAbsolutePath() + "/PowerBellTest/";
|
||||||
|
File privateDir = new File(mAppPrivateDirPath);
|
||||||
|
if (!privateDir.exists()) {
|
||||||
|
privateDir.mkdirs();
|
||||||
|
LogUtils.d(TAG, "创建私有目录:" + mAppPrivateDirPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化File(无Uri)
|
||||||
|
File refFile = new File(ASSETS_TEST_IMAGE_PATH);
|
||||||
|
String uniqueTestName = FileUtils.createUniqueFileName(refFile) + ".png";
|
||||||
|
String uniqueCropName = uniqueTestName.replace(".png", "_crop.png");
|
||||||
|
mPrivateTestImageFile = new File(mAppPrivateDirPath, uniqueTestName);
|
||||||
|
mPrivateCropImageFile = new File(mAppPrivateDirPath, uniqueCropName);
|
||||||
|
|
||||||
|
LogUtils.d(TAG, "测试图File路径:" + mPrivateTestImageFile.getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initViewAndEvent() {
|
||||||
|
LogUtils.d(TAG, "初始化布局与控件事件");
|
||||||
|
setContentView(R.layout.activity_mainunittest2);
|
||||||
|
mllBackgroundView = (LinearLayout) findViewById(R.id.ll_backgroundview);
|
||||||
|
mMemoryCachedBackgroundView = MemoryCachedBackgroundView.getInstance(this, "", false);
|
||||||
|
mllBackgroundView.addView(mMemoryCachedBackgroundView);
|
||||||
|
|
||||||
|
//mMemoryCachedBackgroundView = (BackgroundView) findViewById(R.id.backgroundview);
|
||||||
|
|
||||||
|
// 跳转主页面按钮
|
||||||
|
Button btnMain = (Button) findViewById(R.id.btn_main_activity);
|
||||||
|
btnMain.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
LogUtils.d(TAG, "点击按钮:跳转主页面");
|
||||||
|
startActivity(new Intent(MainUnitTest2Activity.this, MainActivity.class));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 裁剪按钮(直接用File路径启动,无Uri)
|
||||||
|
Button btnCrop = (Button) findViewById(R.id.btn_test_cropimage);
|
||||||
|
btnCrop.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
LogUtils.d(TAG, "点击按钮:启动裁剪(File路径版)");
|
||||||
|
ToastUtils.show("准备启动图片裁剪");
|
||||||
|
|
||||||
|
if (mPrivateTestImageFile.exists() && mPrivateTestImageFile.length() > 100) {
|
||||||
|
startCropTestByFile(); // 直接传File
|
||||||
|
} else {
|
||||||
|
ToastUtils.show("测试图片未准备好,重新拷贝");
|
||||||
|
copyAssetsTestImageToPrivateDir();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从assets拷贝图片(不变,确保File存在)
|
||||||
|
private void copyAssetsTestImageToPrivateDir() {
|
||||||
|
LogUtils.d(TAG, "开始拷贝assets图片到私有目录");
|
||||||
|
if (mPrivateTestImageFile.exists() && mPrivateTestImageFile.length() > 100) {
|
||||||
|
LogUtils.d(TAG, "图片已存在,无需拷贝");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
InputStream inputStream = null;
|
||||||
|
try {
|
||||||
|
inputStream = getAssets().open(ASSETS_TEST_IMAGE_PATH);
|
||||||
|
FileUtils.copyStreamToFile(inputStream, mPrivateTestImageFile);
|
||||||
|
LogUtils.d(TAG, "图片拷贝成功,大小:" + mPrivateTestImageFile.length() + "字节");
|
||||||
|
} catch (IOException e) {
|
||||||
|
LogUtils.e(TAG, "图片拷贝失败:" + e.getMessage(), e);
|
||||||
|
ToastUtils.show("图片准备失败");
|
||||||
|
} finally {
|
||||||
|
if (inputStream != null) {
|
||||||
|
try {
|
||||||
|
inputStream.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
LogUtils.e(TAG, "关闭流失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================== 核心业务方法(全改为File路径) ======================
|
||||||
|
/** 直接用File路径加载背景图(无Uri,无冲突) */
|
||||||
|
// private void loadBackgroundByFile() {
|
||||||
|
// LogUtils.d(TAG, "开始加载背景图(File路径版)");
|
||||||
|
// if (mPrivateTestImageFile.exists() && mPrivateTestImageFile.length() > 100) {
|
||||||
|
// mBackgroundView.loadImage(mPrivateTestImageFile.getAbsolutePath()); // 直接传路径
|
||||||
|
// LogUtils.d(TAG, "背景图加载成功:" + mPrivateTestImageFile.getAbsolutePath());
|
||||||
|
// ToastUtils.show("背景图加载成功");
|
||||||
|
// } else {
|
||||||
|
// LogUtils.e(TAG, "背景图加载失败:文件无效");
|
||||||
|
// ToastUtils.show("背景图加载失败");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
/** 直接用File启动裁剪(关键:调用ImageCropUtils的File重载方法) */
|
||||||
|
private void startCropTestByFile() {
|
||||||
|
LogUtils.d(TAG, "启动裁剪(File路径版),原图:" + mPrivateTestImageFile.getAbsolutePath());
|
||||||
|
|
||||||
|
// 确保输出目录存在
|
||||||
|
File cropParent = mPrivateCropImageFile.getParentFile();
|
||||||
|
if (!cropParent.exists()) {
|
||||||
|
cropParent.mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用ImageCropUtils的File参数方法(核心:绕开Uri)
|
||||||
|
ImageCropUtils.startImageCrop(
|
||||||
|
this,
|
||||||
|
mPrivateTestImageFile, // 原图File
|
||||||
|
mPrivateCropImageFile, // 输出File
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
true,
|
||||||
|
REQUEST_CROP_IMAGE
|
||||||
|
);
|
||||||
|
|
||||||
|
LogUtils.d(TAG, "裁剪请求已发送,输出路径:" + mPrivateCropImageFile.getAbsolutePath());
|
||||||
|
ToastUtils.show("已启动图片裁剪");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 处理裁剪结果(直接校验输出File) */
|
||||||
|
private void handleCropResult(int resultCode) {
|
||||||
|
LogUtils.d(TAG, "裁剪回调处理:resultCode=" + resultCode);
|
||||||
|
if (resultCode == RESULT_OK) {
|
||||||
|
if (mPrivateCropImageFile.exists() && mPrivateCropImageFile.length() > 100) {
|
||||||
|
mMemoryCachedBackgroundView.loadImage(mPrivateCropImageFile.getAbsolutePath());
|
||||||
|
LogUtils.d(TAG, "裁剪成功,加载裁剪图:" + mPrivateCropImageFile.getAbsolutePath());
|
||||||
|
ToastUtils.show("裁剪成功");
|
||||||
|
mPreviewBackgroundBean.setIsUseBackgroundScaledCompressFile(true);
|
||||||
|
doubleRefreshPreview();
|
||||||
|
} else {
|
||||||
|
LogUtils.e(TAG, "裁剪成功但输出文件无效");
|
||||||
|
ToastUtils.show("裁剪失败:输出文件无效");
|
||||||
|
}
|
||||||
|
} else if (resultCode == RESULT_CANCELED) {
|
||||||
|
LogUtils.d(TAG, "裁剪取消");
|
||||||
|
ToastUtils.show("裁剪已取消");
|
||||||
|
} else {
|
||||||
|
LogUtils.e(TAG, "裁剪失败:resultCode异常");
|
||||||
|
ToastUtils.show("裁剪失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 双重刷新预览,确保背景加载最新数据
|
||||||
|
* 移除:缓存清空逻辑
|
||||||
|
*/
|
||||||
|
private void doubleRefreshPreview() {
|
||||||
|
|
||||||
|
// 第一重刷新
|
||||||
|
try {
|
||||||
|
mMemoryCachedBackgroundView.loadByBackgroundBean(mPreviewBackgroundBean, true);
|
||||||
|
mMemoryCachedBackgroundView.setBackgroundColor(mPreviewBackgroundBean.getPixelColor());
|
||||||
|
LogUtils.d(TAG, "【双重刷新】第一重完成");
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtils.e(TAG, "【双重刷新】第一重异常:" + e.getMessage());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 第二重刷新(延迟执行)
|
||||||
|
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (mMemoryCachedBackgroundView != null && !isFinishing()) {
|
||||||
|
try {
|
||||||
|
mMemoryCachedBackgroundView.loadByBackgroundBean(mPreviewBackgroundBean, true);
|
||||||
|
mMemoryCachedBackgroundView.setBackgroundColor(mPreviewBackgroundBean.getPixelColor());
|
||||||
|
LogUtils.d(TAG, "【双重刷新】第二重完成");
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtils.e(TAG, "【双重刷新】第二重异常:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -221,7 +221,7 @@ public class MainUnitTestActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
// 第一重刷新
|
// 第一重刷新
|
||||||
try {
|
try {
|
||||||
mBackgroundView.loadBackgroundBean(mPreviewBackgroundBean, true);
|
mBackgroundView.loadByBackgroundBean(mPreviewBackgroundBean, true);
|
||||||
mBackgroundView.setBackgroundColor(mPreviewBackgroundBean.getPixelColor());
|
mBackgroundView.setBackgroundColor(mPreviewBackgroundBean.getPixelColor());
|
||||||
LogUtils.d(TAG, "【双重刷新】第一重完成");
|
LogUtils.d(TAG, "【双重刷新】第一重完成");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -235,7 +235,7 @@ public class MainUnitTestActivity extends AppCompatActivity {
|
|||||||
public void run() {
|
public void run() {
|
||||||
if (mBackgroundView != null && !isFinishing()) {
|
if (mBackgroundView != null && !isFinishing()) {
|
||||||
try {
|
try {
|
||||||
mBackgroundView.loadBackgroundBean(mPreviewBackgroundBean, true);
|
mBackgroundView.loadByBackgroundBean(mPreviewBackgroundBean, true);
|
||||||
mBackgroundView.setBackgroundColor(mPreviewBackgroundBean.getPixelColor());
|
mBackgroundView.setBackgroundColor(mPreviewBackgroundBean.getPixelColor());
|
||||||
LogUtils.d(TAG, "【双重刷新】第二重完成");
|
LogUtils.d(TAG, "【双重刷新】第二重完成");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
@@ -183,10 +183,17 @@ public class BackgroundSourceUtils {
|
|||||||
/**
|
/**
|
||||||
* 检查背景是否为空并创建空白背景Bean
|
* 检查背景是否为空并创建空白背景Bean
|
||||||
*/
|
*/
|
||||||
boolean checkEmptyBackgroundAndCreateBlankBackgroundBean(BackgroundBean checkBackgroundBean) {
|
public boolean checkEmptyBackgroundAndCreateBlankBackgroundBean(BackgroundBean checkBackgroundBean) {
|
||||||
LogUtils.d(TAG, "【checkEmptyBackgroundAndCreateBlankBackgroundBean调用】开始检查背景Bean");
|
LogUtils.d(TAG, "【checkEmptyBackgroundAndCreateBlankBackgroundBean调用】开始检查背景Bean");
|
||||||
File fCheckBackgroundFile = new File(checkBackgroundBean.getBackgroundFilePath());
|
File fCheckBackgroundFile = new File(checkBackgroundBean.getBackgroundFilePath());
|
||||||
if (!fCheckBackgroundFile.exists()) {
|
if (!fCheckBackgroundFile.exists()) {
|
||||||
|
return createBlankBackgroundBean(checkBackgroundBean.getPixelColor());
|
||||||
|
}
|
||||||
|
LogUtils.d(TAG, "背景Bean文件存在,无需创建空白背景");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean createBlankBackgroundBean(int nBackgroundPixelColor) {
|
||||||
String newCropFileName = genNewCropFileName();
|
String newCropFileName = genNewCropFileName();
|
||||||
String fileSuffix = "png";
|
String fileSuffix = "png";
|
||||||
mCropSourceFile = new File(fCropCacheDir, newCropFileName + "." + fileSuffix);
|
mCropSourceFile = new File(fCropCacheDir, newCropFileName + "." + fileSuffix);
|
||||||
@@ -200,7 +207,7 @@ public class BackgroundSourceUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
loadSettings();
|
loadSettings();
|
||||||
previewBackgroundBean.setPixelColor(0xFFFFFFFF);
|
previewBackgroundBean.setPixelColor(nBackgroundPixelColor);
|
||||||
previewBackgroundBean.setIsUseBackgroundFile(true);
|
previewBackgroundBean.setIsUseBackgroundFile(true);
|
||||||
previewBackgroundBean.setIsUseBackgroundScaledCompressFile(false);
|
previewBackgroundBean.setIsUseBackgroundScaledCompressFile(false);
|
||||||
previewBackgroundBean.setBackgroundFileName(mCropSourceFile.getName());
|
previewBackgroundBean.setBackgroundFileName(mCropSourceFile.getName());
|
||||||
@@ -211,9 +218,6 @@ public class BackgroundSourceUtils {
|
|||||||
LogUtils.d(TAG, "背景Bean为空,已创建空白背景并更新配置");
|
LogUtils.d(TAG, "背景Bean为空,已创建空白背景并更新配置");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
LogUtils.d(TAG, "背景Bean文件存在,无需创建空白背景");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
String genNewCropFileName() {
|
String genNewCropFileName() {
|
||||||
return UUID.randomUUID().toString() + System.currentTimeMillis();
|
return UUID.randomUUID().toString() + System.currentTimeMillis();
|
||||||
|
|||||||
@@ -104,11 +104,11 @@ public class BackgroundView extends RelativeLayout {
|
|||||||
LogUtils.d(TAG, "=== initImageView 完成 ===");
|
LogUtils.d(TAG, "=== initImageView 完成 ===");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadBackgroundBean(BackgroundBean bean) {
|
public void loadByBackgroundBean(BackgroundBean bean) {
|
||||||
loadBackgroundBean(bean, false);
|
loadByBackgroundBean(bean, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadBackgroundBean(BackgroundBean bean, boolean isRefresh) {
|
public void loadByBackgroundBean(BackgroundBean bean, boolean isRefresh) {
|
||||||
if (!bean.isUseBackgroundFile()) {
|
if (!bean.isUseBackgroundFile()) {
|
||||||
setDefaultTransparentBackground();
|
setDefaultTransparentBackground();
|
||||||
return;
|
return;
|
||||||
@@ -124,8 +124,8 @@ public class BackgroundView extends RelativeLayout {
|
|||||||
|
|
||||||
// 调用带路径判断的loadImage方法
|
// 调用带路径判断的loadImage方法
|
||||||
if (isRefresh) {
|
if (isRefresh) {
|
||||||
App._mBitmapCacheUtils.removeCachedBitmap(targetPath);
|
App.sBitmapCacheUtils.removeCachedBitmap(targetPath);
|
||||||
App._mBitmapCacheUtils.cacheBitmap(targetPath);
|
App.sBitmapCacheUtils.cacheBitmap(targetPath);
|
||||||
}
|
}
|
||||||
loadImage(targetPath);
|
loadImage(targetPath);
|
||||||
}
|
}
|
||||||
@@ -149,19 +149,18 @@ public class BackgroundView extends RelativeLayout {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mIvBackground.setVisibility(View.GONE);
|
//mIvBackground.setVisibility(View.GONE);
|
||||||
|
|
||||||
// ======================== 新增:路径判断逻辑 ========================
|
// ======================== 新增:路径判断逻辑 ========================
|
||||||
// 1. 路径未变化:直接使用缓存
|
// 1. 路径未变化:直接使用缓存
|
||||||
if (imagePath.equals(mCurrentCachedPath)) {
|
if (imagePath.equals(mCurrentCachedPath)) {
|
||||||
Bitmap cachedBitmap = App._mBitmapCacheUtils.getCachedBitmap(imagePath);
|
Bitmap cachedBitmap = App.sBitmapCacheUtils.getCachedBitmap(imagePath);
|
||||||
// 核心修改:判断缓存Bitmap是否为null
|
// 核心修改:判断缓存Bitmap是否为null
|
||||||
if (cachedBitmap != null && !cachedBitmap.isRecycled()) {
|
if (cachedBitmap != null && !cachedBitmap.isRecycled()) {
|
||||||
LogUtils.d(TAG, "loadImage: 路径未变,使用缓存 Bitmap");
|
LogUtils.d(TAG, "loadImage: 路径未变,使用缓存 Bitmap");
|
||||||
mImageAspectRatio = (float) cachedBitmap.getWidth() / cachedBitmap.getHeight();
|
mImageAspectRatio = (float) cachedBitmap.getWidth() / cachedBitmap.getHeight();
|
||||||
mIvBackground.setImageBitmap(cachedBitmap);
|
mIvBackground.setImageBitmap(cachedBitmap);
|
||||||
adjustImageViewSize();
|
adjustImageViewSize();
|
||||||
mIvBackground.setVisibility(View.VISIBLE);
|
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// 缓存Bitmap为空或已回收,提示并加载透明背景
|
// 缓存Bitmap为空或已回收,提示并加载透明背景
|
||||||
@@ -174,7 +173,7 @@ public class BackgroundView extends RelativeLayout {
|
|||||||
|
|
||||||
// 2. 路径已更新:移除旧缓存,加载新图片并更新缓存
|
// 2. 路径已更新:移除旧缓存,加载新图片并更新缓存
|
||||||
if (!TextUtils.isEmpty(mCurrentCachedPath)) {
|
if (!TextUtils.isEmpty(mCurrentCachedPath)) {
|
||||||
App._mBitmapCacheUtils.removeCachedBitmap(mCurrentCachedPath);
|
App.sBitmapCacheUtils.removeCachedBitmap(mCurrentCachedPath);
|
||||||
LogUtils.d(TAG, "loadImage: 路径已更新,移除旧缓存 - " + mCurrentCachedPath);
|
LogUtils.d(TAG, "loadImage: 路径已更新,移除旧缓存 - " + mCurrentCachedPath);
|
||||||
}
|
}
|
||||||
// ======================== 路径判断逻辑结束 ========================
|
// ======================== 路径判断逻辑结束 ========================
|
||||||
@@ -194,13 +193,12 @@ public class BackgroundView extends RelativeLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 缓存新图片,并更新当前缓存路径记录
|
// 缓存新图片,并更新当前缓存路径记录
|
||||||
App._mBitmapCacheUtils.cacheBitmap(imagePath);
|
App.sBitmapCacheUtils.cacheBitmap(imagePath);
|
||||||
mCurrentCachedPath = imagePath;
|
mCurrentCachedPath = imagePath;
|
||||||
LogUtils.d(TAG, "loadImage: 加载新图片并更新缓存 - " + imagePath);
|
LogUtils.d(TAG, "loadImage: 加载新图片并更新缓存 - " + imagePath);
|
||||||
|
|
||||||
mIvBackground.setImageDrawable(new BitmapDrawable(mContext.getResources(), bitmap));
|
mIvBackground.setImageDrawable(new BitmapDrawable(mContext.getResources(), bitmap));
|
||||||
adjustImageViewSize();
|
adjustImageViewSize();
|
||||||
mIvBackground.setVisibility(View.VISIBLE);
|
|
||||||
LogUtils.d(TAG, "=== loadImage 完成 ===");
|
LogUtils.d(TAG, "=== loadImage 完成 ===");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,7 +269,7 @@ public class BackgroundView extends RelativeLayout {
|
|||||||
params.height = ivHeight;
|
params.height = ivHeight;
|
||||||
mIvBackground.setLayoutParams(params);
|
mIvBackground.setLayoutParams(params);
|
||||||
mIvBackground.setScaleType(ScaleType.FIT_CENTER);
|
mIvBackground.setScaleType(ScaleType.FIT_CENTER);
|
||||||
mIvBackground.setVisibility(View.VISIBLE);
|
//mIvBackground.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,14 +279,14 @@ public class BackgroundView extends RelativeLayout {
|
|||||||
mImageAspectRatio = 1.0f;
|
mImageAspectRatio = 1.0f;
|
||||||
// 清空缓存路径记录
|
// 清空缓存路径记录
|
||||||
mCurrentCachedPath = "";
|
mCurrentCachedPath = "";
|
||||||
mIvBackground.setVisibility(View.GONE);
|
//mIvBackground.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ====================================== 重写方法 ======================================
|
// ====================================== 重写方法 ======================================
|
||||||
@Override
|
@Override
|
||||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||||
super.onSizeChanged(w, h, oldw, oldh);
|
super.onSizeChanged(w, h, oldw, oldh);
|
||||||
adjustImageViewSize(); // 尺寸变化时重新调整
|
//adjustImageViewSize(); // 尺寸变化时重新调整
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import android.content.DialogInterface;
|
|||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
import android.widget.CheckBox;
|
import android.widget.CheckBox;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
@@ -14,6 +15,7 @@ import android.widget.RelativeLayout;
|
|||||||
import android.widget.Switch;
|
import android.widget.Switch;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import cc.winboll.studio.libappbase.LogUtils;
|
import cc.winboll.studio.libappbase.LogUtils;
|
||||||
|
import cc.winboll.studio.powerbell.App;
|
||||||
import cc.winboll.studio.powerbell.R;
|
import cc.winboll.studio.powerbell.R;
|
||||||
import cc.winboll.studio.powerbell.models.ControlCenterServiceBean;
|
import cc.winboll.studio.powerbell.models.ControlCenterServiceBean;
|
||||||
import cc.winboll.studio.powerbell.services.ControlCenterService;
|
import cc.winboll.studio.powerbell.services.ControlCenterService;
|
||||||
@@ -81,7 +83,8 @@ public class MainContentView {
|
|||||||
// 视图控件(按「布局→开关→文本→进度条→图标」功能归类)
|
// 视图控件(按「布局→开关→文本→进度条→图标」功能归类)
|
||||||
// 基础布局控件
|
// 基础布局控件
|
||||||
public RelativeLayout mainLayout;
|
public RelativeLayout mainLayout;
|
||||||
public BackgroundView backgroundView;
|
public MemoryCachedBackgroundView backgroundView;
|
||||||
|
LinearLayout mllBackgroundView;
|
||||||
// 容器布局控件
|
// 容器布局控件
|
||||||
public LinearLayout llLeftSeekBar;
|
public LinearLayout llLeftSeekBar;
|
||||||
public LinearLayout llRightSeekBar;
|
public LinearLayout llRightSeekBar;
|
||||||
@@ -144,7 +147,13 @@ public class MainContentView {
|
|||||||
LogUtils.d(TAG, "bindViews() | rootView=" + rootView);
|
LogUtils.d(TAG, "bindViews() | rootView=" + rootView);
|
||||||
// 基础布局绑定
|
// 基础布局绑定
|
||||||
mainLayout = (RelativeLayout) rootView.findViewById(R.id.activitymainRelativeLayout1);
|
mainLayout = (RelativeLayout) rootView.findViewById(R.id.activitymainRelativeLayout1);
|
||||||
backgroundView = (BackgroundView) rootView.findViewById(R.id.fragmentmainviewBackgroundView1);
|
//backgroundView = (BackgroundView) rootView.findViewById(R.id.fragmentmainviewBackgroundView1);
|
||||||
|
mllBackgroundView = (LinearLayout) rootView.findViewById(R.id.ll_backgroundview);
|
||||||
|
backgroundView = App.sMemoryCachedBackgroundView.getLastInstance(mContext);
|
||||||
|
if (backgroundView.getParent() != null) {
|
||||||
|
((ViewGroup) backgroundView.getParent()).removeView(backgroundView);
|
||||||
|
}
|
||||||
|
mllBackgroundView.addView(backgroundView);
|
||||||
// 容器布局绑定
|
// 容器布局绑定
|
||||||
llLeftSeekBar = (LinearLayout) rootView.findViewById(R.id.fragmentmainviewLinearLayout1);
|
llLeftSeekBar = (LinearLayout) rootView.findViewById(R.id.fragmentmainviewLinearLayout1);
|
||||||
llRightSeekBar = (LinearLayout) rootView.findViewById(R.id.fragmentmainviewLinearLayout2);
|
llRightSeekBar = (LinearLayout) rootView.findViewById(R.id.fragmentmainviewLinearLayout2);
|
||||||
|
|||||||
@@ -0,0 +1,229 @@
|
|||||||
|
package cc.winboll.studio.powerbell.views;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import cc.winboll.studio.libappbase.LogUtils;
|
||||||
|
import cc.winboll.studio.powerbell.models.BackgroundBean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
|
||||||
|
* @Date 2025/12/21 20:43
|
||||||
|
* @Describe 单实例缓存版背景视图控件(基于Java7)
|
||||||
|
* 核心:通过静态属性保存当前缓存路径和实例,支持强制重载图片
|
||||||
|
* 新增:SP持久化最后加载路径、获取最后加载实例功能
|
||||||
|
*/
|
||||||
|
public class MemoryCachedBackgroundView extends BackgroundView {
|
||||||
|
public static final String TAG = "MemoryCachedBackgroundView";
|
||||||
|
// 静态属性:保存当前缓存的路径和实例(替代原Map,仅维护单实例)
|
||||||
|
private static String sCachedImagePath;
|
||||||
|
private static MemoryCachedBackgroundView sCachedView;
|
||||||
|
// SP相关常量
|
||||||
|
private static final String SP_NAME = "MemoryCachedBackgroundView_SP";
|
||||||
|
private static final String KEY_LAST_LOAD_IMAGE_PATH = "last_load_image_path";
|
||||||
|
|
||||||
|
// ====================================== 构造器(继承并兼容父类) ======================================
|
||||||
|
private MemoryCachedBackgroundView(Context context) {
|
||||||
|
super(context);
|
||||||
|
LogUtils.d(TAG, "构造器1:创建MemoryCachedBackgroundView实例");
|
||||||
|
}
|
||||||
|
|
||||||
|
private MemoryCachedBackgroundView(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
LogUtils.d(TAG, "构造器2:创建MemoryCachedBackgroundView实例");
|
||||||
|
}
|
||||||
|
|
||||||
|
private MemoryCachedBackgroundView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
LogUtils.d(TAG, "构造器3:创建MemoryCachedBackgroundView实例");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================================== 核心静态方法:获取/创建缓存实例 ======================================
|
||||||
|
/**
|
||||||
|
* 从缓存获取或创建MemoryCachedBackgroundView实例
|
||||||
|
* @param context 上下文
|
||||||
|
* @param imagePath 图片绝对路径(作为缓存标识)
|
||||||
|
* @param isReload 是否强制重新加载图片(路径匹配时仍刷新)
|
||||||
|
* @return 缓存/新创建的MemoryCachedBackgroundView实例
|
||||||
|
*/
|
||||||
|
public static MemoryCachedBackgroundView getInstance(Context context, String imagePath, boolean isReload) {
|
||||||
|
LogUtils.d(TAG, "getInstance() 调用 | 图片路径:" + 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, "getInstance():强制重载图片 | " + imagePath);
|
||||||
|
sCachedView.loadImage(imagePath);
|
||||||
|
} else {
|
||||||
|
LogUtils.d(TAG, "getInstance():使用缓存实例,无需重载 | " + imagePath);
|
||||||
|
}
|
||||||
|
return sCachedView;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 路径不匹配/无缓存 → 新建实例并更新静态缓存
|
||||||
|
LogUtils.d(TAG, "getInstance():路径未缓存,新建实例 | " + imagePath);
|
||||||
|
sCachedView = new MemoryCachedBackgroundView(context);
|
||||||
|
sCachedImagePath = imagePath;
|
||||||
|
sCachedView.loadImage(imagePath);
|
||||||
|
return sCachedView;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================================== 新增功能:获取最后加载的实例 ======================================
|
||||||
|
/**
|
||||||
|
* 获取最后一次loadImage的路径对应的实例
|
||||||
|
* 无实例则创建并加载图片,同时更新静态缓存
|
||||||
|
* @param context 上下文
|
||||||
|
* @return 最后加载路径对应的实例
|
||||||
|
*/
|
||||||
|
public static MemoryCachedBackgroundView getLastInstance(Context context) {
|
||||||
|
LogUtils.d(TAG, "getLastInstance() 调用");
|
||||||
|
// 1. 从SP获取最后加载的路径
|
||||||
|
String lastPath = getLastLoadImagePath(context);
|
||||||
|
if (TextUtils.isEmpty(lastPath)) {
|
||||||
|
LogUtils.e(TAG, "getLastInstance():无最后加载路径,创建空实例");
|
||||||
|
return new MemoryCachedBackgroundView(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 路径匹配当前缓存 → 直接返回
|
||||||
|
if (lastPath.equals(sCachedImagePath) && sCachedView != null) {
|
||||||
|
LogUtils.d(TAG, "getLastInstance():使用最后路径缓存实例 | " + lastPath);
|
||||||
|
return sCachedView;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 路径不匹配 → 新建实例并更新缓存
|
||||||
|
LogUtils.d(TAG, "getLastInstance():最后路径未缓存,新建实例并加载 | " + lastPath);
|
||||||
|
sCachedView = new MemoryCachedBackgroundView(context);
|
||||||
|
sCachedImagePath = lastPath;
|
||||||
|
sCachedView.loadImage(lastPath);
|
||||||
|
return sCachedView;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================================== 工具方法:SP持久化最后加载路径 ======================================
|
||||||
|
/**
|
||||||
|
* 保存最后一次loadImage的路径到SP
|
||||||
|
* @param context 上下文
|
||||||
|
* @param imagePath 图片路径
|
||||||
|
*/
|
||||||
|
private static void saveLastLoadImagePath(Context context, String imagePath) {
|
||||||
|
if (TextUtils.isEmpty(imagePath) || context == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
|
||||||
|
sp.edit().putString(KEY_LAST_LOAD_IMAGE_PATH, imagePath).apply();
|
||||||
|
LogUtils.d(TAG, "saveLastLoadImagePath():已保存最后路径 | " + imagePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从SP获取最后一次loadImage的路径
|
||||||
|
* @param context 上下文
|
||||||
|
* @return 最后加载的图片路径,空则返回null
|
||||||
|
*/
|
||||||
|
public static String getLastLoadImagePath(Context context) {
|
||||||
|
if (context == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
|
||||||
|
String lastPath = sp.getString(KEY_LAST_LOAD_IMAGE_PATH, null);
|
||||||
|
LogUtils.d(TAG, "getLastLoadImagePath():获取最后路径 | " + lastPath);
|
||||||
|
return lastPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================================== 工具方法:缓存管理 ======================================
|
||||||
|
/**
|
||||||
|
* 清除当前缓存实例和路径
|
||||||
|
*/
|
||||||
|
public static void clearCache() {
|
||||||
|
LogUtils.d(TAG, "clearCache() 调用 | 当前缓存路径:" + sCachedImagePath);
|
||||||
|
sCachedView = null;
|
||||||
|
sCachedImagePath = null;
|
||||||
|
LogUtils.d(TAG, "clearCache():已清除当前缓存实例");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清除指定路径的缓存(仅当路径匹配当前缓存时生效)
|
||||||
|
* @param imagePath 图片路径
|
||||||
|
*/
|
||||||
|
public static void removeCache(String imagePath) {
|
||||||
|
LogUtils.d(TAG, "removeCache() 调用 | 图片路径:" + imagePath);
|
||||||
|
if (TextUtils.isEmpty(imagePath)) {
|
||||||
|
LogUtils.e(TAG, "removeCache():图片路径为空,清除失败");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (imagePath.equals(sCachedImagePath)) {
|
||||||
|
clearCache();
|
||||||
|
// 同步删除SP中最后路径记录
|
||||||
|
clearLastLoadImagePath(getContextFromCache());
|
||||||
|
LogUtils.d(TAG, "removeCache():已清除匹配路径的缓存 | " + imagePath);
|
||||||
|
} else {
|
||||||
|
LogUtils.d(TAG, "removeCache():路径不匹配当前缓存,无需清除 | " + imagePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清除所有缓存(同clearCache,保持方法兼容性)
|
||||||
|
*/
|
||||||
|
public static void clearAllCache() {
|
||||||
|
LogUtils.d(TAG, "clearAllCache() 调用");
|
||||||
|
clearCache();
|
||||||
|
clearLastLoadImagePath(getContextFromCache());
|
||||||
|
LogUtils.d(TAG, "clearAllCache():已清除所有缓存及最后路径记录");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否存在缓存实例
|
||||||
|
* @return 存在返回true,否则返回false
|
||||||
|
*/
|
||||||
|
public static boolean hasCache() {
|
||||||
|
return sCachedView != null && !TextUtils.isEmpty(sCachedImagePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清除SP中最后加载的路径记录
|
||||||
|
* @param context 上下文
|
||||||
|
*/
|
||||||
|
public static void clearLastLoadImagePath(Context context) {
|
||||||
|
if (context == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
|
||||||
|
sp.edit().remove(KEY_LAST_LOAD_IMAGE_PATH).apply();
|
||||||
|
LogUtils.d(TAG, "clearLastLoadImagePath():已清除最后路径记录");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================================== 辅助方法:从缓存获取上下文 ======================================
|
||||||
|
/**
|
||||||
|
* 从缓存实例中获取上下文(用于无外部上下文时的SP操作)
|
||||||
|
* @return 上下文实例,无则返回null
|
||||||
|
*/
|
||||||
|
private static Context getContextFromCache() {
|
||||||
|
return sCachedView != null ? sCachedView.getContext() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================================== 重写父类方法:增强日志+SP持久化 ======================================
|
||||||
|
@Override
|
||||||
|
public void loadImage(String imagePath) {
|
||||||
|
LogUtils.d(TAG, "loadImage() 重载方法调用 | 图片路径:" + imagePath);
|
||||||
|
super.loadImage(imagePath);
|
||||||
|
// 保存最后加载路径到SP
|
||||||
|
saveLastLoadImagePath(getContext(), imagePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadByBackgroundBean(BackgroundBean bean) {
|
||||||
|
LogUtils.d(TAG, "loadBackgroundBean() 重载方法调用 | BackgroundBean:" + (bean == null ? "null" : bean.toString()));
|
||||||
|
super.loadByBackgroundBean(bean);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadByBackgroundBean(BackgroundBean bean, boolean isRefresh) {
|
||||||
|
LogUtils.d(TAG, "loadBackgroundBean() 重载方法调用 | BackgroundBean:" + (bean == null ? "null" : bean.toString()) + " | 是否刷新:" + isRefresh);
|
||||||
|
super.loadByBackgroundBean(bean, isRefresh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BIN
powerbell/src/main/res/drawable/blank100x100.png
Normal file
BIN
powerbell/src/main/res/drawable/blank100x100.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 517 B |
@@ -40,17 +40,17 @@
|
|||||||
android:layout_width="160dp"
|
android:layout_width="160dp"
|
||||||
android:layout_height="36dp"
|
android:layout_height="36dp"
|
||||||
android:text="Origin BG"
|
android:text="Origin BG"
|
||||||
android:id="@+id/activitybackgroundpictureAButton5"
|
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_margin="5dp"/>
|
android:layout_margin="5dp"
|
||||||
|
android:id="@+id/activitybackgroundsettingsAButton1"/>
|
||||||
|
|
||||||
<cc.winboll.studio.libaes.views.AButton
|
<cc.winboll.studio.libaes.views.AButton
|
||||||
android:layout_width="160dp"
|
android:layout_width="160dp"
|
||||||
android:layout_height="36dp"
|
android:layout_height="36dp"
|
||||||
android:text="Received BG"
|
android:text="Received BG"
|
||||||
android:id="@+id/activitybackgroundpictureAButton4"
|
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
android:layout_margin="5dp"/>
|
android:layout_margin="5dp"
|
||||||
|
android:id="@+id/activitybackgroundsettingsAButton2"/>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@
|
|||||||
android:text="◎"
|
android:text="◎"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_margin="5dp"
|
android:layout_margin="5dp"
|
||||||
android:id="@+id/activitybackgroundpictureAButton1"/>
|
android:id="@+id/activitybackgroundsettingsAButton3"/>
|
||||||
|
|
||||||
<cc.winboll.studio.libaes.views.AButton
|
<cc.winboll.studio.libaes.views.AButton
|
||||||
android:layout_width="50dp"
|
android:layout_width="50dp"
|
||||||
@@ -74,7 +74,7 @@
|
|||||||
android:text="☑"
|
android:text="☑"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_margin="5dp"
|
android:layout_margin="5dp"
|
||||||
android:id="@+id/activitybackgroundpictureAButton2"/>
|
android:id="@+id/activitybackgroundsettingsAButton4"/>
|
||||||
|
|
||||||
<cc.winboll.studio.libaes.views.AButton
|
<cc.winboll.studio.libaes.views.AButton
|
||||||
android:layout_width="50dp"
|
android:layout_width="50dp"
|
||||||
@@ -82,8 +82,7 @@
|
|||||||
android:text="♾"
|
android:text="♾"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_margin="5dp"
|
android:layout_margin="5dp"
|
||||||
android:id="@+id/activitybackgroundpictureAButton9"
|
android:id="@+id/activitybackgroundsettingsAButton5"/>
|
||||||
android:onClick="onNetworkBackgroundDialog"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@@ -99,7 +98,7 @@
|
|||||||
android:text="[+]"
|
android:text="[+]"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_margin="5dp"
|
android:layout_margin="5dp"
|
||||||
android:id="@+id/activitybackgroundpictureAButton3"/>
|
android:id="@+id/activitybackgroundsettingsAButton6"/>
|
||||||
|
|
||||||
<cc.winboll.studio.libaes.views.AButton
|
<cc.winboll.studio.libaes.views.AButton
|
||||||
android:layout_width="50dp"
|
android:layout_width="50dp"
|
||||||
@@ -107,7 +106,7 @@
|
|||||||
android:text="[+~]"
|
android:text="[+~]"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_margin="5dp"
|
android:layout_margin="5dp"
|
||||||
android:id="@+id/activitybackgroundpictureAButton6"/>
|
android:id="@+id/activitybackgroundsettingsAButton7"/>
|
||||||
|
|
||||||
<cc.winboll.studio.libaes.views.AButton
|
<cc.winboll.studio.libaes.views.AButton
|
||||||
android:layout_width="50dp"
|
android:layout_width="50dp"
|
||||||
@@ -115,7 +114,7 @@
|
|||||||
android:text="[◐]"
|
android:text="[◐]"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_margin="5dp"
|
android:layout_margin="5dp"
|
||||||
android:id="@+id/activitybackgroundpictureAButton7"/>
|
android:id="@+id/activitybackgroundsettingsAButton8"/>
|
||||||
|
|
||||||
<cc.winboll.studio.libaes.views.AButton
|
<cc.winboll.studio.libaes.views.AButton
|
||||||
android:layout_width="50dp"
|
android:layout_width="50dp"
|
||||||
@@ -123,8 +122,8 @@
|
|||||||
android:text="[©]"
|
android:text="[©]"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_margin="5dp"
|
android:layout_margin="5dp"
|
||||||
android:id="@+id/activitybackgroundsettingsAButton1"
|
android:onClick="onColorPaletteDialog"
|
||||||
android:onClick="onColorPaletteDialog"/>
|
android:id="@+id/activitybackgroundsettingsAButton9"/>
|
||||||
|
|
||||||
<cc.winboll.studio.libaes.views.AButton
|
<cc.winboll.studio.libaes.views.AButton
|
||||||
android:layout_width="50dp"
|
android:layout_width="50dp"
|
||||||
@@ -132,7 +131,7 @@
|
|||||||
android:text="[○]"
|
android:text="[○]"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_margin="5dp"
|
android:layout_margin="5dp"
|
||||||
android:id="@+id/activitybackgroundpictureAButton8"/>
|
android:id="@+id/activitybackgroundsettingsAButton10"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<!-- 顶部Toolbar(首屏核心,同步加载,保留原有ASupportToolbar) -->
|
|
||||||
<cc.winboll.studio.libaes.views.ASupportToolbar
|
<cc.winboll.studio.libaes.views.ASupportToolbar
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/toolbar_height"
|
android:layout_height="@dimen/toolbar_height"
|
||||||
@@ -14,31 +13,29 @@
|
|||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
style="@style/DefaultAToolbar"/>
|
style="@style/DefaultAToolbar"/>
|
||||||
|
|
||||||
<!-- 主内容区(优化层级,减少冗余RelativeLayout) -->
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_weight="1.0">
|
android:layout_weight="1.0">
|
||||||
|
|
||||||
<!-- 首屏核心容器(合并原冗余RelativeLayout,减少层级) -->
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:id="@+id/activitymainRelativeLayout1">
|
android:id="@+id/activitymainRelativeLayout1">
|
||||||
|
|
||||||
<!-- 1. 背景视图(首屏核心,同步加载,保留原有) -->
|
<LinearLayout
|
||||||
<cc.winboll.studio.powerbell.views.BackgroundView
|
android:orientation="horizontal"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:id="@+id/fragmentmainviewBackgroundView1"/>
|
android:id="@+id/ll_backgroundview">
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<!-- 2. 功能控件容器(首屏核心,同步加载,保留原有结构) -->
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<!-- 服务总开关布局 -->
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -67,7 +64,6 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<!-- 电量控制核心布局(SeekBar+图标) -->
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -82,7 +78,6 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_weight="1.0">
|
android:layout_weight="1.0">
|
||||||
|
|
||||||
<!-- 耗电提醒布局 -->
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="50dp"
|
android:layout_width="50dp"
|
||||||
@@ -116,7 +111,6 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<!-- 耗电提醒数值+图标 -->
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="80dp"
|
android:layout_width="80dp"
|
||||||
@@ -139,7 +133,6 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<!-- 当前电量数值+图标 -->
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@@ -163,7 +156,6 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<!-- 充电提醒数值+图标 -->
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="80dp"
|
android:layout_width="80dp"
|
||||||
@@ -186,7 +178,6 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<!-- 充电提醒布局 -->
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="50dp"
|
android:layout_width="50dp"
|
||||||
@@ -224,7 +215,6 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<!-- Tips文本 -->
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_width="match_parent">
|
android:layout_width="match_parent">
|
||||||
@@ -242,14 +232,12 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<!-- 3. 广告视图:关键优化→用ViewStub延迟加载(替代原直接加载的ADsBannerView) -->
|
|
||||||
<!-- 首次启动仅占位(1px),不inflate真实广告视图,减少首次耗时 -->
|
|
||||||
<ViewStub
|
<ViewStub
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:id="@+id/stub_ads_banner"
|
android:id="@+id/stub_ads_banner"
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_alignParentBottom="true"
|
||||||
android:layout="@layout/view_ads_banner"/> <!-- 广告视图独立布局文件 -->
|
android:layout="@layout/view_ads_banner"/>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
|
|||||||
50
powerbell/src/main/res/layout/activity_mainunittest2.xml
Normal file
50
powerbell/src/main/res/layout/activity_mainunittest2.xml
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="#FF0C6BBF">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:id="@+id/ll_backgroundview">
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<HorizontalScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="#AF4FDA4E">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Main"
|
||||||
|
android:id="@+id/btn_main_activity"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="TestCropImage"
|
||||||
|
android:id="@+id/btn_test_cropimage"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</HorizontalScrollView>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
@@ -13,11 +13,20 @@
|
|||||||
android:id="@+id/tv_dialog_title"
|
android:id="@+id/tv_dialog_title"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="网络后台提示"
|
android:text="网络图片资源下载"
|
||||||
android:textSize="18sp"
|
android:textSize="18sp"
|
||||||
android:textColor="@android:color/black"
|
android:textColor="@android:color/black"
|
||||||
android:textStyle="bold"/>
|
android:textStyle="bold"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_dialog_content"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:text="请输入网络图片地址:"
|
||||||
|
android:textSize="15sp"
|
||||||
|
android:textColor="@android:color/darker_gray"/>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -54,15 +63,6 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tv_dialog_content"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="12dp"
|
|
||||||
android:text="应用正在后台使用网络,是否继续允许?"
|
|
||||||
android:textSize="15sp"
|
|
||||||
android:textColor="@android:color/darker_gray"/>
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@@ -74,7 +74,7 @@
|
|||||||
android:id="@+id/btn_cancel"
|
android:id="@+id/btn_cancel"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="取消"
|
android:text="关闭返回"
|
||||||
android:textSize="14sp"
|
android:textSize="14sp"
|
||||||
android:background="@android:drawable/btn_default_small"
|
android:background="@android:drawable/btn_default_small"
|
||||||
android:layout_marginRight="8dp"/>
|
android:layout_marginRight="8dp"/>
|
||||||
@@ -83,7 +83,7 @@
|
|||||||
android:id="@+id/btn_confirm"
|
android:id="@+id/btn_confirm"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="允许"
|
android:text="使用图片"
|
||||||
android:textSize="14sp"
|
android:textSize="14sp"
|
||||||
android:background="@android:drawable/btn_default_small"/>
|
android:background="@android:drawable/btn_default_small"/>
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,10 @@
|
|||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_unittestactivity"
|
android:id="@+id/action_unittestactivity"
|
||||||
android:title="@string/item_mainunittestactivity"/>
|
android:title="MainUnitTestActivity"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_unittest2activity"
|
||||||
|
android:title="MainUnitTest2Activity"/>
|
||||||
|
|
||||||
</menu>
|
</menu>
|
||||||
|
|||||||
Reference in New Issue
Block a user