服务自启配置持久化
This commit is contained in:
@@ -10,7 +10,7 @@ import cc.winboll.studio.powerbell.models.NotificationMessage;
|
||||
/**
|
||||
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
|
||||
* @Date 2025/12/17 13:41
|
||||
* @Describe 服务通信Handler:弱引用持有服务,避免内存泄漏,适配Java7+API30,统一处理服务消息
|
||||
* @Describe 服务通信Handler:弱引用持有服务,避免内存泄漏,通知格式优化为 (+/-)(当前电量)(充电状态)
|
||||
*/
|
||||
public class ControlCenterServiceHandler extends Handler {
|
||||
// ================================== 静态常量(置顶统一管理,清晰区分消息类型)=================================
|
||||
@@ -26,11 +26,15 @@ public class ControlCenterServiceHandler extends Handler {
|
||||
this.mwrControlCenterService = new WeakReference<>(service);
|
||||
}
|
||||
|
||||
// ================================== 核心消息处理(重写handleMessage,按类型分发)=================================
|
||||
// ================================== 核心消息处理(重写handleMessage,解析多参数消息)=================================
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
super.handleMessage(msg);
|
||||
LogUtils.d(TAG, "接收消息,what:" + msg.what + ",obj:" + (msg.obj != null ? msg.obj : "null"));
|
||||
// 解析线程传递的完整数据:obj=提醒类型(+/-),arg1=当前电量,arg2=充电状态(1=充电中,0=未充电)
|
||||
String remindType = (msg.obj != null) ? (String) msg.obj : "";
|
||||
int currentBattery = msg.arg1;
|
||||
boolean isCharging = msg.arg2 == 1;
|
||||
LogUtils.d(TAG, "接收消息,what:" + msg.what + ",类型:" + remindType + ",电量:" + currentBattery + ",充电状态:" + isCharging);
|
||||
|
||||
// 弱引用获取服务,避免持有强引用导致内存泄漏
|
||||
ControlCenterService service = mwrControlCenterService.get();
|
||||
@@ -42,7 +46,7 @@ public class ControlCenterServiceHandler extends Handler {
|
||||
// 按消息类型分发处理,避免逻辑冗余
|
||||
switch (msg.what) {
|
||||
case MSG_REMIND_TEXT:
|
||||
handleRemindMessage(service, (String) msg.obj);
|
||||
handleRemindMessage(service, remindType, currentBattery, isCharging);
|
||||
break;
|
||||
default:
|
||||
LogUtils.w(TAG, "未知消息类型,what:" + msg.what);
|
||||
@@ -50,41 +54,51 @@ public class ControlCenterServiceHandler extends Handler {
|
||||
}
|
||||
}
|
||||
|
||||
// ================================== 业务辅助方法(单独处理提醒消息,职责单一)=================================
|
||||
// ================================== 业务辅助方法(重构通知内容,格式:(+/-)(当前电量)(充电状态))=================================
|
||||
/**
|
||||
* 处理电量提醒消息,构建通知模型并调用工具类发送
|
||||
* 处理电量提醒消息,构建带电量+充电状态的通知模型
|
||||
* @param service 服务实例(非空,已前置校验)
|
||||
* @param content 消息内容(+:充电提醒,-:耗电提醒)
|
||||
* @param remindType 提醒类型(+:充电提醒,-:耗电提醒)
|
||||
* @param currentBattery 当前电量(0-100)
|
||||
* @param isCharging 充电状态(true=充电中,false=未充电)
|
||||
*/
|
||||
private void handleRemindMessage(ControlCenterService service, String content) {
|
||||
LogUtils.d(TAG, "开始处理提醒消息,内容:" + content);
|
||||
private void handleRemindMessage(ControlCenterService service, String remindType, int currentBattery, boolean isCharging) {
|
||||
LogUtils.d(TAG, "开始处理提醒消息,类型:" + remindType + ",电量:" + currentBattery + ",充电状态:" + isCharging);
|
||||
|
||||
// 校验通知工具类,避免空指针
|
||||
// 1. 前置校验:通知工具类+提醒类型+电量有效性
|
||||
if (service.getNotificationManager() == null) {
|
||||
LogUtils.e(TAG, "通知管理工具类为空,无法发送提醒");
|
||||
return;
|
||||
}
|
||||
|
||||
// 构建通知消息模型,区分充电/耗电场景
|
||||
NotificationMessage remindMsg = new NotificationMessage();
|
||||
if ("+".equals(content)) {
|
||||
remindMsg.setTitle("充电提醒");
|
||||
remindMsg.setContent("电池电量已达标,建议及时断电,保护电池寿命~");
|
||||
remindMsg.setRemindMSG("charge_remind");
|
||||
LogUtils.d(TAG, "构建充电提醒通知,标识:charge_remind");
|
||||
} else if ("-".equals(content)) {
|
||||
remindMsg.setTitle("耗电提醒");
|
||||
remindMsg.setContent("电池电量偏低,建议及时充电,避免设备关机~");
|
||||
remindMsg.setRemindMSG("usage_remind");
|
||||
LogUtils.d(TAG, "构建耗电提醒通知,标识:usage_remind");
|
||||
} else {
|
||||
LogUtils.w(TAG, "无效提醒消息内容,跳过发送:" + content);
|
||||
if (!"+".equals(remindType) && !"-".equals(remindType)) {
|
||||
LogUtils.w(TAG, "无效提醒类型,跳过发送:" + remindType);
|
||||
return;
|
||||
}
|
||||
if (currentBattery < 0 || currentBattery > 100) {
|
||||
LogUtils.w(TAG, "无效当前电量,跳过发送:" + currentBattery);
|
||||
return;
|
||||
}
|
||||
|
||||
// 调用服务工具类发送通知,复用现有逻辑
|
||||
// 2. 构建通知模型,按格式拼接内容(核心优化)
|
||||
NotificationMessage remindMsg = new NotificationMessage();
|
||||
String chargeStateDesc = isCharging ? "充电中" : "未充电"; // 充电状态文字描述
|
||||
if ("+".equals(remindType)) {
|
||||
// 充电提醒:格式 (+)(当前电量)(充电状态)
|
||||
remindMsg.setTitle("充电提醒");
|
||||
remindMsg.setContent("(+) 当前电量" + currentBattery + "%," + chargeStateDesc + ",已达标建议及时断电,保护电池寿命~");
|
||||
remindMsg.setRemindMSG("charge_remind");
|
||||
LogUtils.d(TAG, "构建充电提醒通知,内容:" + remindMsg.getContent());
|
||||
} else if ("-".equals(remindType)) {
|
||||
// 耗电提醒:格式 (-)(当前电量)(充电状态)
|
||||
remindMsg.setTitle("耗电提醒");
|
||||
remindMsg.setContent("(-) 当前电量" + currentBattery + "%," + chargeStateDesc + ",已偏低建议及时充电,避免设备关机~");
|
||||
remindMsg.setRemindMSG("usage_remind");
|
||||
LogUtils.d(TAG, "构建耗电提醒通知,内容:" + remindMsg.getContent());
|
||||
}
|
||||
|
||||
// 3. 调用服务工具类发送通知,复用现有逻辑
|
||||
service.getNotificationManager().showRemindNotification(service, remindMsg);
|
||||
LogUtils.d(TAG, "提醒通知发送完成,标题:" + remindMsg.getTitle());
|
||||
LogUtils.d(TAG, "提醒通知发送完成,标题:" + remindMsg.getTitle() + ",完整内容:" + remindMsg.getContent());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,99 +1,142 @@
|
||||
package cc.winboll.studio.powerbell.models;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen<zhangsken@qq.com>
|
||||
* @Date 2024/07/18 07:06:07
|
||||
* @Describe 服务控制参数
|
||||
*/
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.JsonReader;
|
||||
import android.util.JsonWriter;
|
||||
import cc.winboll.studio.libappbase.BaseBean;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
|
||||
// 核心修正:实现 Parcelable + Serializable 接口(适配持久化+Intent传递,API30 必备)
|
||||
import cc.winboll.studio.libappbase.BaseBean;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
|
||||
* @Date 2025/12/17 15:55
|
||||
* @Describe 服务控制参数模型:管理服务启用状态,支持序列化、Parcel传递、JSON解析
|
||||
*/
|
||||
public class ControlCenterServiceBean extends BaseBean implements Parcelable, Serializable {
|
||||
// ================================== 静态常量(置顶统一管理,避免魔法值)=================================
|
||||
private static final long serialVersionUID = 1L; // Serializable 必备,保障反序列化兼容
|
||||
private static final String TAG = "ControlCenterServiceBean";
|
||||
// JSON 字段常量,避免硬编码,减少拼写错误
|
||||
private static final String JSON_FIELD_IS_ENABLE_SERVICE = "isEnableService";
|
||||
|
||||
// 序列化版本号(Serializable 必备,避免反序列化崩溃)
|
||||
private static final long serialVersionUID = 1L;
|
||||
// ================================== 核心成员变量(私有封装,规范命名)=================================
|
||||
private boolean isEnableService = false; // 服务启用状态:true=启用,false=禁用
|
||||
|
||||
public static final String TAG = "ControlCenterServiceBean";
|
||||
|
||||
boolean isEnableService = false;
|
||||
|
||||
public ControlCenterServiceBean() {
|
||||
this.isEnableService = false;
|
||||
}
|
||||
|
||||
public ControlCenterServiceBean(boolean isEnableService) {
|
||||
this.isEnableService = isEnableService;
|
||||
}
|
||||
|
||||
public void setIsEnableService(boolean isEnableService) {
|
||||
this.isEnableService = isEnableService;
|
||||
}
|
||||
|
||||
public boolean isEnableService() {
|
||||
return isEnableService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return ControlCenterServiceBean.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
|
||||
super.writeThisToJsonWriter(jsonWriter);
|
||||
ControlCenterServiceBean bean = this;
|
||||
jsonWriter.name("isEnableService").value(bean.isEnableService());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBean readBeanFromJsonReader(JsonReader jsonReader) throws IOException {
|
||||
ControlCenterServiceBean bean = new ControlCenterServiceBean();
|
||||
jsonReader.beginObject();
|
||||
while (jsonReader.hasNext()) {
|
||||
String name = jsonReader.nextName();
|
||||
if (name.equals("isEnableService")) {
|
||||
bean.setIsEnableService(jsonReader.nextBoolean());
|
||||
} else {
|
||||
jsonReader.skipValue();
|
||||
}
|
||||
}
|
||||
// 结束 JSON 对象
|
||||
jsonReader.endObject();
|
||||
return bean;
|
||||
}
|
||||
|
||||
// ======================== 补全:Parcelable 接口实现(API30 持久化/Intent传递必备)========================
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0; // 无特殊内容描述,返回0即可
|
||||
}
|
||||
|
||||
// 序列化:将对象属性写入 Parcel
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
// boolean 类型用 byte 存储(Parcel 无直接 writeBoolean 方法,Java7 适配)
|
||||
dest.writeByte((byte) (isEnableService ? 1 : 0));
|
||||
}
|
||||
|
||||
// 反序列化:从 Parcel 读取属性,创建对象(必须是 public static final 修饰)
|
||||
// ================================== Parcelable 静态创建器(必须 public static final,适配 API30 传递)=================================
|
||||
public static final Parcelable.Creator<ControlCenterServiceBean> CREATOR = new Parcelable.Creator<ControlCenterServiceBean>() {
|
||||
@Override
|
||||
public ControlCenterServiceBean createFromParcel(Parcel source) {
|
||||
// 从 Parcel 读取 byte,转为 boolean
|
||||
LogUtils.d(TAG, "Parcelable createFromParcel: 从Parcel反序列化对象");
|
||||
// Java7 + API30 适配:Parcel 无直接 writeBoolean,用 byte 存储/读取
|
||||
boolean isEnable = source.readByte() != 0;
|
||||
return new ControlCenterServiceBean(isEnable);
|
||||
ControlCenterServiceBean bean = new ControlCenterServiceBean(isEnable);
|
||||
LogUtils.d(TAG, "Parcelable createFromParcel: 反序列化完成,isEnableService=" + isEnable);
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ControlCenterServiceBean[] newArray(int size) {
|
||||
LogUtils.d(TAG, "Parcelable newArray: 创建数组,长度=" + size);
|
||||
return new ControlCenterServiceBean[size];
|
||||
}
|
||||
};
|
||||
|
||||
// ================================== 构造方法(无参+有参,满足不同初始化场景)=================================
|
||||
/**
|
||||
* 无参构造(JSON解析、反射创建必备)
|
||||
*/
|
||||
public ControlCenterServiceBean() {
|
||||
this.isEnableService = false;
|
||||
LogUtils.d(TAG, "无参构造:初始化服务状态为禁用(false)");
|
||||
}
|
||||
|
||||
/**
|
||||
* 有参构造(指定服务启用状态)
|
||||
* @param isEnableService 服务启用状态
|
||||
*/
|
||||
public ControlCenterServiceBean(boolean isEnableService) {
|
||||
this.isEnableService = isEnableService;
|
||||
LogUtils.d(TAG, "有参构造:初始化服务状态,isEnableService=" + isEnableService);
|
||||
}
|
||||
|
||||
// ================================== Getter/Setter 方法(封装成员变量,控制访问)=================================
|
||||
public boolean isEnableService() {
|
||||
LogUtils.d(TAG, "get isEnableService: 当前状态=" + isEnableService);
|
||||
return isEnableService;
|
||||
}
|
||||
|
||||
public void setIsEnableService(boolean isEnableService) {
|
||||
LogUtils.d(TAG, "set isEnableService: 旧状态=" + this.isEnableService + ",新状态=" + isEnableService);
|
||||
this.isEnableService = isEnableService;
|
||||
}
|
||||
|
||||
// ================================== 父类 BaseBean 方法重写(核心业务逻辑)=================================
|
||||
@Override
|
||||
public String getName() {
|
||||
String className = ControlCenterServiceBean.class.getName();
|
||||
LogUtils.d(TAG, "getName: 返回类名=" + className);
|
||||
return className;
|
||||
}
|
||||
|
||||
/**
|
||||
* 序列化对象到 JSON(适配数据持久化/网络传输)
|
||||
*/
|
||||
@Override
|
||||
public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
|
||||
LogUtils.d(TAG, "writeThisToJsonWriter: 开始将对象序列化到JSON");
|
||||
super.writeThisToJsonWriter(jsonWriter);
|
||||
// 写入服务启用状态字段
|
||||
jsonWriter.name(JSON_FIELD_IS_ENABLE_SERVICE).value(this.isEnableService);
|
||||
LogUtils.d(TAG, "writeThisToJsonWriter: JSON序列化完成,字段=" + JSON_FIELD_IS_ENABLE_SERVICE + ",值=" + this.isEnableService);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 JSON 反序列化创建对象(适配数据恢复)
|
||||
*/
|
||||
@Override
|
||||
public BaseBean readBeanFromJsonReader(JsonReader jsonReader) throws IOException {
|
||||
LogUtils.d(TAG, "readBeanFromJsonReader: 开始从JSON反序列化对象");
|
||||
ControlCenterServiceBean bean = new ControlCenterServiceBean();
|
||||
jsonReader.beginObject();
|
||||
while (jsonReader.hasNext()) {
|
||||
String fieldName = jsonReader.nextName();
|
||||
if (JSON_FIELD_IS_ENABLE_SERVICE.equals(fieldName)) {
|
||||
// 读取并设置服务启用状态
|
||||
boolean isEnable = jsonReader.nextBoolean();
|
||||
bean.setIsEnableService(isEnable);
|
||||
LogUtils.d(TAG, "readBeanFromJsonReader: 读取JSON字段," + fieldName + "=" + isEnable);
|
||||
} else {
|
||||
// 跳过未知字段,避免解析异常
|
||||
jsonReader.skipValue();
|
||||
LogUtils.w(TAG, "readBeanFromJsonReader: 跳过未知JSON字段=" + fieldName);
|
||||
}
|
||||
}
|
||||
jsonReader.endObject();
|
||||
LogUtils.d(TAG, "readBeanFromJsonReader: JSON反序列化完成");
|
||||
return bean;
|
||||
}
|
||||
|
||||
// ================================== Parcelable 接口方法实现(适配 Intent 组件间传递)=================================
|
||||
@Override
|
||||
public int describeContents() {
|
||||
// 无特殊内容(如文件描述符),返回0即可(API30 标准实现)
|
||||
LogUtils.d(TAG, "describeContents: 返回内容描述符=0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 序列化对象到 Parcel(Intent 传递必备,Java7 适配)
|
||||
*/
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
LogUtils.d(TAG, "writeToParcel: 开始将对象序列化到Parcel,flags=" + flags);
|
||||
// Java7 + API30 适配:Parcel 无 writeBoolean 方法,用 byte 存储(1=true,0=false)
|
||||
dest.writeByte((byte) (this.isEnableService ? 1 : 0));
|
||||
LogUtils.d(TAG, "writeToParcel: Parcel序列化完成,isEnableService=" + this.isEnableService + "(存储为byte=" + (this.isEnableService ? 1 : 0) + ")");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -10,7 +10,7 @@ import java.lang.ref.WeakReference;
|
||||
/**
|
||||
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
|
||||
* @Date 2025/12/17 13:38
|
||||
* @Describe 提醒线程(单例模式):统一管理充电/耗电提醒逻辑,适配Java7+API30+,保障线程安全与内存安全
|
||||
* @Describe 提醒线程(单例模式):统一管理充电/耗电提醒逻辑,适配Java7+API30+,发送提醒时同步携带当前电量+充电状态
|
||||
*/
|
||||
public class RemindThread extends Thread {
|
||||
// ================================== 静态常量(置顶,统一管理魔法值)=================================
|
||||
@@ -18,7 +18,7 @@ public class RemindThread extends Thread {
|
||||
private static final long INIT_DELAY_TIME = 500L; // 初始化延迟(ms,等待服务就绪)
|
||||
private static final int MIN_SLEEP_TIME = 500; // 最小检测间隔(ms,防高频轮询)
|
||||
private static final int DEFAULT_SLEEP_TIME = 1000; // 默认检测间隔(ms)
|
||||
private static final long REMIND_INTERVAL = 30000L; // 重复提醒间隔(ms,防骚扰)
|
||||
private static final long REMIND_INTERVAL = 3000L; // 重复提醒间隔(ms,防骚扰)
|
||||
private static final int CONFIG_RETRY_MAX = 3; // 配置同步重试次数(兜底)
|
||||
|
||||
// ================================== 单例核心(线程安全,避免复用旧实例)=================================
|
||||
@@ -166,17 +166,17 @@ public class RemindThread extends Thread {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 充电提醒触发
|
||||
// 充电提醒触发(新增:携带当前电量+充电状态发送)
|
||||
if (isCharging && isEnableChargeReminder && quantityOfElectricity >= chargeReminderValue) {
|
||||
LogUtils.d(TAG, "触发充电提醒:电量" + quantityOfElectricity + "≥阈值" + chargeReminderValue);
|
||||
sendNotificationMessage("+");
|
||||
LogUtils.d(TAG, "触发充电提醒:充电中,电量" + quantityOfElectricity + "≥阈值" + chargeReminderValue);
|
||||
sendNotificationMessage("+", quantityOfElectricity, isCharging);
|
||||
lastRemindTime = currentTime;
|
||||
startRemindRecoveryTimer();
|
||||
}
|
||||
// 耗电提醒触发
|
||||
// 耗电提醒触发(新增:携带当前电量+充电状态发送)
|
||||
else if (!isCharging && isEnableUsageReminder && quantityOfElectricity <= usageReminderValue) {
|
||||
LogUtils.d(TAG, "触发耗电提醒:电量" + quantityOfElectricity + "≤阈值" + usageReminderValue);
|
||||
sendNotificationMessage("-");
|
||||
LogUtils.d(TAG, "触发耗电提醒:未充电,电量" + quantityOfElectricity + "≤阈值" + usageReminderValue);
|
||||
sendNotificationMessage("-", quantityOfElectricity, isCharging);
|
||||
lastRemindTime = currentTime;
|
||||
startRemindRecoveryTimer();
|
||||
}
|
||||
@@ -228,10 +228,13 @@ public class RemindThread extends Thread {
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送提醒消息(弱引用Handler+Message复用,防泄漏)
|
||||
* 发送提醒消息(新增:携带当前电量+充电状态,弱引用Handler+Message复用,防泄漏)
|
||||
* @param type 提醒类型(+:充电提醒,-:耗电提醒)
|
||||
* @param battery 当前电量(0-100)
|
||||
* @param isCharging 当前充电状态(true=充电中)
|
||||
*/
|
||||
private void sendNotificationMessage(String content) {
|
||||
LogUtils.d(TAG, "准备发送提醒消息:" + content);
|
||||
private void sendNotificationMessage(String type, int battery, boolean isCharging) {
|
||||
LogUtils.d(TAG, "准备发送提醒消息:类型=" + type + ",电量=" + battery + ",充电状态=" + isCharging);
|
||||
if (isExist || !isReminding) {
|
||||
LogUtils.d(TAG, "线程退出/提醒关闭,跳过发送");
|
||||
return;
|
||||
@@ -243,10 +246,14 @@ public class RemindThread extends Thread {
|
||||
return;
|
||||
}
|
||||
|
||||
Message message = Message.obtain(handler, ControlCenterServiceHandler.MSG_REMIND_TEXT, content);
|
||||
// 构建消息:what=提醒标识,obj=类型,arg1=当前电量,arg2=充电状态(0=未充电,1=充电中)
|
||||
Message message = Message.obtain(handler, ControlCenterServiceHandler.MSG_REMIND_TEXT);
|
||||
message.obj = type;
|
||||
message.arg1 = battery;
|
||||
message.arg2 = isCharging ? 1 : 0; // boolean转int(Message无boolean参数,兼容Java7)
|
||||
try {
|
||||
handler.sendMessage(message);
|
||||
LogUtils.d(TAG, "提醒消息发送成功");
|
||||
LogUtils.d(TAG, "提醒消息发送成功:类型=" + type + ",电量=" + battery + ",充电状态=" + isCharging);
|
||||
} catch (Exception e) {
|
||||
LogUtils.e(TAG, "消息发送异常", e);
|
||||
if (message != null) message.recycle();
|
||||
|
||||
Reference in New Issue
Block a user