mirror of
https://gitea.winboll.cc/ZhanGSKen/MyWinBoLL.git
synced 2026-08-14 13:37:11 +08:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f7968e55c6 | |||
| 97f42054d2 | |||
| 184ea4fd71 | |||
| 526fa6c241 | |||
| a038a2db97 | |||
| 526ca1e926 | |||
| e1428632e6 | |||
| 575664b2d6 | |||
| 3479bb0faf | |||
| 9f93489a71 | |||
| 2747b074ad |
+15
-2
@@ -21,6 +21,12 @@ android {
|
||||
// 适配MIUI12
|
||||
compileSdkVersion 30
|
||||
buildToolsVersion "30.0.3"
|
||||
|
||||
// 确保 Java 7 兼容性(已适配项目技术栈)
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_7
|
||||
targetCompatibility JavaVersion.VERSION_1_7
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
applicationId "cc.winboll.studio.powerbell"
|
||||
@@ -36,7 +42,10 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
packagingOptions {
|
||||
exclude 'META-INF/NOTICE.md'
|
||||
exclude 'META-INF/LICENSE.md'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -75,7 +84,7 @@ dependencies {
|
||||
//api 'androidx.fragment:fragment:1.1.0'
|
||||
|
||||
// WinBoLL库 nexus.winboll.cc 地址
|
||||
api 'cc.winboll.studio:libaes:15.20.18'
|
||||
api 'cc.winboll.studio:libaes:15.20.21'
|
||||
api 'cc.winboll.studio:libappbase:15.20.34'
|
||||
|
||||
// WinBoLL备用库 jitpack.io 地址
|
||||
@@ -84,4 +93,8 @@ dependencies {
|
||||
|
||||
//api fileTree(dir: 'libs', include: ['*.aar'])
|
||||
api fileTree(dir: 'libs', include: ['*.jar'])
|
||||
|
||||
// JavaMail(APPMSGMailUtils 发送邮件依赖,Android 专用版)
|
||||
implementation 'com.sun.mail:android-mail:1.6.7'
|
||||
implementation 'com.sun.mail:android-activation:1.6.7'
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#Created by .winboll/winboll_app_build.gradle
|
||||
#Sun Jul 12 10:33:40 HKT 2026
|
||||
stageCount=19
|
||||
#Sat Jul 18 05:24:20 HKT 2026
|
||||
stageCount=24
|
||||
libraryProject=
|
||||
baseVersion=15.15
|
||||
publishVersion=15.15.18
|
||||
publishVersion=15.15.23
|
||||
buildCount=0
|
||||
baseBetaVersion=15.15.19
|
||||
baseBetaVersion=15.15.24
|
||||
|
||||
Vendored
+16
@@ -60,6 +60,22 @@
|
||||
-dontwarn java.util.function.**
|
||||
|
||||
# ============================== 第三方框架专项规则 ==============================
|
||||
# JavaMail / SMTP 邮件发送(APPMSGMailUtils 依赖,防止 R8 混淆导致 SMTP 发送失败)
|
||||
-keep class javax.mail.** { *; }
|
||||
-keep class javax.mail.internet.** { *; }
|
||||
-keep class javax.activation.** { *; }
|
||||
-keep class com.sun.mail.** { *; }
|
||||
-keep class com.sun.mail.util.** { *; }
|
||||
-keep class com.sun.mail.smtp.** { *; }
|
||||
-keep class com.sun.mail.pop3.** { *; }
|
||||
-keep class com.sun.mail.imap.** { *; }
|
||||
-dontwarn javax.mail.**
|
||||
-dontwarn javax.activation.**
|
||||
-dontwarn com.sun.mail.**
|
||||
-dontwarn java.awt.**
|
||||
-dontwarn javax.naming.**
|
||||
-dontwarn javax.net.ssl.**
|
||||
|
||||
# OkHttp 4.4.1(米盟广告请求依赖,完善Lambda兼容)
|
||||
-keep class okhttp3.** { *; }
|
||||
-keep interface okhttp3.** { *; }
|
||||
|
||||
@@ -14,10 +14,16 @@ import android.widget.Toast;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import cc.winboll.studio.libaes.interfaces.IWinBoLLActivity;
|
||||
import cc.winboll.studio.libaes.views.SMTPConfigView;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.libappbase.ToastUtils;
|
||||
import cc.winboll.studio.powerbell.R;
|
||||
import cc.winboll.studio.powerbell.models.ThoughtfulServiceBean;
|
||||
import cc.winboll.studio.powerbell.utils.ChargeMailNotifyHelper;
|
||||
import cc.winboll.studio.powerbell.utils.ChargeMailNotifyFloatWindow;
|
||||
import cc.winboll.studio.powerbell.threads.RemindThread;
|
||||
import cc.winboll.studio.powerbell.services.ControlCenterService;
|
||||
import android.widget.Switch;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
@@ -40,6 +46,8 @@ public class SettingsActivity extends WinBoLLActivity implements IWinBoLLActivit
|
||||
private CheckBox cbUseageTtsBattary; // 用电TTS带电量提醒(子开关)
|
||||
private CheckBox cbChargeTtsBattary; // 充电TTS带电量提醒(子开关)
|
||||
private CheckBox cbTtsWhenNotifyBattery; // 👉 新增:通知电量时同时播放TTS
|
||||
private Switch switchChargeMailNotify; // 充电邮件通知主开关
|
||||
private SMTPConfigView smtpConfigView; // SMTP邮件配置视图
|
||||
|
||||
// ======================== 接口实现区 =========================
|
||||
@Override
|
||||
@@ -62,6 +70,8 @@ public class SettingsActivity extends WinBoLLActivity implements IWinBoLLActivit
|
||||
initToolbar();
|
||||
initTtsCheckBoxes();
|
||||
initTtsCheckBoxStatus();
|
||||
initSMTPConfigView();
|
||||
initChargeMailNotifySwitch();
|
||||
|
||||
LogUtils.d(TAG, "onCreate: 应用设置页面初始化完成");
|
||||
}
|
||||
@@ -126,6 +136,50 @@ public class SettingsActivity extends WinBoLLActivity implements IWinBoLLActivit
|
||||
LogUtils.d(TAG, "initTtsCheckBoxStatus: TTS复选框状态初始化完成");
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化充电邮件通知开关
|
||||
*/
|
||||
private void initChargeMailNotifySwitch() {
|
||||
LogUtils.d(TAG, "initChargeMailNotifySwitch: 充电邮件通知开关初始化开始");
|
||||
switchChargeMailNotify = findViewById(R.id.switchChargeMailNotify);
|
||||
boolean enabled = ChargeMailNotifyHelper.isEnabled(this);
|
||||
switchChargeMailNotify.setChecked(enabled);
|
||||
updateSMTPConfigViewEnabled(enabled);
|
||||
LogUtils.d(TAG, "initChargeMailNotifySwitch: 充电邮件通知开关初始化完成,状态=" + enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化SMTP邮件配置视图
|
||||
*/
|
||||
private void initSMTPConfigView() {
|
||||
LogUtils.d(TAG, "initSMTPConfigView: SMTP邮件配置视图初始化开始");
|
||||
smtpConfigView = findViewById(R.id.smtp_config_view);
|
||||
LogUtils.d(TAG, "initSMTPConfigView: SMTP邮件配置视图初始化完成");
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新SMTP配置视图的启用状态
|
||||
*/
|
||||
private void updateSMTPConfigViewEnabled(boolean enabled) {
|
||||
LogUtils.d(TAG, "updateSMTPConfigViewEnabled: 设置SMTPConfigView启用状态=" + enabled);
|
||||
smtpConfigView.setEnabled(enabled);
|
||||
// 递归设置子控件的启用状态
|
||||
setViewAndChildrenEnabled(smtpConfigView, enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归设置View及其所有子控件的启用状态
|
||||
*/
|
||||
private void setViewAndChildrenEnabled(View view, boolean enabled) {
|
||||
view.setEnabled(enabled);
|
||||
if (view instanceof android.view.ViewGroup) {
|
||||
android.view.ViewGroup group = (android.view.ViewGroup) view;
|
||||
for (int i = 0; i < group.getChildCount(); i++) {
|
||||
setViewAndChildrenEnabled(group.getChildAt(i), enabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ======================== 事件响应区 =========================
|
||||
/**
|
||||
* 悬浮窗权限检查入口
|
||||
@@ -201,6 +255,29 @@ public class SettingsActivity extends WinBoLLActivity implements IWinBoLLActivit
|
||||
LogUtils.d(TAG, "onEnableTtsWhenNotifyBattery: 保存完成");
|
||||
}
|
||||
|
||||
/**
|
||||
* 充电邮件通知开关点击事件
|
||||
*/
|
||||
public void onChargeMailNotifySwitchChanged(View view) {
|
||||
boolean isChecked = switchChargeMailNotify.isChecked();
|
||||
LogUtils.d(TAG, "onChargeMailNotifySwitchChanged: 充电邮件通知开关状态=" + isChecked);
|
||||
ChargeMailNotifyHelper.setEnabled(this, isChecked);
|
||||
updateSMTPConfigViewEnabled(isChecked);
|
||||
if (isChecked) {
|
||||
// 开启时重启ControlCenterService
|
||||
LogUtils.d(TAG, "onChargeMailNotifySwitchChanged: 开启充电邮件通知,重启ControlCenterService");
|
||||
stopService(new Intent(this, ControlCenterService.class));
|
||||
startService(new Intent(this, ControlCenterService.class));
|
||||
} else {
|
||||
// 关闭时停止RemindThread并关闭悬浮窗
|
||||
LogUtils.d(TAG, "onChargeMailNotifySwitchChanged: 关闭充电邮件通知,停止RemindThread");
|
||||
RemindThread.stopRemindThread();
|
||||
LogUtils.d(TAG, "onChargeMailNotifySwitchChanged: 关闭充电邮件通知悬浮窗");
|
||||
ChargeMailNotifyFloatWindow.dismissWindow();
|
||||
}
|
||||
LogUtils.d(TAG, "onChargeMailNotifySwitchChanged: 状态保存完成");
|
||||
}
|
||||
|
||||
// ======================== 工具方法区 =========================
|
||||
/**
|
||||
* 获取配置Bean实例,避免重复代码
|
||||
|
||||
+19
-1
@@ -18,6 +18,8 @@ import cc.winboll.studio.powerbell.models.NotificationMessage;
|
||||
import cc.winboll.studio.powerbell.receivers.ControlCenterServiceReceiver;
|
||||
import cc.winboll.studio.powerbell.threads.RemindThread;
|
||||
import cc.winboll.studio.powerbell.utils.NotificationManagerUtils;
|
||||
import cc.winboll.studio.powerbell.utils.ChargeMailNotifyHelper;
|
||||
import cc.winboll.studio.powerbell.utils.ChargeMailNotifyFloatWindow;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -93,9 +95,10 @@ public class ControlCenterService extends Service {
|
||||
LogUtils.d(TAG, "onDestroy() 执行:服务销毁流程启动");
|
||||
super.onDestroy();
|
||||
|
||||
// 资源释放顺序:前台服务 → 线程 → 广播接收器 → Handler → 通知 → 引用(避免内存泄漏)
|
||||
// 资源释放顺序:前台服务 → 线程 → 悬浮窗 → 广播接收器 → Handler → 通知 → 引用(避免内存泄漏)
|
||||
stopForegroundService();
|
||||
RemindThread.stopRemindThread();
|
||||
ChargeMailNotifyFloatWindow.dismissWindow();
|
||||
releaseBroadcastReceiver();
|
||||
destroyHandler();
|
||||
releaseNotificationResource();
|
||||
@@ -220,6 +223,19 @@ public class ControlCenterService extends Service {
|
||||
}
|
||||
|
||||
// ====================== 业务组件初始化与销毁(Handler/广播/线程等) ======================
|
||||
/**
|
||||
* 检查充电邮件通知功能,启用时显示悬浮窗提示
|
||||
*/
|
||||
private void checkChargeMailNotifyAndShowFloatWindow() {
|
||||
LogUtils.d(TAG, "checkChargeMailNotifyAndShowFloatWindow() 执行");
|
||||
if (ChargeMailNotifyHelper.isEnabled(this)) {
|
||||
LogUtils.d(TAG, "checkChargeMailNotifyAndShowFloatWindow() | 充电邮件通知功能已启用,显示悬浮窗");
|
||||
ChargeMailNotifyFloatWindow.getInstance(this).show();
|
||||
} else {
|
||||
LogUtils.d(TAG, "checkChargeMailNotifyAndShowFloatWindow() | 充电邮件通知功能未启用,跳过悬浮窗");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化Handler等核心业务组件
|
||||
*/
|
||||
@@ -240,6 +256,8 @@ public class ControlCenterService extends Service {
|
||||
} else {
|
||||
LogUtils.d(TAG, "initServiceBusinessLogic() | 广播接收器已存在");
|
||||
}
|
||||
// 检查充电邮件通知功能,启用时显示悬浮窗提示
|
||||
checkChargeMailNotifyAndShowFloatWindow();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
package cc.winboll.studio.powerbell.threads;
|
||||
|
||||
import android.content.Context;
|
||||
import cc.winboll.studio.libaes.utils.APPMSGMailUtils;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.powerbell.App;
|
||||
|
||||
/**
|
||||
* APPMSG 邮件通知提醒线程(单例 + 继承 Thread)
|
||||
* 功能:定时每30秒调用 APPMSGMailUtils 发送电量状态邮件给预设收件人
|
||||
* 适配:Java7 | API30
|
||||
* @Author ZhanGSKen<zhangsken@qq.com>
|
||||
* @Date 2026/07/17
|
||||
*/
|
||||
public class APPMSGMailRemindThread extends Thread {
|
||||
|
||||
public static final String TAG = "APPMSGMailRemindThread";
|
||||
|
||||
// 邮件发送间隔(毫秒)
|
||||
private static final long MAIL_SEND_INTERVAL = 10000;
|
||||
|
||||
// 单例实例
|
||||
private static APPMSGMailRemindThread sInstance;
|
||||
|
||||
// 运行标志
|
||||
private volatile boolean mIsRunning = false;
|
||||
private volatile int mBattery;
|
||||
private volatile boolean mIsCharging;
|
||||
|
||||
private Context mContext;
|
||||
|
||||
/**
|
||||
* 私有构造,单例禁用外部 new
|
||||
*/
|
||||
private APPMSGMailRemindThread(Context context) {
|
||||
this.mContext = context.getApplicationContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单例(DCL 双重校验)
|
||||
*/
|
||||
public static APPMSGMailRemindThread getInstance(Context context) {
|
||||
if (sInstance == null) {
|
||||
synchronized (APPMSGMailRemindThread.class) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new APPMSGMailRemindThread(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对外静态启动入口
|
||||
*/
|
||||
public static void start(Context context, int battery, boolean isCharging) {
|
||||
APPMSGMailRemindThread instance = getInstance(context);
|
||||
instance.mBattery = battery;
|
||||
instance.mIsCharging = isCharging;
|
||||
if (!instance.mIsRunning) {
|
||||
LogUtils.d(TAG, "start() 邮件提醒线程启动");
|
||||
instance.mIsRunning = true;
|
||||
instance.start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 对外静态停止入口
|
||||
*/
|
||||
public static void stopMail() {
|
||||
if (sInstance != null) {
|
||||
LogUtils.d(TAG, "stopMail() 邮件提醒线程停止");
|
||||
sInstance.mIsRunning = false;
|
||||
sInstance = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 线程主逻辑:定时发送邮件
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
super.run();
|
||||
LogUtils.d(TAG, "run() 邮件线程已开始循环");
|
||||
|
||||
while (mIsRunning) {
|
||||
try {
|
||||
String chargingText = mIsCharging ? "充电" : "用电";
|
||||
String subject = "PowerBell 电量状态通知";
|
||||
String content = String.format(
|
||||
"当前状态:%s,电量为百分之%d",
|
||||
chargingText, mBattery);
|
||||
String recipient = APPMSGMailUtils.getRecipient(mContext);
|
||||
|
||||
LogUtils.d(TAG, String.format("run() 发送邮件 | 收件人:%s | 内容:%s", recipient, content));
|
||||
APPMSGMailUtils.sendMail(mContext, subject, content, recipient);
|
||||
|
||||
sleep(MAIL_SEND_INTERVAL);
|
||||
} catch (InterruptedException e) {
|
||||
LogUtils.e(TAG, "邮件线程被中断", e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mIsRunning = false;
|
||||
LogUtils.d(TAG, "run() 邮件线程已退出");
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否正在运行
|
||||
*/
|
||||
public boolean isRunning() {
|
||||
return mIsRunning;
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.powerbell.App;
|
||||
import cc.winboll.studio.powerbell.handlers.ControlCenterServiceHandler;
|
||||
import cc.winboll.studio.powerbell.models.AppConfigBean;
|
||||
import cc.winboll.studio.powerbell.utils.ChargeMailNotifyHelper;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -191,6 +192,10 @@ public class RemindThread extends Thread {
|
||||
|
||||
// 启动电量通知 TTS 语音提醒线程
|
||||
TTSRemindThread.start(this.mContext, App.sQuantityOfElectricity, isCharging);
|
||||
// 启动电量通知邮件提醒线程(仅在充电邮件通知功能启用时)
|
||||
if (ChargeMailNotifyHelper.isEnabled(this.mContext)) {
|
||||
APPMSGMailRemindThread.start(this.mContext, App.sQuantityOfElectricity, isCharging);
|
||||
}
|
||||
|
||||
// 安全休眠,保留中断标记
|
||||
safeSleepInternal(sleepTime);
|
||||
@@ -283,7 +288,11 @@ public class RemindThread extends Thread {
|
||||
*/
|
||||
private void cleanThreadStateInternal() {
|
||||
LogUtils.d(TAG, String.format("cleanThreadStateInternal() 调用 | threadId=%d", getId()));
|
||||
TTSRemindThread.stopTTS();
|
||||
TTSRemindThread.stopTTS();
|
||||
// 仅在充电邮件通知功能启用时停止邮件提醒线程
|
||||
if (ChargeMailNotifyHelper.isEnabled(this.mContext)) {
|
||||
APPMSGMailRemindThread.stopMail();
|
||||
}
|
||||
isReminding = false;
|
||||
isExist = true;
|
||||
// 中断当前线程(如果存活)
|
||||
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
package cc.winboll.studio.powerbell.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.os.Build;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.powerbell.R;
|
||||
|
||||
/**
|
||||
* 充电邮件通知悬浮窗工具类(单例)
|
||||
* 功能:在服务启动时显示充电邮件通知已启用的悬浮提示
|
||||
* 适配:Java7 | API30 | 悬浮窗权限检查
|
||||
* @Author 豆包&ZhanGSKen<zhangsken@qq.com>
|
||||
* @Date 2026年07月17日
|
||||
*/
|
||||
public class ChargeMailNotifyFloatWindow {
|
||||
// ====================== 常量区 ======================
|
||||
public static final String TAG = "ChargeMailNotifyFloatWindow";
|
||||
|
||||
// ====================== 单例实例 ======================
|
||||
private static volatile ChargeMailNotifyFloatWindow sInstance;
|
||||
|
||||
// ====================== 成员变量 ======================
|
||||
private Context mContext;
|
||||
private WindowManager mWindowManager;
|
||||
private View mView;
|
||||
|
||||
// ====================== 私有构造器(单例模式) ======================
|
||||
private ChargeMailNotifyFloatWindow(Context context) {
|
||||
LogUtils.d(TAG, "ChargeMailNotifyFloatWindow() 构造器调用");
|
||||
this.mContext = context.getApplicationContext();
|
||||
this.mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
|
||||
LogUtils.d(TAG, "ChargeMailNotifyFloatWindow() 构造完成");
|
||||
}
|
||||
|
||||
// ====================== 单例获取入口(DCL双重检查锁) ======================
|
||||
public static ChargeMailNotifyFloatWindow getInstance(Context context) {
|
||||
if (sInstance == null) {
|
||||
synchronized (ChargeMailNotifyFloatWindow.class) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new ChargeMailNotifyFloatWindow(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
// ====================== 对外公开方法 ======================
|
||||
/**
|
||||
* 显示充电邮件通知悬浮窗
|
||||
*/
|
||||
public void show() {
|
||||
LogUtils.d(TAG, "show() 调用");
|
||||
|
||||
// 检查悬浮窗权限
|
||||
if (!checkOverlayPermission()) {
|
||||
LogUtils.w(TAG, "show() 悬浮窗权限未授予,跳过显示");
|
||||
return;
|
||||
}
|
||||
|
||||
// 清理已存在的悬浮窗
|
||||
dismiss();
|
||||
|
||||
try {
|
||||
// 创建Window布局参数
|
||||
WindowManager.LayoutParams params = new WindowManager.LayoutParams();
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
|
||||
} else {
|
||||
params.type = WindowManager.LayoutParams.TYPE_PHONE;
|
||||
}
|
||||
params.alpha = 0.9f;
|
||||
params.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
|
||||
params.x = 0;
|
||||
params.y = 100;
|
||||
params.format = PixelFormat.RGBA_8888;
|
||||
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
|
||||
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
|
||||
params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
||||
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
|
||||
|
||||
// 加载悬浮窗布局
|
||||
mView = View.inflate(mContext, R.layout.view_charge_mail_notify, null);
|
||||
mWindowManager.addView(mView, params);
|
||||
LogUtils.d(TAG, "show() 悬浮窗显示成功");
|
||||
} catch (Exception e) {
|
||||
LogUtils.e(TAG, "show() 悬浮窗显示异常", e);
|
||||
mView = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭悬浮窗(实例方法)
|
||||
*/
|
||||
public void dismiss() {
|
||||
LogUtils.d(TAG, "dismiss() 调用");
|
||||
|
||||
if (mWindowManager != null && mView != null) {
|
||||
try {
|
||||
mWindowManager.removeView(mView);
|
||||
LogUtils.d(TAG, "dismiss() 悬浮窗移除成功");
|
||||
} catch (Exception e) {
|
||||
LogUtils.e(TAG, "dismiss() 悬浮窗移除异常", e);
|
||||
} finally {
|
||||
mView = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭悬浮窗(静态公共方法,供外部调用)
|
||||
*/
|
||||
public static void dismissWindow() {
|
||||
LogUtils.d(TAG, "dismissWindow() 静态方法调用");
|
||||
if (sInstance != null) {
|
||||
sInstance.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
// ====================== 私有辅助方法 ======================
|
||||
/**
|
||||
* 检查悬浮窗权限
|
||||
*/
|
||||
private boolean checkOverlayPermission() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
boolean hasPermission = android.provider.Settings.canDrawOverlays(mContext);
|
||||
LogUtils.d(TAG, "checkOverlayPermission() 权限校验结果=" + hasPermission);
|
||||
return hasPermission;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package cc.winboll.studio.powerbell.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
|
||||
/**
|
||||
* 充电邮件通知功能开关管理类
|
||||
* 适配 API30,基于 Java7 开发
|
||||
* @Author 豆包&ZhanGSKen<zhangsken@qq.com>
|
||||
* @Date 2026年07月17日
|
||||
* @Describe 管理充电邮件通知功能的启用/关闭状态,使用SP持久化存储
|
||||
*/
|
||||
public class ChargeMailNotifyHelper {
|
||||
// ======================== 静态常量区 =========================
|
||||
private static final String TAG = "ChargeMailNotifyHelper";
|
||||
private static final String SP_NAME = "charge_mail_notify_config";
|
||||
private static final String SP_KEY_ENABLED = "charge_mail_notify_enabled";
|
||||
private static final boolean DEFAULT_ENABLED = false;
|
||||
|
||||
// ======================== 静态方法区 =========================
|
||||
/**
|
||||
* 获取充电邮件通知功能是否启用
|
||||
* @param context 上下文
|
||||
* @return true=已启用,false=已关闭
|
||||
*/
|
||||
public static boolean isEnabled(Context context) {
|
||||
SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
|
||||
boolean enabled = sp.getBoolean(SP_KEY_ENABLED, DEFAULT_ENABLED);
|
||||
LogUtils.d(TAG, "isEnabled: " + enabled);
|
||||
return enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置充电邮件通知功能启用/关闭状态
|
||||
* @param context 上下文
|
||||
* @param enabled true=启用,false=关闭
|
||||
*/
|
||||
public static void setEnabled(Context context, boolean enabled) {
|
||||
SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
|
||||
sp.edit().putBoolean(SP_KEY_ENABLED, enabled).apply();
|
||||
LogUtils.d(TAG, "setEnabled: " + enabled);
|
||||
}
|
||||
}
|
||||
@@ -153,6 +153,51 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:orientation="vertical"
|
||||
android:background="@drawable/bg_frame"
|
||||
android:padding="10dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:padding="5dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="充电邮件通知服务"
|
||||
android:textSize="16sp"/>
|
||||
|
||||
<Switch
|
||||
android:id="@+id/switchChargeMailNotify"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:onClick="onChargeMailNotifySwitchChanged"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="开启后,充电状态变化时将通过邮件发送通知"
|
||||
android:textSize="12sp"
|
||||
android:paddingLeft="5dp"
|
||||
android:paddingBottom="5dp"/>
|
||||
|
||||
<cc.winboll.studio.libaes.views.SMTPConfigView
|
||||
android:id="@+id/smtp_config_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="300dp"
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_frame_white"
|
||||
android:gravity="center_vertical"
|
||||
android:padding="10dp"
|
||||
android:id="@+id/viewChargeMailNotifyLinearLayout1">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:src="@drawable/ic_email"
|
||||
android:layout_marginRight="8dp"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="充电邮件通知服务已启用"
|
||||
android:textColor="#FF000000"
|
||||
android:textSize="14sp"/>
|
||||
|
||||
</LinearLayout>
|
||||
Reference in New Issue
Block a user