Compare commits
11 Commits
powerbell-
...
powerbell-
| Author | SHA1 | Date | |
|---|---|---|---|
| c8333e1e81 | |||
| 6beb56efae | |||
| eb51b2c8f4 | |||
| 36bdd059b0 | |||
| bf051dcc9f | |||
| b38a8df462 | |||
| a8dbe43d4b | |||
| 05a8dc5205 | |||
| 280fc1abd6 | |||
| fe2084f5ff | |||
| 2a75aa140e |
@@ -1,8 +1,8 @@
|
||||
#Created by .winboll/winboll_app_build.gradle
|
||||
#Sat Dec 20 19:28:00 HKT 2025
|
||||
stageCount=12
|
||||
#Sun Dec 21 11:22:23 HKT 2025
|
||||
stageCount=15
|
||||
libraryProject=
|
||||
baseVersion=15.14
|
||||
publishVersion=15.14.11
|
||||
publishVersion=15.14.14
|
||||
buildCount=0
|
||||
baseBetaVersion=15.14.12
|
||||
baseBetaVersion=15.14.15
|
||||
|
||||
@@ -4,54 +4,73 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="cc.winboll.studio.powerbell">
|
||||
|
||||
<!-- ====================== 原有权限保留 + 补充核心权限 ====================== -->
|
||||
<!-- 运行前台服务(原有保留,补充 Android 12+ 特殊前台服务权限) -->
|
||||
<!-- 运行前台服务 -->
|
||||
<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.POST_NOTIFICATIONS"/>
|
||||
|
||||
<!-- 应用使用统计相关(原有保留,忽略保护权限警告) -->
|
||||
<!-- 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.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
|
||||
android:name="android.permission.ACCESS_PACKAGE_USAGE_STATS"
|
||||
tools:ignore="ProtectedPermissions"/>
|
||||
|
||||
<!-- 相机相关(原有保留,补充权限等级声明,避免安装警告) -->
|
||||
<uses-feature
|
||||
android:name="android.hardware.camera"
|
||||
android:required="false"/> <!-- 非核心功能设为非必须,兼容无相机设备 -->
|
||||
<uses-feature
|
||||
android:name="android.hardware.camera.autofocus"
|
||||
<uses-feature
|
||||
android:name="android.hardware.camera"
|
||||
android:required="false"/>
|
||||
<uses-permission android:name="android.permission.CAMERA" /> <!-- 补充相机权限,原有仅声明feature无权限 -->
|
||||
|
||||
<!-- 应用信息相关(原有保留) -->
|
||||
<uses-feature
|
||||
android:name="android.hardware.camera.autofocus"
|
||||
android:required="false"/>
|
||||
|
||||
<uses-permission android:name="android.permission.CAMERA"/>
|
||||
|
||||
<uses-permission android:name="android.permission.GET_PACKAGE_SIZE"/>
|
||||
|
||||
<uses-permission
|
||||
android:name="android.permission.QUERY_ALL_PACKAGES"
|
||||
tools:ignore="QueryAllPackagesPermission"/>
|
||||
|
||||
<!-- 新增:文件管理权限(对应 PermissionUtils 全文件管理逻辑) -->
|
||||
<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+ 全文件权限 -->
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
|
||||
<!-- 新增:忽略电池优化权限(对应 PermissionUtils 电池优化逻辑,必须声明) -->
|
||||
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
|
||||
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
|
||||
|
||||
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
|
||||
|
||||
<!-- 新增:API30+ 跳转系统权限页兼容(避免自启/文件权限跳转失败) -->
|
||||
<queries>
|
||||
<!-- 全文件管理权限跳转兼容 -->
|
||||
|
||||
<!-- 小米自启权限跳转兼容(精准匹配安全中心包名) -->
|
||||
<package android:name="com.miui.securitycenter" />
|
||||
<!-- 电池优化权限跳转兼容 -->
|
||||
<package android:name="com.miui.securitycenter"/>
|
||||
|
||||
</queries>
|
||||
|
||||
@@ -68,17 +87,17 @@
|
||||
android:supportsRtl="true"
|
||||
tools:ignore="GoogleAppIndexingWarning,UnusedAttribute">
|
||||
|
||||
<!-- ====================== 页面配置(原有保留,优化 exported 安全) ====================== -->
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/app_name"
|
||||
android:exported="true"
|
||||
android:launchMode="singleTask">
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
<activity
|
||||
android:name=".activities.CrashActivity"
|
||||
android:exported="false"/> <!-- 新增:非外部调用,设为 false,提升安全 -->
|
||||
android:exported="false"/>
|
||||
|
||||
<activity-alias
|
||||
android:name=".MainActivityEN1"
|
||||
@@ -87,13 +106,19 @@
|
||||
android:label="@string/app_name"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:enabled="true">
|
||||
|
||||
<intent-filter>
|
||||
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.app.shortcuts"
|
||||
android:resource="@xml/shortcutsmainen1"/>
|
||||
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
@@ -103,13 +128,19 @@
|
||||
android:label="@string/app_name_cn1"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:enabled="false">
|
||||
|
||||
<intent-filter>
|
||||
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.app.shortcuts"
|
||||
android:resource="@xml/shortcutsmaincn1"/>
|
||||
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
@@ -119,53 +150,71 @@
|
||||
android:label="@string/app_name_cn2"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:enabled="false">
|
||||
|
||||
<intent-filter>
|
||||
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.app.shortcuts"
|
||||
android:resource="@xml/shortcutsmaincn2"/>
|
||||
|
||||
</activity-alias>
|
||||
|
||||
<activity
|
||||
android:name=".activities.ClearRecordActivity"
|
||||
android:parentActivityName="cc.winboll.studio.powerbell.MainActivity"
|
||||
android:launchMode="singleTask"
|
||||
android:exported="false"/> <!-- 新增:非外部调用,设为 false -->
|
||||
android:exported="false"/>
|
||||
|
||||
<activity
|
||||
android:name=".activities.BackgroundSettingsActivity"
|
||||
android:parentActivityName="cc.winboll.studio.powerbell.MainActivity"
|
||||
android:exported="true"
|
||||
android:launchMode="singleTask">
|
||||
|
||||
<intent-filter>
|
||||
|
||||
<action android:name="android.intent.action.SEND"/>
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
|
||||
<data android:mimeType="image/jpeg"/>
|
||||
|
||||
<data android:mimeType="image/jpg"/>
|
||||
|
||||
<data android:mimeType="image/png"/>
|
||||
|
||||
<data android:mimeType="image/webp"/>
|
||||
|
||||
<data android:mimeType="image/*"/>
|
||||
|
||||
</intent-filter>
|
||||
|
||||
</activity>
|
||||
|
||||
<!-- ====================== 广播接收器(优化自启广播,提升保活成功率) ====================== -->
|
||||
<receiver
|
||||
android:name=".receivers.MainReceiver"
|
||||
android:enabled="true"
|
||||
android:exported="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.POWER_CONNECTED"/>
|
||||
|
||||
<action android:name="android.intent.action.USER_PRESENT"/>
|
||||
|
||||
</intent-filter>
|
||||
|
||||
</receiver>
|
||||
|
||||
<!-- ====================== 服务配置(核心优化:前台服务保活,适配 API29-30) ====================== -->
|
||||
<!-- 核心前台服务:ControlCenterService(保活核心,重点优化) -->
|
||||
<service
|
||||
android:name=".services.ControlCenterService"
|
||||
android:priority="1000"
|
||||
@@ -173,67 +222,72 @@
|
||||
android:exported="false"
|
||||
android:process=".controlcenterservice"
|
||||
android:foregroundServiceType="dataSync">
|
||||
<!-- 新增:Android 12+ 前台服务用途声明(系统强制,否则拦截服务启动) -->
|
||||
|
||||
<property
|
||||
android:name="android.app.PROPERTY_SPECIAL_USE_FOREGROUND_SERVICE"
|
||||
android:value="后台核心功能运行、持续保活" /> <!-- 按实际用途填写,不可空 -->
|
||||
android:value="后台核心功能运行、持续保活"/>
|
||||
|
||||
</service>
|
||||
|
||||
<!-- 辅助服务:AssistantService(按需优化,增强稳定性) -->
|
||||
<service
|
||||
android:name=".services.AssistantService"
|
||||
android:enabled="true"
|
||||
android:exported="false"
|
||||
android:process=".assistantservice"> <!-- 若需前台启动,添加此配置;纯后台可移除 -->
|
||||
android:process=".assistantservice">
|
||||
|
||||
<property
|
||||
android:name="android.app.PROPERTY_SPECIAL_USE_FOREGROUND_SERVICE"
|
||||
android:value="辅助核心功能运行" />
|
||||
android:value="辅助核心功能运行"/>
|
||||
|
||||
</service>
|
||||
|
||||
<!-- ====================== 其他配置(原有保留,补充优化) ====================== -->
|
||||
<meta-data
|
||||
android:name="android.max_aspect"
|
||||
android:value="4.0"/>
|
||||
|
||||
<!-- 所有非外部调用的 Activity,统一设 exported=false,提升安全 -->
|
||||
<activity
|
||||
<activity
|
||||
android:name=".activities.BatteryReporterActivity"
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
|
||||
<activity
|
||||
android:name=".activities.PixelPickerActivity"
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
|
||||
<activity
|
||||
android:name=".activities.BatteryReportActivity"
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
|
||||
<activity
|
||||
android:name=".unittest.MainUnitTestActivity"
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
|
||||
<activity
|
||||
android:name=".activities.ShortcutActionActivity"
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
|
||||
<activity
|
||||
android:name=".activities.SettingsActivity"
|
||||
android:exported="false"/>
|
||||
|
||||
<!-- 文件提供者(原有保留,正常使用) -->
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.fileprovider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/file_provider"/>
|
||||
|
||||
</provider>
|
||||
|
||||
<!-- UCrop 第三方页面(原有保留,exported=true 正常) -->
|
||||
<activity
|
||||
android:name="com.yalantis.ucrop.UCropActivity"
|
||||
android:theme="@style/Theme.AppCompat.Light.NoActionBar"
|
||||
android:exported="true">
|
||||
|
||||
</activity>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
||||
</manifest>
|
||||
BIN
powerbell/src/main/assets/images/blank100x100.png
Normal file
BIN
powerbell/src/main/assets/images/blank100x100.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 517 B |
Binary file not shown.
|
Before Width: | Height: | Size: 100 B |
@@ -1,5 +1,6 @@
|
||||
package cc.winboll.studio.powerbell;
|
||||
|
||||
import android.content.ComponentCallbacks2;
|
||||
import android.content.Context;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
@@ -9,11 +10,13 @@ import cc.winboll.studio.libappbase.GlobalApplication;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.libappbase.ToastUtils;
|
||||
import cc.winboll.studio.powerbell.models.BackgroundBean;
|
||||
import cc.winboll.studio.powerbell.models.NotificationMessage;
|
||||
import cc.winboll.studio.powerbell.receivers.GlobalApplicationReceiver;
|
||||
import cc.winboll.studio.powerbell.utils.AppCacheUtils;
|
||||
import cc.winboll.studio.powerbell.utils.AppConfigUtils;
|
||||
import cc.winboll.studio.powerbell.utils.BackgroundSourceUtils;
|
||||
import cc.winboll.studio.powerbell.utils.BitmapCacheUtils;
|
||||
import cc.winboll.studio.powerbell.utils.NotificationManagerUtils;
|
||||
import java.io.File;
|
||||
|
||||
public class App extends GlobalApplication {
|
||||
@@ -26,14 +29,20 @@ public class App extends GlobalApplication {
|
||||
public static final String ACTION_SWITCHTO_CN1 = "cc.winboll.studio.powerbell.App.ACTION_SWITCHTO_CN1";
|
||||
public static final String ACTION_SWITCHTO_CN2 = "cc.winboll.studio.powerbell.App.ACTION_SWITCHTO_CN2";
|
||||
|
||||
// 内存紧张通知常量
|
||||
private static final String TRIM_MEMORY_NOTIFY_TITLE = "应用使用时内存紧张提醒";
|
||||
private static final String TRIM_MEMORY_NOTIFY_CONTENT = "由于本应用使用时,系统通知内存紧张程度级别较高,图片缓存功能暂时不启用。";
|
||||
|
||||
// 数据配置存储工具
|
||||
static AppConfigUtils _mAppConfigUtils;
|
||||
static AppCacheUtils _mAppCacheUtils;
|
||||
// 新增:全局 Bitmap 缓存工具(常驻内存)
|
||||
// 全局 Bitmap 缓存工具(常驻内存)
|
||||
public static BitmapCacheUtils _mBitmapCacheUtils;
|
||||
|
||||
GlobalApplicationReceiver mReceiver;
|
||||
static String szTempDir = "";
|
||||
// 通知工具类实例(用于发送内存紧张通知)
|
||||
private NotificationManagerUtils mNotificationManager;
|
||||
|
||||
public static String getTempDirPath() {
|
||||
return szTempDir;
|
||||
@@ -60,13 +69,17 @@ public class App extends GlobalApplication {
|
||||
// 设置数据配置存储工具
|
||||
_mAppConfigUtils = getAppConfigUtils(this);
|
||||
_mAppCacheUtils = getAppCacheUtils(this);
|
||||
// 初始化全局 Bitmap 缓存工具(关键:App 启动时初始化,常驻内存)
|
||||
// 初始化全局 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() {
|
||||
@@ -74,23 +87,19 @@ public class App extends GlobalApplication {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
// 1. 获取背景源工具类实例
|
||||
BackgroundSourceUtils bgSourceUtils = BackgroundSourceUtils.getInstance(App.this);
|
||||
if (bgSourceUtils == null) {
|
||||
LogUtils.e(TAG, "preloadBitmap: BackgroundSourceUtils 实例为空");
|
||||
return;
|
||||
}
|
||||
// 2. 获取当前背景Bean
|
||||
BackgroundBean bgBean = bgSourceUtils.getCurrentBackgroundBean();
|
||||
if (bgBean == null || !bgBean.isUseBackgroundFile()) {
|
||||
LogUtils.d(TAG, "preloadBitmap: 无有效背景文件,跳过预加载");
|
||||
return;
|
||||
}
|
||||
// 3. 获取背景图路径(优先取压缩图路径)
|
||||
String bgPath = bgBean.isUseBackgroundScaledCompressFile()
|
||||
? bgBean.getBackgroundScaledCompressFilePath()
|
||||
: bgBean.getBackgroundFilePath();
|
||||
// 4. 预加载到全局缓存
|
||||
if (_mBitmapCacheUtils != null) {
|
||||
_mBitmapCacheUtils.cacheBitmap(bgPath);
|
||||
LogUtils.d(TAG, "preloadBitmap: 应用启动时预加载成功 - " + bgPath);
|
||||
@@ -103,8 +112,7 @@ public class App extends GlobalApplication {
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}, 1000); // 延迟1秒执行,避免阻塞应用初始化
|
||||
// ======================== 预加载逻辑结束 ========================
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
// 保持原有方法不变
|
||||
@@ -130,11 +138,91 @@ public class App extends GlobalApplication {
|
||||
public void onTerminate() {
|
||||
super.onTerminate();
|
||||
ToastUtils.release();
|
||||
// 释放通知工具类资源,避免内存泄漏
|
||||
if (mNotificationManager != null) {
|
||||
mNotificationManager.release();
|
||||
mNotificationManager = null;
|
||||
LogUtils.d(TAG, "onTerminate: 通知工具类资源已释放");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTrimMemory(int level) {
|
||||
super.onTrimMemory(level);
|
||||
LogUtils.d(TAG, "onTrimMemory: 内存等级变化 | level=" + getTrimMemoryLevelDesc(level));
|
||||
|
||||
// 仅在中等及以上内存紧张等级发送通知,避免频繁打扰
|
||||
if (mNotificationManager == null) {
|
||||
mNotificationManager = new NotificationManagerUtils(this);
|
||||
}
|
||||
if (level > ComponentCallbacks2.TRIM_MEMORY_MODERATE) {
|
||||
sendTrimMemoryNotification(level);
|
||||
} else {
|
||||
// 再次缓存 Bitmap 缓存工具
|
||||
_mBitmapCacheUtils = BitmapCacheUtils.getInstance();
|
||||
LogUtils.d(TAG, "Bitmap 缓存启用中。");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送内存紧张通知(完全复用 NotificationManagerUtils 的 showRemindNotification 方法)
|
||||
*/
|
||||
private void sendTrimMemoryNotification(int level) {
|
||||
LogUtils.d(TAG, "sendTrimMemoryNotification: 准备发送内存紧张通知");
|
||||
// 构建通知消息体
|
||||
NotificationMessage message = new NotificationMessage();
|
||||
message.setTitle(TRIM_MEMORY_NOTIFY_TITLE);
|
||||
message.setContent(String.format("%s [ 缓存紧张级别描述: Level %d | %s ]",TRIM_MEMORY_NOTIFY_CONTENT, level, getTrimMemoryLevelDesc(level)));
|
||||
// 使用整理后的 NotificationManagerUtils 发送通知(复用提醒渠道配置)
|
||||
mNotificationManager.showConfigNotification(this, message);
|
||||
LogUtils.d(TAG, "sendTrimMemoryNotification: 通知已通过 NotificationManagerUtils 发送");
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换内存等级为可读描述,便于日志调试
|
||||
* 排序规则:按 ComponentCallbacks2 枚举数值从高到低排列(数值越高,内存越紧张)
|
||||
*/
|
||||
/**
|
||||
* 转换内存等级为可读描述,便于日志调试
|
||||
* 排序规则:按 ComponentCallbacks2 枚举实际数值(10进制)从高到低排列
|
||||
* 数值来源:接口中定义的 16进制(注释10进制)数值
|
||||
*/
|
||||
private String getTrimMemoryLevelDesc(int level) {
|
||||
switch (level) {
|
||||
// 数值 80(0x50):应用内存完全紧张(补充接口中实际存在的枚举项)
|
||||
case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
|
||||
return "TRIM_MEMORY_COMPLETE(应用内存完全紧张)";
|
||||
// 数值 60(0x3c):中等内存紧张
|
||||
case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
|
||||
return "MODERATE(中等内存紧张)";
|
||||
// 数值 40(0x28):应用进入后台
|
||||
case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND:
|
||||
return "BACKGROUND(应用进入后台)";
|
||||
// 数值 20(0x14):应用UI隐藏
|
||||
case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:
|
||||
return "BACKGROUND(应用UI隐藏)";
|
||||
// 数值 15(0xf):应用运行时关键级紧张
|
||||
case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL:
|
||||
return "RUNNING_CRITICAL(应用运行关键级紧张)";
|
||||
// 数值 10(0xa):应用运行时低内存
|
||||
case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW:
|
||||
return "RUNNING_LOW(应用运行低内存)";
|
||||
// 数值 5(0x5):应用运行时中等紧张
|
||||
case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE:
|
||||
return "RUNNING_MODERATE(应用运行中等内存紧张)";
|
||||
|
||||
// 以下为注释备用项(接口中未提供,按你的原有注释保留)
|
||||
// 数值 100:内存极度紧张(系统可能强制杀死应用)
|
||||
// case ComponentCallbacks2.TRIM_MEMORY_URGENT:
|
||||
// return "URGENT(内存极度紧张)";
|
||||
// 数值 20:用户正在离开应用(如按Home键)
|
||||
// case ComponentCallbacks2.TRIM_MEMORY_USER_LEAVING:
|
||||
// return "USER_LEAVING(用户正在离开应用)";
|
||||
|
||||
// 未知等级
|
||||
default:
|
||||
return "UNKNOWN(" + level + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,6 +21,7 @@ import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import cc.winboll.studio.powerbell.utils.ImageDownloader;
|
||||
import cc.winboll.studio.powerbell.utils.BackgroundSourceUtils;
|
||||
import android.text.TextUtils;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
|
||||
@@ -52,7 +53,7 @@ public class NetworkBackgroundDialog extends AlertDialog {
|
||||
|
||||
// 按钮点击回调接口(Java7 接口实现)
|
||||
public interface OnDialogClickListener {
|
||||
void onConfirm(String szConfirmFilePath, String previewFileUrl); // 确认按钮点击
|
||||
void onConfirm(String szConfirmFilePath); // 确认按钮点击
|
||||
void onCancel(); // 取消按钮点击
|
||||
}
|
||||
|
||||
@@ -91,7 +92,7 @@ public class NetworkBackgroundDialog extends AlertDialog {
|
||||
case MSG_IMAGE_LOAD_SUCCESS:
|
||||
// 图片加载成功,获取文件路径并设置背景
|
||||
mDownloadSavedPath = (String) msg.obj;
|
||||
previewBackground(mDownloadSavedPath);
|
||||
mBackgroundView.loadImage(mDownloadSavedPath);
|
||||
break;
|
||||
case MSG_IMAGE_LOAD_FAILED:
|
||||
// 图片加载失败,设置默认背景
|
||||
@@ -139,7 +140,7 @@ public class NetworkBackgroundDialog extends AlertDialog {
|
||||
etURL = (EditText) dialogView.findViewById(R.id.et_url);
|
||||
mBackgroundView = (BackgroundView) dialogView.findViewById(R.id.bv_background_preview);
|
||||
// 加载初始图片
|
||||
mBackgroundView.setBackgroundResource(R.drawable.ic_launcher);
|
||||
mBackgroundView.setBackgroundResource(R.drawable.blank100x100);
|
||||
// 设置按钮点击事件
|
||||
setButtonClickListeners();
|
||||
}
|
||||
@@ -168,13 +169,13 @@ public class NetworkBackgroundDialog extends AlertDialog {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
LogUtils.d("NetworkBackgroundDialog", "确认按钮点击");
|
||||
// 确定预览背景资源
|
||||
BackgroundSourceUtils utils = BackgroundSourceUtils.getInstance(mContext);
|
||||
utils.saveFileToPreviewBean(new File(mPreviewFilePath), mPreviewFileUrl);
|
||||
|
||||
dismiss(); // 关闭对话框
|
||||
if(TextUtils.isEmpty(mDownloadSavedPath)) {
|
||||
ToastUtils.show("未下载图片。");
|
||||
return;
|
||||
}
|
||||
if (listener != null) {
|
||||
listener.onConfirm(mPreviewFilePath, mPreviewFileUrl);
|
||||
listener.onConfirm(mDownloadSavedPath);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -258,6 +259,7 @@ public class NetworkBackgroundDialog extends AlertDialog {
|
||||
// 发送消息到主线程,携带图片路径
|
||||
Message successMsg = mUiHandler.obtainMessage(MSG_IMAGE_LOAD_SUCCESS, savePath);
|
||||
mUiHandler.sendMessage(successMsg);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -222,10 +222,14 @@ public class RemindThread extends Thread {
|
||||
} else if (!isCharging && isEnableUsageReminder && quantityOfElectricity <= usageReminderValue) {
|
||||
LogUtils.d(TAG, "触发耗电提醒 | 当前电量=" + quantityOfElectricity + " ≤ 阈值=" + usageReminderValue + " | threadId=" + getId());
|
||||
sendNotificationMessageInternal(REMIND_TYPE_USAGE, quantityOfElectricity, isCharging);
|
||||
}
|
||||
|
||||
// 安全休眠,保留中断标记
|
||||
} else {
|
||||
// 未有合适类型提醒,退出提醒线程
|
||||
LogUtils.d(TAG, "未有合适类型提醒,退出提醒线程");
|
||||
break;
|
||||
}
|
||||
// 安全休眠,保留中断标记
|
||||
safeSleepInternal(sleepTime);
|
||||
|
||||
} catch (Exception e) {
|
||||
LogUtils.e(TAG, "循环运行异常,退出电量提醒线程 | 当前电量=" + quantityOfElectricity + " | threadId=" + getId(), e);
|
||||
break;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package cc.winboll.studio.powerbell.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.media.ExifInterface;
|
||||
import android.net.Uri;
|
||||
@@ -11,6 +12,7 @@ import androidx.core.content.FileProvider;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.libappbase.ToastUtils;
|
||||
import cc.winboll.studio.powerbell.BuildConfig;
|
||||
import cc.winboll.studio.powerbell.R;
|
||||
import cc.winboll.studio.powerbell.models.BackgroundBean;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
@@ -181,37 +183,42 @@ public class BackgroundSourceUtils {
|
||||
/**
|
||||
* 检查背景是否为空并创建空白背景Bean
|
||||
*/
|
||||
boolean checkEmptyBackgroundAndCreateBlankBackgroundBean(BackgroundBean checkBackgroundBean) {
|
||||
public boolean checkEmptyBackgroundAndCreateBlankBackgroundBean(BackgroundBean checkBackgroundBean) {
|
||||
LogUtils.d(TAG, "【checkEmptyBackgroundAndCreateBlankBackgroundBean调用】开始检查背景Bean");
|
||||
File fCheckBackgroundFile = new File(checkBackgroundBean.getBackgroundFilePath());
|
||||
if (!fCheckBackgroundFile.exists()) {
|
||||
String newCropFileName = genNewCropFileName();
|
||||
String fileSuffix = "png";
|
||||
mCropSourceFile = new File(fCropCacheDir, newCropFileName + "." + fileSuffix);
|
||||
mCropResultFile = new File(fCropCacheDir, "SelectCompress_" + newCropFileName + "." + fileSuffix);
|
||||
|
||||
AssetsCopyUtils.copyAssetsFileToDir(mContext, "images/blank10x10.png", mCropSourceFile.getAbsolutePath());
|
||||
try {
|
||||
mCropResultFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
}
|
||||
|
||||
loadSettings();
|
||||
previewBackgroundBean.setIsUseBackgroundFile(true);
|
||||
previewBackgroundBean.setIsUseBackgroundScaledCompressFile(false);
|
||||
previewBackgroundBean.setBackgroundFileName(mCropSourceFile.getName());
|
||||
previewBackgroundBean.setBackgroundFilePath(mCropSourceFile.getAbsolutePath());
|
||||
previewBackgroundBean.setBackgroundScaledCompressFileName(mCropResultFile.getName());
|
||||
previewBackgroundBean.setBackgroundScaledCompressFilePath(mCropResultFile.getAbsolutePath());
|
||||
saveSettings();
|
||||
LogUtils.d(TAG, "背景Bean为空,已创建空白背景并更新配置");
|
||||
return true;
|
||||
return createBlankBackgroundBean(checkBackgroundBean.getPixelColor());
|
||||
}
|
||||
LogUtils.d(TAG, "背景Bean文件存在,无需创建空白背景");
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean createBlankBackgroundBean(int nBackgroundPixelColor) {
|
||||
String newCropFileName = genNewCropFileName();
|
||||
String fileSuffix = "png";
|
||||
mCropSourceFile = new File(fCropCacheDir, newCropFileName + "." + fileSuffix);
|
||||
mCropResultFile = new File(fCropCacheDir, "SelectCompress_" + newCropFileName + "." + fileSuffix);
|
||||
|
||||
AssetsCopyUtils.copyAssetsFileToDir(mContext, "images/blank100x100.png", mCropSourceFile.getAbsolutePath());
|
||||
try {
|
||||
mCropResultFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
}
|
||||
|
||||
loadSettings();
|
||||
previewBackgroundBean.setPixelColor(nBackgroundPixelColor);
|
||||
previewBackgroundBean.setIsUseBackgroundFile(true);
|
||||
previewBackgroundBean.setIsUseBackgroundScaledCompressFile(false);
|
||||
previewBackgroundBean.setBackgroundFileName(mCropSourceFile.getName());
|
||||
previewBackgroundBean.setBackgroundFilePath(mCropSourceFile.getAbsolutePath());
|
||||
previewBackgroundBean.setBackgroundScaledCompressFileName(mCropResultFile.getName());
|
||||
previewBackgroundBean.setBackgroundScaledCompressFilePath(mCropResultFile.getAbsolutePath());
|
||||
saveSettings();
|
||||
LogUtils.d(TAG, "背景Bean为空,已创建空白背景并更新配置");
|
||||
return true;
|
||||
}
|
||||
|
||||
String genNewCropFileName() {
|
||||
return UUID.randomUUID().toString() + System.currentTimeMillis();
|
||||
}
|
||||
|
||||
@@ -20,9 +20,9 @@ import cc.winboll.studio.powerbell.R;
|
||||
import cc.winboll.studio.powerbell.models.NotificationMessage;
|
||||
|
||||
/**
|
||||
* 通知工具类:统一管理前台服务/电池提醒通知
|
||||
* 通知工具类:统一管理前台服务/电池提醒/应用配置信息通知
|
||||
* 适配:API19-30 | Java7 | 小米手机
|
||||
* 特性:前台服务无铃声、提醒通知系统默认铃声、API分级适配、内存泄漏防护
|
||||
* 特性:前台服务无铃声、提醒通知系统默认铃声、配置通知低优先级无打扰、API分级适配、内存泄漏防护
|
||||
*/
|
||||
public class NotificationManagerUtils {
|
||||
// ================================== 静态常量(置顶统一管理,杜绝魔法值)=================================
|
||||
@@ -30,9 +30,11 @@ public class NotificationManagerUtils {
|
||||
// 通知渠道ID(API26+ 必需,区分通知类型)
|
||||
public static final String CHANNEL_ID_FOREGROUND = "cc.winboll.studio.powerbell.channel.foreground";
|
||||
public static final String CHANNEL_ID_REMIND = "cc.winboll.studio.powerbell.channel.remind";
|
||||
public static final String CHANNEL_ID_CONFIG = "cc.winboll.studio.powerbell.channel.config"; // 新增:应用配置信息渠道
|
||||
// 通知ID(唯一标识,避免重复)
|
||||
public static final int NOTIFY_ID_FOREGROUND_SERVICE = 1001;
|
||||
public static final int NOTIFY_ID_REMIND = 1002;
|
||||
public static final int NOTIFY_ID_CONFIG = 1003; // 新增:应用配置信息通知ID
|
||||
// 低版本兼容:默认通知图标(API<21 避免显示异常)
|
||||
private static final int NOTIFICATION_DEFAULT_ICON = R.drawable.ic_launcher;
|
||||
// 通知内容兜底常量
|
||||
@@ -40,9 +42,12 @@ public class NotificationManagerUtils {
|
||||
private static final String FOREGROUND_NOTIFY_CONTENT_DEFAULT = "后台监测电池状态";
|
||||
private static final String REMIND_NOTIFY_TITLE_DEFAULT = "电池状态提醒";
|
||||
private static final String REMIND_NOTIFY_CONTENT_DEFAULT = "电池状态异常,请及时处理";
|
||||
private static final String CONFIG_NOTIFY_TITLE_DEFAULT = "应用配置更新"; // 新增:配置通知默认标题
|
||||
private static final String CONFIG_NOTIFY_CONTENT_DEFAULT = "配置信息已更新,生效中"; // 新增:配置通知默认内容
|
||||
// PendingIntent请求码
|
||||
private static final int PENDING_INTENT_REQUEST_CODE_FOREGROUND = 0;
|
||||
private static final int PENDING_INTENT_REQUEST_CODE_REMIND = 1;
|
||||
private static final int PENDING_INTENT_REQUEST_CODE_CONFIG = 2; // 新增:配置通知请求码
|
||||
|
||||
// ================================== 成员变量(私有封装,按依赖优先级排序)=================================
|
||||
// 核心上下文(应用级,避免内存泄漏)
|
||||
@@ -54,33 +59,35 @@ public class NotificationManagerUtils {
|
||||
|
||||
// ================================== 构造方法(初始化核心资源,前置校验)=================================
|
||||
public NotificationManagerUtils(Context context) {
|
||||
LogUtils.d(TAG, "构造方法执行");
|
||||
LogUtils.d(TAG, "NotificationManagerUtils: 构造方法执行 | context=" + context);
|
||||
// 前置校验:Context非空
|
||||
if (context == null) {
|
||||
LogUtils.e(TAG, "构造失败:context is null");
|
||||
LogUtils.e(TAG, "NotificationManagerUtils: 构造失败:context is null");
|
||||
return;
|
||||
}
|
||||
// 初始化核心资源
|
||||
this.mContext = context.getApplicationContext();
|
||||
this.mNotificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
LogUtils.d(TAG, "NotificationManagerUtils: 核心资源初始化完成 | mContext=" + mContext + " | mNotificationManager=" + mNotificationManager);
|
||||
// 初始化通知渠道(API26+ 必需)
|
||||
initNotificationChannels();
|
||||
LogUtils.d(TAG, "构造完成:核心资源初始化成功");
|
||||
LogUtils.d(TAG, "NotificationManagerUtils: 构造完成");
|
||||
}
|
||||
|
||||
// ================================== 核心初始化方法(通知渠道,API分级适配)=================================
|
||||
/**
|
||||
* 初始化通知渠道:前台服务渠道(无铃声+无振动)、提醒渠道(系统默认铃声+无振动)
|
||||
* 初始化通知渠道:前台服务渠道(无铃声+无振动)、提醒渠道(系统默认铃声+无振动)、配置信息渠道(低优先级无打扰)
|
||||
*/
|
||||
private void initNotificationChannels() {
|
||||
LogUtils.d(TAG, "initNotificationChannels: 执行通知渠道初始化");
|
||||
// API<26 无渠道机制,直接返回
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||
LogUtils.d(TAG, "initNotificationChannels:API<26,无需创建渠道");
|
||||
LogUtils.d(TAG, "initNotificationChannels: API<26,无需创建渠道");
|
||||
return;
|
||||
}
|
||||
// 通知服务为空,避免空指针
|
||||
if (mNotificationManager == null) {
|
||||
LogUtils.e(TAG, "initNotificationChannels失败:NotificationManager is null");
|
||||
LogUtils.e(TAG, "initNotificationChannels: 失败:NotificationManager is null");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -96,6 +103,7 @@ public class NotificationManagerUtils {
|
||||
foregroundChannel.setSound(null, null); // 强制无铃声
|
||||
foregroundChannel.setShowBadge(false);
|
||||
foregroundChannel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
|
||||
LogUtils.d(TAG, "initNotificationChannels: 前台服务渠道配置完成");
|
||||
|
||||
// 2. 电池提醒渠道(中优先级,系统默认铃声,无振动)
|
||||
NotificationChannel remindChannel = new NotificationChannel(
|
||||
@@ -109,11 +117,27 @@ public class NotificationManagerUtils {
|
||||
remindChannel.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION), Notification.AUDIO_ATTRIBUTES_DEFAULT);
|
||||
remindChannel.setShowBadge(false);
|
||||
remindChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
|
||||
LogUtils.d(TAG, "initNotificationChannels: 电池提醒渠道配置完成");
|
||||
|
||||
// 3. 应用配置信息渠道(新增:最低优先级,无铃声无振动,仅提示不打扰)
|
||||
NotificationChannel configChannel = new NotificationChannel(
|
||||
CHANNEL_ID_CONFIG,
|
||||
"应用配置信息",
|
||||
NotificationManager.IMPORTANCE_MIN
|
||||
);
|
||||
configChannel.setDescription("应用配置更新、参数变更等提示,无声音、无振动");
|
||||
configChannel.enableLights(false);
|
||||
configChannel.enableVibration(false);
|
||||
configChannel.setSound(null, null);
|
||||
configChannel.setShowBadge(false);
|
||||
configChannel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
|
||||
LogUtils.d(TAG, "initNotificationChannels: 应用配置信息渠道配置完成");
|
||||
|
||||
// 注册渠道到系统
|
||||
mNotificationManager.createNotificationChannel(foregroundChannel);
|
||||
mNotificationManager.createNotificationChannel(remindChannel);
|
||||
LogUtils.d(TAG, "initNotificationChannels成功:创建前台服务+电池提醒渠道");
|
||||
mNotificationManager.createNotificationChannel(configChannel); // 注册新增渠道
|
||||
LogUtils.d(TAG, "initNotificationChannels: 成功:创建前台服务+电池提醒+应用配置信息渠道");
|
||||
}
|
||||
|
||||
// ================================== 对外核心方法(前台服务通知:启动/更新/取消)=================================
|
||||
@@ -121,26 +145,26 @@ public class NotificationManagerUtils {
|
||||
* 启动前台服务通知(API30适配,无铃声)
|
||||
*/
|
||||
public void startForegroundServiceNotify(Service service, NotificationMessage message) {
|
||||
LogUtils.d(TAG, "startForegroundServiceNotify执行 | notifyId=" + NOTIFY_ID_FOREGROUND_SERVICE);
|
||||
LogUtils.d(TAG, "startForegroundServiceNotify: 执行 | notifyId=" + NOTIFY_ID_FOREGROUND_SERVICE + " | service=" + service + " | message=" + message);
|
||||
// 前置校验:参数非空
|
||||
if (service == null || message == null || mNotificationManager == null) {
|
||||
LogUtils.e(TAG, "startForegroundServiceNotify失败:param is null | service=" + service + " | message=" + message + " | mNotificationManager=" + mNotificationManager);
|
||||
LogUtils.e(TAG, "startForegroundServiceNotify: 失败:param is null | service=" + service + " | message=" + message + " | mNotificationManager=" + mNotificationManager);
|
||||
return;
|
||||
}
|
||||
|
||||
// 构建前台通知
|
||||
mForegroundServiceNotify = buildForegroundNotification(message);
|
||||
if (mForegroundServiceNotify == null) {
|
||||
LogUtils.e(TAG, "startForegroundServiceNotify失败:构建通知为空");
|
||||
LogUtils.e(TAG, "startForegroundServiceNotify: 失败:构建通知为空");
|
||||
return;
|
||||
}
|
||||
|
||||
// 启动前台服务(API30无FOREGROUND_SERVICE_TYPE限制,全版本通用)
|
||||
try {
|
||||
service.startForeground(NOTIFY_ID_FOREGROUND_SERVICE, mForegroundServiceNotify);
|
||||
LogUtils.d(TAG, "startForegroundServiceNotify成功");
|
||||
LogUtils.d(TAG, "startForegroundServiceNotify: 成功");
|
||||
} catch (Exception e) {
|
||||
LogUtils.e(TAG, "startForegroundServiceNotify异常", e);
|
||||
LogUtils.e(TAG, "startForegroundServiceNotify: 异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,23 +172,23 @@ public class NotificationManagerUtils {
|
||||
* 更新前台服务通知内容(复用通知ID,保持无铃声)
|
||||
*/
|
||||
public void updateForegroundServiceNotify(NotificationMessage message) {
|
||||
LogUtils.d(TAG, "updateForegroundServiceNotify执行 | notifyId=" + NOTIFY_ID_FOREGROUND_SERVICE);
|
||||
LogUtils.d(TAG, "updateForegroundServiceNotify: 执行 | notifyId=" + NOTIFY_ID_FOREGROUND_SERVICE + " | message=" + message);
|
||||
if (message == null || mNotificationManager == null) {
|
||||
LogUtils.e(TAG, "updateForegroundServiceNotify失败:param is null | message=" + message + " | mNotificationManager=" + mNotificationManager);
|
||||
LogUtils.e(TAG, "updateForegroundServiceNotify: 失败:param is null | message=" + message + " | mNotificationManager=" + mNotificationManager);
|
||||
return;
|
||||
}
|
||||
|
||||
mForegroundServiceNotify = buildForegroundNotification(message);
|
||||
if (mForegroundServiceNotify == null) {
|
||||
LogUtils.e(TAG, "updateForegroundServiceNotify失败:构建通知为空");
|
||||
LogUtils.e(TAG, "updateForegroundServiceNotify: 失败:构建通知为空");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
mNotificationManager.notify(NOTIFY_ID_FOREGROUND_SERVICE, mForegroundServiceNotify);
|
||||
LogUtils.d(TAG, "updateForegroundServiceNotify成功");
|
||||
LogUtils.d(TAG, "updateForegroundServiceNotify: 成功");
|
||||
} catch (Exception e) {
|
||||
LogUtils.e(TAG, "updateForegroundServiceNotify异常", e);
|
||||
LogUtils.e(TAG, "updateForegroundServiceNotify: 异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,10 +196,10 @@ public class NotificationManagerUtils {
|
||||
* 取消前台服务通知(Service销毁时调用)
|
||||
*/
|
||||
public void cancelForegroundServiceNotify() {
|
||||
LogUtils.d(TAG, "cancelForegroundServiceNotify执行 | notifyId=" + NOTIFY_ID_FOREGROUND_SERVICE);
|
||||
LogUtils.d(TAG, "cancelForegroundServiceNotify: 执行 | notifyId=" + NOTIFY_ID_FOREGROUND_SERVICE);
|
||||
cancelNotification(NOTIFY_ID_FOREGROUND_SERVICE);
|
||||
mForegroundServiceNotify = null; // 置空释放
|
||||
LogUtils.d(TAG, "cancelForegroundServiceNotify成功");
|
||||
LogUtils.d(TAG, "cancelForegroundServiceNotify: 成功");
|
||||
}
|
||||
|
||||
// ================================== 对外核心方法(电池提醒通知:发送)=================================
|
||||
@@ -183,23 +207,48 @@ public class NotificationManagerUtils {
|
||||
* 发送电池提醒通知(系统默认铃声,无振动)
|
||||
*/
|
||||
public void showRemindNotification(Context context, NotificationMessage message) {
|
||||
LogUtils.d(TAG, "showRemindNotification执行 | notifyId=" + NOTIFY_ID_REMIND);
|
||||
LogUtils.d(TAG, "showRemindNotification: 执行 | notifyId=" + NOTIFY_ID_REMIND + " | context=" + context + " | message=" + message);
|
||||
if (context == null || message == null || mNotificationManager == null) {
|
||||
LogUtils.e(TAG, "showRemindNotification失败:param is null | context=" + context + " | message=" + message + " | mNotificationManager=" + mNotificationManager);
|
||||
LogUtils.e(TAG, "showRemindNotification: 失败:param is null | context=" + context + " | message=" + message + " | mNotificationManager=" + mNotificationManager);
|
||||
return;
|
||||
}
|
||||
|
||||
Notification remindNotify = buildRemindNotification(context, message);
|
||||
if (remindNotify == null) {
|
||||
LogUtils.e(TAG, "showRemindNotification失败:构建通知为空");
|
||||
LogUtils.e(TAG, "showRemindNotification: 失败:构建通知为空");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
mNotificationManager.notify(NOTIFY_ID_REMIND, remindNotify);
|
||||
LogUtils.d(TAG, "showRemindNotification成功");
|
||||
LogUtils.d(TAG, "showRemindNotification: 成功");
|
||||
} catch (Exception e) {
|
||||
LogUtils.e(TAG, "showRemindNotification异常", e);
|
||||
LogUtils.e(TAG, "showRemindNotification: 异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
// ================================== 对外核心方法(应用配置信息通知:发送)=================================
|
||||
/**
|
||||
* 发送应用配置信息通知(新增:低优先级无铃声,仅提示不打扰)
|
||||
*/
|
||||
public void showConfigNotification(Context context, NotificationMessage message) {
|
||||
LogUtils.d(TAG, "showConfigNotification: 执行 | notifyId=" + NOTIFY_ID_CONFIG + " | context=" + context + " | message=" + message);
|
||||
if (context == null || message == null || mNotificationManager == null) {
|
||||
LogUtils.e(TAG, "showConfigNotification: 失败:param is null | context=" + context + " | message=" + message + " | mNotificationManager=" + mNotificationManager);
|
||||
return;
|
||||
}
|
||||
|
||||
Notification configNotify = buildConfigNotification(context, message);
|
||||
if (configNotify == null) {
|
||||
LogUtils.e(TAG, "showConfigNotification: 失败:构建通知为空");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
mNotificationManager.notify(NOTIFY_ID_CONFIG, configNotify);
|
||||
LogUtils.d(TAG, "showConfigNotification: 成功");
|
||||
} catch (Exception e) {
|
||||
LogUtils.e(TAG, "showConfigNotification: 异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,16 +257,16 @@ public class NotificationManagerUtils {
|
||||
* 取消指定ID的通知
|
||||
*/
|
||||
public void cancelNotification(int notifyId) {
|
||||
LogUtils.d(TAG, "cancelNotification执行 | notifyId=" + notifyId);
|
||||
LogUtils.d(TAG, "cancelNotification: 执行 | notifyId=" + notifyId);
|
||||
if (mNotificationManager == null) {
|
||||
LogUtils.e(TAG, "cancelNotification失败:NotificationManager is null");
|
||||
LogUtils.e(TAG, "cancelNotification: 失败:NotificationManager is null");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
mNotificationManager.cancel(notifyId);
|
||||
LogUtils.d(TAG, "cancelNotification成功 | notifyId=" + notifyId);
|
||||
LogUtils.d(TAG, "cancelNotification: 成功 | notifyId=" + notifyId);
|
||||
} catch (Exception e) {
|
||||
LogUtils.e(TAG, "cancelNotification异常 | notifyId=" + notifyId, e);
|
||||
LogUtils.e(TAG, "cancelNotification: 异常 | notifyId=" + notifyId, e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,16 +274,16 @@ public class NotificationManagerUtils {
|
||||
* 取消所有通知(兜底场景使用)
|
||||
*/
|
||||
public void cancelAllNotifications() {
|
||||
LogUtils.d(TAG, "cancelAllNotifications执行");
|
||||
LogUtils.d(TAG, "cancelAllNotifications: 执行");
|
||||
if (mNotificationManager == null) {
|
||||
LogUtils.e(TAG, "cancelAllNotifications失败:NotificationManager is null");
|
||||
LogUtils.e(TAG, "cancelAllNotifications: 失败:NotificationManager is null");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
mNotificationManager.cancelAll();
|
||||
LogUtils.d(TAG, "cancelAllNotifications成功");
|
||||
LogUtils.d(TAG, "cancelAllNotifications: 成功");
|
||||
} catch (Exception e) {
|
||||
LogUtils.e(TAG, "cancelAllNotifications异常", e);
|
||||
LogUtils.e(TAG, "cancelAllNotifications: 异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,28 +292,30 @@ public class NotificationManagerUtils {
|
||||
* 构建前台服务通知(全版本无铃声+无振动)
|
||||
*/
|
||||
private Notification buildForegroundNotification(NotificationMessage message) {
|
||||
LogUtils.d(TAG, "buildForegroundNotification执行");
|
||||
LogUtils.d(TAG, "buildForegroundNotification: 执行 | message=" + message);
|
||||
if (message == null || mContext == null) {
|
||||
LogUtils.e(TAG, "buildForegroundNotification失败:param is null | message=" + message + " | mContext=" + mContext);
|
||||
LogUtils.e(TAG, "buildForegroundNotification: 失败:param is null | message=" + message + " | mContext=" + mContext);
|
||||
return null;
|
||||
}
|
||||
|
||||
// 内容兜底
|
||||
String title = message.getTitle() != null && !message.getTitle().isEmpty() ? message.getTitle() : FOREGROUND_NOTIFY_TITLE_DEFAULT;
|
||||
String content = message.getContent() != null && !message.getContent().isEmpty() ? message.getContent() : FOREGROUND_NOTIFY_CONTENT_DEFAULT;
|
||||
LogUtils.d(TAG, "buildForegroundNotification:title=" + title + " | content=" + content);
|
||||
LogUtils.d(TAG, "buildForegroundNotification: 内容兜底完成 | title=" + title + " | content=" + content);
|
||||
|
||||
Notification.Builder builder;
|
||||
// API分级构建
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
// API26+:绑定前台渠道(渠道已配置无铃声)
|
||||
builder = new Notification.Builder(mContext, CHANNEL_ID_FOREGROUND);
|
||||
LogUtils.d(TAG, "buildForegroundNotification: 使用API26+渠道构建");
|
||||
} else {
|
||||
// API<26:直接构建,手动禁用铃声振动
|
||||
builder = new Notification.Builder(mContext);
|
||||
builder.setSound(null);
|
||||
builder.setVibrate(new long[]{0});
|
||||
builder.setDefaults(0);
|
||||
LogUtils.d(TAG, "buildForegroundNotification: 使用API<26手动配置");
|
||||
}
|
||||
|
||||
// 通用配置
|
||||
@@ -281,9 +332,12 @@ public class NotificationManagerUtils {
|
||||
builder.setLargeIcon(getAppIcon(mContext))
|
||||
.setColor(mContext.getResources().getColor(R.color.colorPrimary))
|
||||
.setPriority(Notification.PRIORITY_LOW);
|
||||
LogUtils.d(TAG, "buildForegroundNotification: 补充API21+配置");
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
Notification notification = builder.build();
|
||||
LogUtils.d(TAG, "buildForegroundNotification: 成功构建前台通知");
|
||||
return notification;
|
||||
}
|
||||
|
||||
// ================================== 内部辅助方法(通知构建:电池提醒通知)=================================
|
||||
@@ -291,28 +345,30 @@ public class NotificationManagerUtils {
|
||||
* 构建电池提醒通知(全版本系统默认铃声+无振动)
|
||||
*/
|
||||
private Notification buildRemindNotification(Context context, NotificationMessage message) {
|
||||
LogUtils.d(TAG, "buildRemindNotification执行");
|
||||
LogUtils.d(TAG, "buildRemindNotification: 执行 | context=" + context + " | message=" + message);
|
||||
if (context == null || message == null) {
|
||||
LogUtils.e(TAG, "buildRemindNotification失败:param is null | context=" + context + " | message=" + message);
|
||||
LogUtils.e(TAG, "buildRemindNotification: 失败:param is null | context=" + context + " | message=" + message);
|
||||
return null;
|
||||
}
|
||||
|
||||
// 内容兜底
|
||||
String title = message.getTitle() != null && !message.getTitle().isEmpty() ? message.getTitle() : REMIND_NOTIFY_TITLE_DEFAULT;
|
||||
String content = message.getContent() != null && !message.getContent().isEmpty() ? message.getContent() : REMIND_NOTIFY_CONTENT_DEFAULT;
|
||||
LogUtils.d(TAG, "buildRemindNotification:title=" + title + " | content=" + content);
|
||||
LogUtils.d(TAG, "buildRemindNotification: 内容兜底完成 | title=" + title + " | content=" + content);
|
||||
|
||||
Notification.Builder builder;
|
||||
// API分级构建
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
// API26+:绑定提醒渠道(渠道已配置默认铃声)
|
||||
builder = new Notification.Builder(context, CHANNEL_ID_REMIND);
|
||||
LogUtils.d(TAG, "buildRemindNotification: 使用API26+渠道构建");
|
||||
} else {
|
||||
// API<26:手动配置默认铃声,关闭振动
|
||||
builder = new Notification.Builder(context);
|
||||
builder.setSound(Settings.System.DEFAULT_NOTIFICATION_URI) // 显式默认铃声
|
||||
.setVibrate(new long[]{0})
|
||||
.setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_SOUND);
|
||||
LogUtils.d(TAG, "buildRemindNotification: 使用API<26手动配置");
|
||||
}
|
||||
|
||||
// 通用配置
|
||||
@@ -330,9 +386,65 @@ public class NotificationManagerUtils {
|
||||
builder.setLargeIcon(getAppIcon(context))
|
||||
.setColor(context.getResources().getColor(R.color.colorPrimary))
|
||||
.setPriority(Notification.PRIORITY_DEFAULT);
|
||||
LogUtils.d(TAG, "buildRemindNotification: 补充API21+配置");
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
Notification notification = builder.build();
|
||||
LogUtils.d(TAG, "buildRemindNotification: 成功构建提醒通知");
|
||||
return notification;
|
||||
}
|
||||
|
||||
// ================================== 内部辅助方法(通知构建:应用配置信息通知)=================================
|
||||
/**
|
||||
* 构建应用配置信息通知(新增:全版本无铃声+无振动,低优先级)
|
||||
*/
|
||||
private Notification buildConfigNotification(Context context, NotificationMessage message) {
|
||||
LogUtils.d(TAG, "buildConfigNotification: 执行 | context=" + context + " | message=" + message);
|
||||
if (context == null || message == null) {
|
||||
LogUtils.e(TAG, "buildConfigNotification: 失败:param is null | context=" + context + " | message=" + message);
|
||||
return null;
|
||||
}
|
||||
|
||||
// 内容兜底
|
||||
String title = message.getTitle() != null && !message.getTitle().isEmpty() ? message.getTitle() : CONFIG_NOTIFY_TITLE_DEFAULT;
|
||||
String content = message.getContent() != null && !message.getContent().isEmpty() ? message.getContent() : CONFIG_NOTIFY_CONTENT_DEFAULT;
|
||||
LogUtils.d(TAG, "buildConfigNotification: 内容兜底完成 | title=" + title + " | content=" + content);
|
||||
|
||||
Notification.Builder builder;
|
||||
// API分级构建
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
// API26+:绑定配置渠道(渠道已配置无铃声)
|
||||
builder = new Notification.Builder(context, CHANNEL_ID_CONFIG);
|
||||
LogUtils.d(TAG, "buildConfigNotification: 使用API26+渠道构建");
|
||||
} else {
|
||||
// API<26:直接构建,手动禁用铃声振动
|
||||
builder = new Notification.Builder(context);
|
||||
builder.setSound(null);
|
||||
builder.setVibrate(new long[]{0});
|
||||
builder.setDefaults(0);
|
||||
LogUtils.d(TAG, "buildConfigNotification: 使用API<26手动配置");
|
||||
}
|
||||
|
||||
// 通用配置
|
||||
builder.setSmallIcon(NOTIFICATION_DEFAULT_ICON)
|
||||
.setContentTitle(title)
|
||||
.setContentText(content)
|
||||
.setAutoCancel(true) // 点击关闭
|
||||
.setOngoing(false)
|
||||
.setWhen(System.currentTimeMillis())
|
||||
.setContentIntent(createJumpPendingIntent(context, PENDING_INTENT_REQUEST_CODE_CONFIG));
|
||||
|
||||
// API21+ 新增大图标+主题色
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
builder.setLargeIcon(getAppIcon(context))
|
||||
.setColor(context.getResources().getColor(R.color.colorPrimary))
|
||||
.setPriority(Notification.PRIORITY_MIN); // 最低优先级
|
||||
LogUtils.d(TAG, "buildConfigNotification: 补充API21+配置");
|
||||
}
|
||||
|
||||
Notification notification = builder.build();
|
||||
LogUtils.d(TAG, "buildConfigNotification: 成功构建配置信息通知");
|
||||
return notification;
|
||||
}
|
||||
|
||||
// ================================== 内部辅助方法(创建跳转PendingIntent,API30安全适配)=================================
|
||||
@@ -340,19 +452,20 @@ public class NotificationManagerUtils {
|
||||
* 创建跳转MainActivity的PendingIntent,API23+ 添加IMMUTABLE标记(避免安全异常)
|
||||
*/
|
||||
private PendingIntent createJumpPendingIntent(Context context, int requestCode) {
|
||||
LogUtils.d(TAG, "createJumpPendingIntent执行 | requestCode=" + requestCode);
|
||||
LogUtils.d(TAG, "createJumpPendingIntent: 执行 | requestCode=" + requestCode + " | context=" + context);
|
||||
Intent intent = new Intent(context, MainActivity.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
LogUtils.d(TAG, "createJumpPendingIntent: 跳转Intent配置完成");
|
||||
|
||||
// API23+ 必需添加IMMUTABLE,适配API30安全规范
|
||||
int flags = PendingIntent.FLAG_UPDATE_CURRENT;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
flags |= PendingIntent.FLAG_IMMUTABLE;
|
||||
LogUtils.d(TAG, "createJumpPendingIntent:添加FLAG_IMMUTABLE标记");
|
||||
LogUtils.d(TAG, "createJumpPendingIntent: 添加FLAG_IMMUTABLE标记(API23+)");
|
||||
}
|
||||
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(context, requestCode, intent, flags);
|
||||
LogUtils.d(TAG, "createJumpPendingIntent成功 | requestCode=" + requestCode);
|
||||
LogUtils.d(TAG, "createJumpPendingIntent: 成功 | requestCode=" + requestCode);
|
||||
return pendingIntent;
|
||||
}
|
||||
|
||||
@@ -361,33 +474,33 @@ public class NotificationManagerUtils {
|
||||
* 获取APP图标,失败返回默认图标
|
||||
*/
|
||||
private Bitmap getAppIcon(Context context) {
|
||||
LogUtils.d(TAG, "getAppIcon执行");
|
||||
LogUtils.d(TAG, "getAppIcon: 执行 | context=" + context);
|
||||
try {
|
||||
PackageInfo pkgInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
|
||||
Bitmap appIcon = BitmapFactory.decodeResource(context.getResources(), pkgInfo.applicationInfo.icon);
|
||||
LogUtils.d(TAG, "getAppIcon成功:获取应用图标");
|
||||
LogUtils.d(TAG, "getAppIcon: 成功:获取应用图标");
|
||||
return appIcon;
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
LogUtils.e(TAG, "getAppIcon异常:获取应用图标失败,使用默认图标", e);
|
||||
LogUtils.e(TAG, "getAppIcon: 异常:获取应用图标失败,使用默认图标", e);
|
||||
return BitmapFactory.decodeResource(context.getResources(), NOTIFICATION_DEFAULT_ICON);
|
||||
}
|
||||
}
|
||||
|
||||
// ================================== 对外 getter 方法(仅前台通知实例,只读)=================================
|
||||
public Notification getForegroundServiceNotify() {
|
||||
return mForegroundServiceNotify;
|
||||
}
|
||||
|
||||
// ================================== 资源释放方法(避免内存泄漏)=================================
|
||||
/**
|
||||
* 释放资源,销毁时调用
|
||||
*/
|
||||
public void release() {
|
||||
LogUtils.d(TAG, "release执行");
|
||||
LogUtils.d(TAG, "release: 执行资源释放");
|
||||
cancelForegroundServiceNotify();
|
||||
mNotificationManager = null;
|
||||
mContext = null;
|
||||
LogUtils.d(TAG, "release成功:所有资源已释放");
|
||||
LogUtils.d(TAG, "release: 成功:所有资源已释放");
|
||||
}
|
||||
|
||||
// ================================== 对外 getter 方法(仅前台通知实例,只读)=================================
|
||||
public Notification getForegroundServiceNotify() {
|
||||
return mForegroundServiceNotify;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.libappbase.ToastUtils;
|
||||
import cc.winboll.studio.powerbell.App;
|
||||
import cc.winboll.studio.powerbell.models.BackgroundBean;
|
||||
import cc.winboll.studio.powerbell.utils.BackgroundSourceUtils;
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
@@ -289,5 +290,6 @@ public class BackgroundView extends RelativeLayout {
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
adjustImageViewSize(); // 尺寸变化时重新调整
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
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 |
Binary file not shown.
|
Before Width: | Height: | Size: 100 B |
@@ -40,17 +40,17 @@
|
||||
android:layout_width="160dp"
|
||||
android:layout_height="36dp"
|
||||
android:text="Origin BG"
|
||||
android:id="@+id/activitybackgroundpictureAButton5"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_margin="5dp"/>
|
||||
android:layout_margin="5dp"
|
||||
android:id="@+id/activitybackgroundsettingsAButton1"/>
|
||||
|
||||
<cc.winboll.studio.libaes.views.AButton
|
||||
android:layout_width="160dp"
|
||||
android:layout_height="36dp"
|
||||
android:text="Received BG"
|
||||
android:id="@+id/activitybackgroundpictureAButton4"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_margin="5dp"/>
|
||||
android:layout_margin="5dp"
|
||||
android:id="@+id/activitybackgroundsettingsAButton2"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
android:text="◎"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_margin="5dp"
|
||||
android:id="@+id/activitybackgroundpictureAButton1"/>
|
||||
android:id="@+id/activitybackgroundsettingsAButton3"/>
|
||||
|
||||
<cc.winboll.studio.libaes.views.AButton
|
||||
android:layout_width="50dp"
|
||||
@@ -74,7 +74,7 @@
|
||||
android:text="☑"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_margin="5dp"
|
||||
android:id="@+id/activitybackgroundpictureAButton2"/>
|
||||
android:id="@+id/activitybackgroundsettingsAButton4"/>
|
||||
|
||||
<cc.winboll.studio.libaes.views.AButton
|
||||
android:layout_width="50dp"
|
||||
@@ -82,8 +82,7 @@
|
||||
android:text="♾"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_margin="5dp"
|
||||
android:id="@+id/activitybackgroundpictureAButton9"
|
||||
android:onClick="onNetworkBackgroundDialog"/>
|
||||
android:id="@+id/activitybackgroundsettingsAButton5"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -99,7 +98,7 @@
|
||||
android:text="[+]"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_margin="5dp"
|
||||
android:id="@+id/activitybackgroundpictureAButton3"/>
|
||||
android:id="@+id/activitybackgroundsettingsAButton6"/>
|
||||
|
||||
<cc.winboll.studio.libaes.views.AButton
|
||||
android:layout_width="50dp"
|
||||
@@ -107,7 +106,7 @@
|
||||
android:text="[+~]"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_margin="5dp"
|
||||
android:id="@+id/activitybackgroundpictureAButton6"/>
|
||||
android:id="@+id/activitybackgroundsettingsAButton7"/>
|
||||
|
||||
<cc.winboll.studio.libaes.views.AButton
|
||||
android:layout_width="50dp"
|
||||
@@ -115,7 +114,7 @@
|
||||
android:text="[◐]"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_margin="5dp"
|
||||
android:id="@+id/activitybackgroundpictureAButton7"/>
|
||||
android:id="@+id/activitybackgroundsettingsAButton8"/>
|
||||
|
||||
<cc.winboll.studio.libaes.views.AButton
|
||||
android:layout_width="50dp"
|
||||
@@ -123,8 +122,8 @@
|
||||
android:text="[©]"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_margin="5dp"
|
||||
android:id="@+id/activitybackgroundsettingsAButton1"
|
||||
android:onClick="onColorPaletteDialog"/>
|
||||
android:onClick="onColorPaletteDialog"
|
||||
android:id="@+id/activitybackgroundsettingsAButton9"/>
|
||||
|
||||
<cc.winboll.studio.libaes.views.AButton
|
||||
android:layout_width="50dp"
|
||||
@@ -132,7 +131,7 @@
|
||||
android:text="[○]"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_margin="5dp"
|
||||
android:id="@+id/activitybackgroundpictureAButton8"/>
|
||||
android:id="@+id/activitybackgroundsettingsAButton10"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
@@ -13,11 +13,20 @@
|
||||
android:id="@+id/tv_dialog_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="网络后台提示"
|
||||
android:text="网络图片资源下载"
|
||||
android:textSize="18sp"
|
||||
android:textColor="@android:color/black"
|
||||
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
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
@@ -54,15 +63,6 @@
|
||||
|
||||
</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
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -74,7 +74,7 @@
|
||||
android:id="@+id/btn_cancel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="取消"
|
||||
android:text="关闭返回"
|
||||
android:textSize="14sp"
|
||||
android:background="@android:drawable/btn_default_small"
|
||||
android:layout_marginRight="8dp"/>
|
||||
@@ -83,7 +83,7 @@
|
||||
android:id="@+id/btn_confirm"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="允许"
|
||||
android:text="使用图片"
|
||||
android:textSize="14sp"
|
||||
android:background="@android:drawable/btn_default_small"/>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user