Compare commits

...

16 Commits

Author SHA1 Message Date
4b196acfce <powerbell>APK 15.15.8 release Publish. 2026-02-04 11:07:22 +08:00
cf857c1359 尝试叫豆包修复每天10半左右会无端端调用TTS服务的问题。 2026-02-04 11:04:13 +08:00
81b758ddc5 <powerbell>APK 15.15.7 release Publish. 2026-01-24 20:41:05 +08:00
64a53058cc 增加对签名证书修改后的证书识别能力。 2026-01-24 20:38:52 +08:00
aae17b6cd2 <powerbell>APK 15.15.6 release Publish. 2026-01-24 12:44:08 +08:00
d6637e1c17 更新基础类库,新类库应用验证模块有改进。 2026-01-24 12:41:51 +08:00
6d425cab5c <powerbell>APK 15.15.5 release Publish. 2026-01-23 03:18:09 +08:00
ab566f76ff 添加应用签名联网校验模块。 2026-01-23 03:15:06 +08:00
cd04458c62 <powerbell>APK 15.15.4 release Publish. 2026-01-20 21:21:19 +08:00
6b46180da7 应用指纹校验对话框显示优化。 2026-01-20 21:19:53 +08:00
af8b57b735 <powerbell>APK 15.15.3 release Publish. 2026-01-20 21:00:50 +08:00
21c02db577 更新基础类库,添加应用签名校验。 2026-01-20 20:59:01 +08:00
49a35829d2 <powerbell>APK 15.15.2 release Publish. 2026-01-19 20:40:18 +08:00
8229ab099a 更新应用设置窗口的TTS服务选项卡的处理逻辑。 2026-01-19 20:38:46 +08:00
45400314af <powerbell>APK 15.15.1 release Publish. 2026-01-19 20:04:16 +08:00
f53113d0df TTS贴心服务加入当前电量语音提醒功能。 2026-01-19 20:01:28 +08:00
7 changed files with 505 additions and 297 deletions

View File

@@ -81,7 +81,7 @@ dependencies {
// WinBoLL库 nexus.winboll.cc 地址
api 'cc.winboll.studio:libaes:15.15.2'
api 'cc.winboll.studio:libappbase:15.15.4'
api 'cc.winboll.studio:libappbase:15.15.11'
// WinBoLL备用库 jitpack.io 地址
//api 'com.github.ZhanGSKen:AES:aes-v15.15.2'

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Tue Jan 13 11:47:03 HKT 2026
stageCount=1
#Wed Feb 04 11:07:22 HKT 2026
stageCount=9
libraryProject=
baseVersion=15.15
publishVersion=15.15.0
publishVersion=15.15.8
buildCount=0
baseBetaVersion=15.15.1
baseBetaVersion=15.15.9

View File

@@ -23,20 +23,24 @@ import java.lang.reflect.Field;
/**
* 应用设置窗口,提供应用配置项的统一入口
* 适配 API30基于 Java7 开发
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
* @Date 2025/11/27 14:26
* @Describe 应用设置窗口
* @Author 豆包&ZhanGSKen<zhangsken@qq.com>
* @Date 202511271426分00秒
* @LastEditTime 2026年01月19日22时18分00秒
* @Describe 应用设置窗口(主开关联动子开关启用/禁用,主开关关闭则子开关禁用并取消勾选)
*/
public class SettingsActivity extends WinBoLLActivity implements IWinBoLLActivity {
// ======================== 静态常量 =========================
// ======================== 静态常量 =========================
public static final String TAG = "SettingsActivity";
// 权限请求常量(为后续读取媒体图片权限预留)
private static final int REQUEST_READ_MEDIA_IMAGES = 1001;
// ======================== 成员变量 =========================
private Toolbar mToolbar; // 顶部工具栏
// ======================== 成员属性区 =========================
private Toolbar mToolbar;
private CheckBox cbUsePowerTts; // 用电TTS主开关
private CheckBox cbChargeTts; // 充电TTS主开关
private CheckBox cbUseageTtsBattary; // 用电TTS带电量提醒子开关
private CheckBox cbChargeTtsBattary; // 充电TTS带电量提醒子开关
// ======================== 接口实现方法 =========================
// ======================== 接口实现 =========================
@Override
public Activity getActivity() {
return this;
@@ -47,96 +51,191 @@ public class SettingsActivity extends WinBoLLActivity implements IWinBoLLActivit
return TAG;
}
// ======================== 生命周期方法 =========================
// ======================== 生命周期 =========================
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
LogUtils.d(TAG, "onCreate】SettingsActivity 初始化开始");
LogUtils.d(TAG, "onCreate: 应用设置页面初始化开始");
// 初始化工具栏
initToolbar();
ThoughtfulServiceBean thoughtfulServiceBean = ThoughtfulServiceBean.loadBean(this, ThoughtfulServiceBean.class);
if (thoughtfulServiceBean == null) {
thoughtfulServiceBean = new ThoughtfulServiceBean();
}
((CheckBox)findViewById(R.id.activitysettingsCheckBox1)).setChecked(thoughtfulServiceBean.isEnableUsePowerTts());
((CheckBox)findViewById(R.id.activitysettingsCheckBox2)).setChecked(thoughtfulServiceBean.isEnableChargeTts());
initTtsCheckBoxes();
initTtsCheckBoxStatus();
LogUtils.d(TAG, "onCreate】SettingsActivity 初始化完成");
LogUtils.d(TAG, "onCreate: 应用设置页面初始化完成");
}
// ======================== UI初始化方法 =========================
// ======================== UI初始化 =========================
/**
* 初始化顶部工具栏,设置导航返回与样式
* 初始化顶部工具栏
*/
private void initToolbar() {
LogUtils.d(TAG, "initToolbar: 工具栏初始化开始");
mToolbar = findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
// 设置工具栏副标题与标题样式
mToolbar.setSubtitle(getTag());
mToolbar.setTitleTextAppearance(this, R.style.Toolbar_TitleText);
// 显示返回按钮
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// 绑定导航点击事件
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LogUtils.d(TAG, "【导航栏】点击返回");
LogUtils.d(TAG, "initToolbar-navigationOnClick: 点击导航返回按钮");
finish();
}
});
LogUtils.d(TAG, "initToolbar工具栏初始化完成");
LogUtils.d(TAG, "initToolbar: 工具栏初始化完成");
}
public void onCheckTTSDrawOverlaysPermission(View view) {
canDrawOverlays();
}
/**
* 绑定TTS相关复选框控件
*/
private void initTtsCheckBoxes() {
LogUtils.d(TAG, "initTtsCheckBoxes: TTS复选框绑定开始");
cbUsePowerTts = findViewById(R.id.activitysettingsCheckBox1);
cbChargeTts = findViewById(R.id.activitysettingsCheckBox2);
cbUseageTtsBattary = findViewById(R.id.activitysettingsCheckBox3);
cbChargeTtsBattary = findViewById(R.id.activitysettingsCheckBox4);
LogUtils.d(TAG, "initTtsCheckBoxes: TTS复选框绑定完成");
}
public void onEnableChargeTts(View view) {
ThoughtfulServiceBean thoughtfulServiceBean = ThoughtfulServiceBean.loadBean(this, ThoughtfulServiceBean.class);
if (thoughtfulServiceBean == null) {
thoughtfulServiceBean = new ThoughtfulServiceBean();
}
thoughtfulServiceBean.setIsEnableChargeTts(((CheckBox)view).isChecked());
ThoughtfulServiceBean.saveBean(this, thoughtfulServiceBean);
}
/**
* 初始化TTS复选框初始状态
*/
private void initTtsCheckBoxStatus() {
LogUtils.d(TAG, "initTtsCheckBoxStatus: TTS复选框状态初始化开始");
ThoughtfulServiceBean bean = ThoughtfulServiceBean.loadBean(this, ThoughtfulServiceBean.class);
if (bean == null) {
LogUtils.d(TAG, "initTtsCheckBoxStatus: 未读取到配置Bean创建新实例");
bean = new ThoughtfulServiceBean();
}
public void onEnableUsePowerTts(View view) {
ThoughtfulServiceBean thoughtfulServiceBean = ThoughtfulServiceBean.loadBean(this, ThoughtfulServiceBean.class);
if (thoughtfulServiceBean == null) {
thoughtfulServiceBean = new ThoughtfulServiceBean();
}
thoughtfulServiceBean.setIsEnableUsePowerTts(((CheckBox)view).isChecked());
ThoughtfulServiceBean.saveBean(this, thoughtfulServiceBean);
}
boolean useMainOpen = bean.isEnableUsePowerTts();
boolean chargeMainOpen = bean.isEnableChargeTts();
cbUsePowerTts.setChecked(useMainOpen);
cbChargeTts.setChecked(chargeMainOpen);
cbUseageTtsBattary.setChecked(bean.isEnableUseageTtsWithBattary());
cbChargeTtsBattary.setChecked(bean.isEnableChargeTtsWithBattary());
cbUseageTtsBattary.setEnabled(useMainOpen);
cbChargeTtsBattary.setEnabled(chargeMainOpen);
/**
LogUtils.d(TAG, "initTtsCheckBoxStatus: 主开关状态-用电TTS" + useMainOpen + " 充电TTS" + chargeMainOpen);
LogUtils.d(TAG, "initTtsCheckBoxStatus: TTS复选框状态初始化完成");
}
// ======================== 事件响应区 =========================
/**
* 悬浮窗权限检查入口
*/
public void onCheckTTSDrawOverlaysPermission(View view) {
LogUtils.d(TAG, "onCheckTTSDrawOverlaysPermission: 触发悬浮窗权限检查");
canDrawOverlays();
}
/**
* 用电TTS主开关点击事件
*/
public void onEnableUsePowerTts(View view) {
boolean isChecked = cbUsePowerTts.isChecked();
LogUtils.d(TAG, "onEnableUsePowerTts: 用电TTS主开关点击切换后状态=" + isChecked);
cbUsePowerTts.setChecked(isChecked);
// 主开关联动子开关
cbUseageTtsBattary.setEnabled(isChecked);
// if (!isChecked) {
// cbUseageTtsBattary.setChecked(false);
// }
// 保存配置
ThoughtfulServiceBean bean = getThoughtfulServiceBean();
bean.setIsEnableUsePowerTts(isChecked);
ThoughtfulServiceBean.saveBean(this, bean);
LogUtils.d(TAG, "onEnableUsePowerTts: 用电TTS状态保存完成");
}
/**
* 充电TTS主开关点击事件
*/
public void onEnableChargeTts(View view) {
boolean isChecked = cbChargeTts.isChecked();
LogUtils.d(TAG, "onEnableChargeTts: 充电TTS主开关点击切换后状态=" + isChecked);
cbChargeTts.setChecked(isChecked);
// 主开关联动子开关
cbChargeTtsBattary.setEnabled(isChecked);
// if (!isChecked) {
// cbChargeTtsBattary.setChecked(false);
// }
// 保存配置
ThoughtfulServiceBean bean = getThoughtfulServiceBean();
bean.setIsEnableChargeTts(isChecked);
ThoughtfulServiceBean.saveBean(this, bean);
LogUtils.d(TAG, "onEnableChargeTts: 充电TTS状态保存完成");
}
/**
* 用电TTS带电量提醒子开关点击事件
*/
public void onEnableUseageTtsWithBattary(View view) {
boolean isChecked = cbUseageTtsBattary.isChecked();
LogUtils.d(TAG, "onEnableUseageTtsWithBattary: 用电TTS电量提醒开关点击切换后状态=" + isChecked);
cbUseageTtsBattary.setChecked(isChecked);
ThoughtfulServiceBean bean = getThoughtfulServiceBean();
bean.setIsEnableUseageTtsWithBattary(isChecked);
ThoughtfulServiceBean.saveBean(this, bean);
LogUtils.d(TAG, "onEnableUseageTtsWithBattary: 用电TTS电量提醒状态保存完成");
}
/**
* 充电TTS带电量提醒子开关点击事件
*/
public void onEnableChargeTtsWithBattary(View view) {
boolean isChecked = cbChargeTtsBattary.isChecked();
LogUtils.d(TAG, "onEnableChargeTtsWithBattary: 充电TTS电量提醒开关点击切换后状态=" + isChecked);
cbChargeTtsBattary.setChecked(isChecked);
ThoughtfulServiceBean bean = getThoughtfulServiceBean();
bean.setIsEnableChargeTtsWithBattary(isChecked);
ThoughtfulServiceBean.saveBean(this, bean);
LogUtils.d(TAG, "onEnableChargeTtsWithBattary: 充电TTS电量提醒状态保存完成");
}
// ======================== 工具方法区 =========================
/**
* 获取配置Bean实例避免重复代码
*/
private ThoughtfulServiceBean getThoughtfulServiceBean() {
LogUtils.d(TAG, "getThoughtfulServiceBean: 获取配置Bean");
ThoughtfulServiceBean bean = ThoughtfulServiceBean.loadBean(this, ThoughtfulServiceBean.class);
if (bean == null) {
LogUtils.d(TAG, "getThoughtfulServiceBean: 配置Bean为空创建新实例");
bean = new ThoughtfulServiceBean();
}
return bean;
}
/**
* 悬浮窗权限检查与请求
*/
void canDrawOverlays() {
LogUtils.d(TAG, "onCanDrawOverlays: 检查悬浮窗权限");
// API6.0+校验权限
void canDrawOverlays() {
LogUtils.d(TAG, "canDrawOverlays: 悬浮窗权限检查开始");
if (Build.VERSION.SDK_INT >= 23 && !Settings.canDrawOverlays(this)) {
LogUtils.d(TAG, "onCanDrawOverlays: 未开启悬浮窗权限,发起请求");
LogUtils.d(TAG, "canDrawOverlays: 未开启悬浮窗权限,发起请求");
showDrawOverlayRequestDialog();
} else {
LogUtils.d(TAG, "canDrawOverlays: 悬浮窗权限已开启");
ToastUtils.show("悬浮窗权限已开启");
}
}
/**
* 显示悬浮窗权限请求对话框
*/
private void showDrawOverlayRequestDialog() {
LogUtils.d(TAG, "showDrawOverlayRequestDialog: 显示悬浮窗权限请求弹窗");
AlertDialog dialog = new AlertDialog.Builder(this)
.setTitle("权限请求")
.setMessage("为保证通话监听功能正常,需开启悬浮窗权限")
.setPositiveButton("去设置", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
LogUtils.d(TAG, "showDrawOverlayRequestDialog-去设置: 点击跳转权限页面");
dialog.dismiss();
jumpToDrawOverlaySettings();
}
@@ -144,12 +243,12 @@ public class SettingsActivity extends WinBoLLActivity implements IWinBoLLActivit
.setNegativeButton("稍后", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
LogUtils.d(TAG, "showDrawOverlayRequestDialog-稍后: 点击取消请求");
dialog.dismiss();
}
})
.create();
// 解决对话框焦点问题
if (dialog.getWindow() != null) {
dialog.getWindow().setFlags(
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
@@ -162,23 +261,21 @@ public class SettingsActivity extends WinBoLLActivity implements IWinBoLLActivit
* 跳转悬浮窗权限设置页面(反射适配低版本)
*/
private void jumpToDrawOverlaySettings() {
LogUtils.d(TAG, "jumpToDrawOverlaySettings: 跳转悬浮窗权限设置");
LogUtils.d(TAG, "jumpToDrawOverlaySettings: 跳转悬浮窗权限设置页面");
try {
// 反射获取设置页面Action避免高版本API依赖
Class<?> settingsClazz = Settings.class;
Field actionField = settingsClazz.getDeclaredField("ACTION_MANAGE_OVERLAY_PERMISSION");
String action = (String) actionField.get(null);
// 跳转当前应用权限设置页
Intent intent = new Intent(action);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivity(intent);
LogUtils.d(TAG, "jumpToDrawOverlaySettings: 跳转权限页面意图已发送");
} catch (Exception e) {
LogUtils.e(TAG, "jumpToDrawOverlaySettings: 跳转权限设置失败", e);
Toast.makeText(this, "请手动在设置中开启悬浮窗权限", Toast.LENGTH_LONG).show();
}
}
}

View File

@@ -24,10 +24,15 @@ public class ThoughtfulServiceBean extends BaseBean implements Parcelable, Seria
// JSON序列化字段常量 杜绝硬编码
public static final String JSON_FIELD_IS_ENABLE_CHARGE_TTS = "isEnableChargeTts";
public static final String JSON_FIELD_IS_ENABLE_USE_POWER_TTS = "isEnableUsePowerTts";
// 新增字段JSON常量
public static final String JSON_FIELD_IS_ENABLE_USAGE_TTS_WITH_BATTERY = "isEnableUseageTtsWithBattary";
public static final String JSON_FIELD_IS_ENABLE_CHARGE_TTS_WITH_BATTERY = "isEnableChargeTtsWithBattary";
// ====================== 核心成员变量 - 私有封装 ======================
private boolean isEnableChargeTts = false; // 是否启用 充电TTS贴心语音服务
private boolean isEnableUsePowerTts = false; // 是否启用 用电TTS贴心语音服务
private boolean isEnableUseageTtsWithBattary = false; // 用电TTS加入电量提醒
private boolean isEnableChargeTtsWithBattary = false;// 充电TTS加入电量提醒
// ====================== Parcelable 静态创建器 (API30标准写法 必须public static final) ======================
public static final Creator<ThoughtfulServiceBean> CREATOR = new Creator<ThoughtfulServiceBean>() {
@@ -55,11 +60,17 @@ public class ThoughtfulServiceBean extends BaseBean implements Parcelable, Seria
* 全参构造 - 手动配置所有服务状态
* @param isEnableChargeTts 充电TTS服务开关
* @param isEnableUsePowerTts 用电TTS服务开关
* @param isEnableUseageTtsWithBattary 用电TTS加电量提醒开关
* @param isEnableChargeTtsWithBattary 充电TTS加电量提醒开关
*/
public ThoughtfulServiceBean(boolean isEnableChargeTts, boolean isEnableUsePowerTts) {
public ThoughtfulServiceBean(boolean isEnableChargeTts, boolean isEnableUsePowerTts,
boolean isEnableUseageTtsWithBattary, boolean isEnableChargeTtsWithBattary) {
this.isEnableChargeTts = isEnableChargeTts;
this.isEnableUsePowerTts = isEnableUsePowerTts;
LogUtils.d(TAG, "ThoughtfulServiceBean: 全参构造 | isEnableChargeTts=" + isEnableChargeTts + " | isEnableUsePowerTts=" + isEnableUsePowerTts);
this.isEnableUseageTtsWithBattary = isEnableUseageTtsWithBattary;
this.isEnableChargeTtsWithBattary = isEnableChargeTtsWithBattary;
LogUtils.d(TAG, "ThoughtfulServiceBean: 全参构造 | 充电TTS=" + isEnableChargeTts + " | 用电TTS=" + isEnableUsePowerTts
+ " | 用电TTS加电量=" + isEnableUseageTtsWithBattary + " | 充电TTS加电量=" + isEnableChargeTtsWithBattary);
}
/**
@@ -68,7 +79,11 @@ public class ThoughtfulServiceBean extends BaseBean implements Parcelable, Seria
private ThoughtfulServiceBean(Parcel in) {
this.isEnableChargeTts = in.readByte() != 0;
this.isEnableUsePowerTts = in.readByte() != 0;
LogUtils.d(TAG, "ThoughtfulServiceBean: Parcel构造解析完成 | isEnableChargeTts=" + isEnableChargeTts + " | isEnableUsePowerTts=" + isEnableUsePowerTts);
// 新增字段反序列化
this.isEnableUseageTtsWithBattary = in.readByte() != 0;
this.isEnableChargeTtsWithBattary = in.readByte() != 0;
LogUtils.d(TAG, "ThoughtfulServiceBean: Parcel构造解析完成 | 充电TTS=" + isEnableChargeTts + " | 用电TTS=" + isEnableUsePowerTts
+ " | 用电TTS加电量=" + isEnableUseageTtsWithBattary + " | 充电TTS加电量=" + isEnableChargeTtsWithBattary);
}
// ====================== Getter/Setter 方法区 (封装成员变量 统一访问) ======================
@@ -90,6 +105,26 @@ public class ThoughtfulServiceBean extends BaseBean implements Parcelable, Seria
this.isEnableUsePowerTts = isEnableUsePowerTts;
}
// 新增 用电TTS加入电量提醒 Getter/Setter
public boolean isEnableUseageTtsWithBattary() {
return isEnableUseageTtsWithBattary;
}
public void setIsEnableUseageTtsWithBattary(boolean isEnableUseageTtsWithBattary) {
LogUtils.d(TAG, "setIsEnableUseageTtsWithBattary: 旧值=" + this.isEnableUseageTtsWithBattary + " 新值=" + isEnableUseageTtsWithBattary);
this.isEnableUseageTtsWithBattary = isEnableUseageTtsWithBattary;
}
// 新增 充电TTS加入电量提醒 Getter/Setter
public boolean isEnableChargeTtsWithBattary() {
return isEnableChargeTtsWithBattary;
}
public void setIsEnableChargeTtsWithBattary(boolean isEnableChargeTtsWithBattary) {
LogUtils.d(TAG, "setIsEnableChargeTtsWithBattary: 旧值=" + this.isEnableChargeTtsWithBattary + " 新值=" + isEnableChargeTtsWithBattary);
this.isEnableChargeTtsWithBattary = isEnableChargeTtsWithBattary;
}
// ====================== 重写父类 BaseBean 核心方法 (JSON序列化/反序列化 业务核心) ======================
@Override
public String getName() {
@@ -106,6 +141,9 @@ public class ThoughtfulServiceBean extends BaseBean implements Parcelable, Seria
super.writeThisToJsonWriter(jsonWriter);
jsonWriter.name(JSON_FIELD_IS_ENABLE_CHARGE_TTS).value(this.isEnableChargeTts);
jsonWriter.name(JSON_FIELD_IS_ENABLE_USE_POWER_TTS).value(this.isEnableUsePowerTts);
// 新增字段JSON序列化
jsonWriter.name(JSON_FIELD_IS_ENABLE_USAGE_TTS_WITH_BATTERY).value(this.isEnableUseageTtsWithBattary);
jsonWriter.name(JSON_FIELD_IS_ENABLE_CHARGE_TTS_WITH_BATTERY).value(this.isEnableChargeTtsWithBattary);
LogUtils.d(TAG, "writeThisToJsonWriter: JSON序列化完成所有TTS服务状态已写入");
}
@@ -124,6 +162,13 @@ public class ThoughtfulServiceBean extends BaseBean implements Parcelable, Seria
break;
case JSON_FIELD_IS_ENABLE_USE_POWER_TTS:
bean.setIsEnableUsePowerTts(jsonReader.nextBoolean());
break;
// 新增字段反序列化
case JSON_FIELD_IS_ENABLE_USAGE_TTS_WITH_BATTERY:
bean.setIsEnableUseageTtsWithBattary(jsonReader.nextBoolean());
break;
case JSON_FIELD_IS_ENABLE_CHARGE_TTS_WITH_BATTERY:
bean.setIsEnableChargeTtsWithBattary(jsonReader.nextBoolean());
break;
default:
jsonReader.skipValue();
@@ -149,6 +194,9 @@ public class ThoughtfulServiceBean extends BaseBean implements Parcelable, Seria
public void writeToParcel(Parcel dest, int flags) {
dest.writeByte((byte) (isEnableChargeTts ? 1 : 0));
dest.writeByte((byte) (isEnableUsePowerTts ? 1 : 0));
// 新增字段Parcel序列化
dest.writeByte((byte) (isEnableUseageTtsWithBattary ? 1 : 0));
dest.writeByte((byte) (isEnableChargeTtsWithBattary ? 1 : 0));
LogUtils.d(TAG, "writeToParcel: Parcel序列化完成所有TTS服务状态已写入");
}

View File

@@ -24,56 +24,55 @@ import cc.winboll.studio.powerbell.services.ThoughtfulService;
* @Describe 统一处理系统与应用内广播,同步电池状态与配置,保障多线程数据一致性
*/
public class ControlCenterServiceReceiver extends BroadcastReceiver {
// ====================== 静态常量区(置顶归类,消除魔法值) ======================
// ====================== 静态常量区 ======================
public static final String TAG = "ControlCenterServiceReceiver";
// 广播Action常量带包名前缀防冲突
public static final String ACTION_UPDATE_FOREGROUND_NOTIFICATION = "cc.winboll.studio.powerbell.action.ACTION_UPDATE_FOREGROUND_NOTIFICATION";
public static final String ACTION_APPCONFIG_CHANGED = "cc.winboll.studio.powerbell.action.ACTION_APPCONFIG_CHANGED";
public static final String EXTRA_APP_CONFIG_BEAN = "extra_app_config_bean";
// 广播优先级与电量范围常量
private static final int BROADCAST_PRIORITY = IntentFilter.SYSTEM_HIGH_PRIORITY - 10;
private static final int BATTERY_LEVEL_MIN = 0;
private static final int BATTERY_LEVEL_MAX = 100;
private static final int INVALID_BATTERY = -1; // 无效电量标识
private static final int INVALID_BATTERY = -1;
// ====================== 静态状态标记volatile保证多线程可见性 ======================
private static volatile int sLastBatteryLevel = INVALID_BATTERY; // 上次电量(多线程可见)
private static volatile boolean sIsCharging = false; // 上次充电状态(多线程可见)
// ====================== 静态状态(防抖动 + 防重复播报 ======================
private static volatile int sLastBatteryLevel = INVALID_BATTERY;
private static volatile boolean sIsCharging = false;
// ====================== 成员变量区(弱引用防泄漏,按功能分层) ======================
// 【新增】防重复触发3秒内只允许一次播报关键修复
private static final long MIN_TRIGGER_INTERVAL = 3000;
private static long sLastTriggerTime = 0;
// ====================== 成员变量 ======================
private WeakReference<ControlCenterService> mwrControlCenterService;
private boolean isRegistered = false; // 标记广播注册状态,避免冗余操作
private boolean isRegistered = false;
// ====================== 构造方法(初始化弱引用,避免服务强引用泄漏) ======================
// ====================== 构造 ======================
public ControlCenterServiceReceiver(ControlCenterService service) {
LogUtils.d(TAG, String.format("ControlCenterServiceReceiver() 构造 | 服务实例%s",
LogUtils.d(TAG, String.format("ControlCenterServiceReceiver() 构造 | 服务:%s",
service != null ? service.getClass().getSimpleName() : "null"));
this.mwrControlCenterService = new WeakReference<ControlCenterService>(service);
this.mwrControlCenterService = new WeakReference<>(service);
}
// ====================== 广播核心接收逻辑入口方法分Action分发处理 ======================
// ====================== 广播入口 ======================
@Override
public void onReceive(Context context, Intent intent) {
String action = intent != null ? intent.getAction() : "null";
LogUtils.d(TAG, String.format("onReceive() 执行 | 接收广播 Action%s", action));
LogUtils.d(TAG, String.format("onReceive() | Action=%s", action));
// 基础参数校验
if (context == null || intent == null || action == null) {
LogUtils.e(TAG, "onReceive() 终止 | 参数无效context=" + context + " | intent=" + intent + "");
LogUtils.e(TAG, "onReceive() 终止参数无效");
return;
}
// 弱引用获取服务,双重校验服务有效性
ControlCenterService service = mwrControlCenterService != null ? mwrControlCenterService.get() : null;
if (service == null || service.isDestroyed()) {
LogUtils.e(TAG, "onReceive() 终止 | 服务已销毁或为空,执行注销");
LogUtils.e(TAG, "onReceive() 终止服务已销毁");
unregisterAction(context);
return;
}
// 分Action处理业务逻辑
switch (action) {
case Intent.ACTION_BATTERY_CHANGED:
handleBatteryStateChanged(service, intent);
@@ -82,192 +81,145 @@ public class ControlCenterServiceReceiver extends BroadcastReceiver {
handleUpdateForegroundNotification(service);
break;
case ACTION_APPCONFIG_CHANGED:
LogUtils.d(TAG, "onReceive() 分发 | 处理配置更新广播");
handleNotifyAppConfigUpdate(service);
break;
default:
LogUtils.w(TAG, String.format("onReceive() 警告 | 未知Action=%s", action));
LogUtils.w(TAG, "未知Action" + action);
}
LogUtils.d(TAG, "onReceive() 完成 | 广播处理结束");
}
// ====================== 业务处理方法(按功能拆分,强化容错与日志 ======================
/**
* 处理电池状态变化广播
* @param service 控制中心服务实例
* @param intent 电池状态广播意图
*/
// ====================== 电池状态(核心修复区 ======================
private void handleBatteryStateChanged(ControlCenterService service, Intent intent) {
LogUtils.d(TAG, "handleBatteryStateChanged() 执行 | 解析电池状态");
LogUtils.d(TAG, "handleBatteryStateChanged() 解析电池状态");
try {
// 1. 解析并校验当前电池状态
boolean currentCharging = BatteryUtils.isCharging(intent);
int currentBatteryLevel = BatteryUtils.getCurrentBatteryLevel(intent);
currentBatteryLevel = Math.min(Math.max(currentBatteryLevel, BATTERY_LEVEL_MIN), BATTERY_LEVEL_MAX);
LogUtils.d(TAG, String.format("handleBatteryStateChanged() 解析 | 充电=%b | 电量=%d%%", currentCharging, currentBatteryLevel));
// 2. 状态无变化则跳过,减少无效运算
LogUtils.d(TAG, String.format("当前:充电=%b | 电量=%d%%", currentCharging, currentBatteryLevel));
// ================ 【关键修复1】状态没变直接跳过 ================
if (currentCharging == sIsCharging && currentBatteryLevel == sLastBatteryLevel) {
LogUtils.d(TAG, "handleBatteryStateChanged() 跳过 | 电池状态无变化");
LogUtils.d(TAG, "状态无变化,跳过");
return;
}
// 在插拔充电线时,执行贴心服务
if(currentCharging != sIsCharging && sLastBatteryLevel != INVALID_BATTERY) {
//App.notifyMessage(TAG, String.format("sLastBatteryLevel %d", sLastBatteryLevel));
if(currentCharging) {
ThoughtfulService.startServiceWithType(service, ThoughtfulService.ServiceType.CHARGE_STATE);
} else {
ThoughtfulService.startServiceWithType(service, ThoughtfulService.ServiceType.DISCHARGE_STATE);
}
}
// 3. 更新静态缓存状态,保证多线程可见
// ================ 【关键修复2】只有 真正插拔充电 才播报 ================
boolean isRealPlugSwitch = (currentCharging != sIsCharging);
boolean isBatteryValid = (sLastBatteryLevel != INVALID_BATTERY);
// ================ 【关键修复3】防抖动3秒内不重复触发 ================
long now = System.currentTimeMillis();
boolean canTrigger = (now - sLastTriggerTime >= MIN_TRIGGER_INTERVAL);
if (isRealPlugSwitch && isBatteryValid && canTrigger) {
LogUtils.d(TAG, "检测到充电状态切换 → 执行TTS提醒");
// 更新触发时间
sLastTriggerTime = now;
// 执行播报
if (currentCharging) {
ThoughtfulService.startServiceWithType(service, ThoughtfulService.ServiceType.CHARGE_STATE);
} else {
ThoughtfulService.startServiceWithType(service, ThoughtfulService.ServiceType.DISCHARGE_STATE);
}
}
// 更新缓存
sIsCharging = currentCharging;
sLastBatteryLevel = currentBatteryLevel;
// 4. 同步缓存状态到配置
// 同步配置
handleNotifyAppConfigUpdate(service);
LogUtils.d(TAG, String.format("handleBatteryStateChanged() 完成 | 缓存电量=%d%% | 缓存充电状态=%b",
sLastBatteryLevel, sIsCharging));
} catch (Exception e) {
LogUtils.e(TAG, "handleBatteryStateChanged() 失败", e);
LogUtils.e(TAG, "handleBatteryStateChanged 异常", e);
}
}
/**
* 处理配置变更通知,同步缓存状态到配置
* @param service 控制中心服务实例
*/
// ====================== 配置同步 ======================
private void handleNotifyAppConfigUpdate(ControlCenterService service) {
LogUtils.d(TAG, "handleNotifyAppConfigUpdate() 执行 | 同步缓存状态到配置");
LogUtils.d(TAG, "handleNotifyAppConfigUpdate() 同步配置");
try {
// 加载最新配置
AppConfigBean latestConfig = AppConfigUtils.getInstance(service).loadAppConfig();
if (latestConfig == null) {
LogUtils.e(TAG, "handleNotifyAppConfigUpdate() 终止 | 最新配置为空");
LogUtils.e(TAG, "配置为空,终止");
return;
}
LogUtils.d(TAG, String.format("handleNotifyAppConfigUpdate() 加载 | 充电阈值=%d | 耗电阈值=%d",
latestConfig.getChargeReminderValue(), latestConfig.getUsageReminderValue()));
// 同步缓存的电池状态到配置
App.sQuantityOfElectricity = sLastBatteryLevel;
latestConfig.setIsCharging(sIsCharging);
service.notifyAppConfigUpdate(latestConfig);
LogUtils.d(TAG, String.format("handleNotifyAppConfigUpdate() 完成 | 缓存电量=%d%% | 充电状态=%b",
sLastBatteryLevel, sIsCharging));
} catch (Exception e) {
LogUtils.e(TAG, "handleNotifyAppConfigUpdate() 失败", e);
LogUtils.e(TAG, "handleNotifyAppConfigUpdate 异常", e);
}
}
/**
* 处理前台服务通知更新
* @param service 控制中心服务实例
*/
// ====================== 通知更新 ======================
private void handleUpdateForegroundNotification(ControlCenterService service) {
LogUtils.d(TAG, "handleUpdateForegroundNotification() 执行 | 更新前台通知");
LogUtils.d(TAG, "handleUpdateForegroundNotification() 更新通知");
try {
NotificationManagerUtils notifyUtils = service.getNotificationManager();
NotificationMessage notifyMsg = service.getForegroundNotifyMsg();
// 非空校验,避免空指针
if (notifyUtils == null || notifyMsg == null) {
LogUtils.e(TAG, String.format("handleUpdateForegroundNotification() 终止 | 通知工具或消息为空notifyUtils=%s | notifyMsg=%s",
notifyUtils, notifyMsg));
LogUtils.e(TAG, "通知工具或消息为空");
return;
}
notifyUtils.updateForegroundServiceNotify(notifyMsg);
LogUtils.d(TAG, String.format("handleUpdateForegroundNotification() 完成 | 标题=%s", notifyMsg.getTitle()));
} catch (Exception e) {
LogUtils.e(TAG, "handleUpdateForegroundNotification() 失败", e);
LogUtils.e(TAG, "更新通知异常", e);
}
}
// ====================== 广播注册/注销(强化容错,避免重复操作) ======================
/**
* 注册广播接收器
* @param context 上下文
*/
// ====================== 注册/注销 ======================
public void registerAction(Context context) {
LogUtils.d(TAG, "registerAction() 执行 | 注册广播接收器");
if (context == null || isRegistered) {
LogUtils.e(TAG, "registerAction() 失败 | 上下文为空或已注册");
return;
}
if (context == null || isRegistered) return;
try {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
filter.addAction(ACTION_UPDATE_FOREGROUND_NOTIFICATION);
filter.addAction(ACTION_APPCONFIG_CHANGED);
filter.setPriority(BROADCAST_PRIORITY);
context.registerReceiver(this, filter);
isRegistered = true;
LogUtils.d(TAG, String.format("registerAction() 完成 | 优先级=%d", BROADCAST_PRIORITY));
LogUtils.d(TAG, "广播注册完成");
} catch (Exception e) {
LogUtils.e(TAG, "registerAction() 失败", e);
LogUtils.e(TAG, "注册异常", e);
}
}
/**
* 注销广播接收器
* @param context 上下文
*/
public void unregisterAction(Context context) {
LogUtils.d(TAG, "unregisterAction() 执行 | 注销广播接收器");
if (context == null || !isRegistered) {
LogUtils.e(TAG, "unregisterAction() 失败 | 上下文为空或未注册");
return;
}
if (context == null || !isRegistered) return;
try {
context.unregisterReceiver(this);
isRegistered = false;
LogUtils.d(TAG, "unregisterAction() 完成 | 广播注销成功");
} catch (IllegalArgumentException e) {
LogUtils.w(TAG, "unregisterAction() 警告 | 广播未注册,跳过注销");
LogUtils.d(TAG, "广播注销");
} catch (Exception e) {
LogUtils.e(TAG, "unregisterAction() 失败", e);
LogUtils.w(TAG, "注销异常", e);
}
}
// ====================== 资源释放与Getter方法按需开放防泄漏 ======================
/**
* 主动释放资源,避免内存泄漏
*/
// ====================== 释放 ======================
public void release() {
LogUtils.d(TAG, "release() 执行 | 释放广播接收器资源");
// 清空弱引用帮助GC回收
LogUtils.d(TAG, "release() 释放资源");
if (mwrControlCenterService != null) {
mwrControlCenterService.clear();
mwrControlCenterService = null;
LogUtils.d(TAG, "release() 步骤 | 弱引用已清空");
}
// 重置静态状态缓存
sLastBatteryLevel = -1;
// 重置静态状态
sLastBatteryLevel = INVALID_BATTERY;
sIsCharging = false;
LogUtils.d(TAG, "release() 完成 | 静态状态缓存已重置");
sLastTriggerTime = 0; // 【新增】重置防抖时间
}
/**
* 获取上次记录的电池电量
* @return 电量值0-100未初始化返回-1
*/
// ====================== Getter ======================
public static int getLastBatteryLevel() {
return sLastBatteryLevel;
}
/**
* 获取上次记录的充电状态
* @return true=充电中false=未充电
*/
public static boolean isLastCharging() {
return sIsCharging;
}

View File

@@ -5,6 +5,7 @@ import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.powerbell.App;
import cc.winboll.studio.powerbell.models.AppConfigBean;
import cc.winboll.studio.powerbell.models.ThoughtfulServiceBean;
import cc.winboll.studio.powerbell.utils.AppConfigUtils;
@@ -18,147 +19,203 @@ import cc.winboll.studio.powerbell.utils.AppConfigUtils;
*/
public class ThoughtfulService extends Service {
// ====================================== 常量区 - 置顶排序 ======================================
// ====================================== 常量区 ======================================
public static final String TAG = "ThoughtfulService";
/** Intent传递 服务类型 的Key值 */
public static final String EXTRA_SERVICE_TYPE = "EXTRA_SERVICE_TYPE";
// ====================================== 枚举类 - 服务类型 充电/放电状态 ======================================
/**
* 服务执行类型枚举
* CHARGE_STATE : 充电状态服务
* DISCHARGE_STATE : 放电(耗电)状态服务
*/
// 防止重复播报的标志(静态,全局唯一)
private static boolean sIsPlaying = false;
// ====================================== 枚举 ======================================
public enum ServiceType {
CHARGE_STATE, //充电状态服务
DISCHARGE_STATE //放电状态服务
CHARGE_STATE,
DISCHARGE_STATE
}
// ====================================== 对外公开静态启动函数【新增核心】入参Context + 枚举 ======================================
/**
* 公开静态方法:传入上下文+服务类型枚举,一键构建意图并启动当前服务
* @param context 上下文对象
* @param serviceType 服务类型枚举【充电/放电】
*/
// ====================================== 外部启动入口(加固) ======================================
public static void startServiceWithType(Context context, ServiceType serviceType) {
LogUtils.d(TAG, "【startServiceWithType】静态启动方法调用 | Context=" + context + " | ServiceType=" + (serviceType == null ? "null" : serviceType.name()));
ThoughtfulServiceBean thoughtfulServiceBean = ThoughtfulServiceBean.loadBean(context, ThoughtfulServiceBean.class);
if (thoughtfulServiceBean == null) {
thoughtfulServiceBean = new ThoughtfulServiceBean();
}
// 对应TTS服务提醒没有启用就退出
if((serviceType == ServiceType.CHARGE_STATE && !thoughtfulServiceBean.isEnableChargeTts())
||(serviceType == ServiceType.DISCHARGE_STATE && !thoughtfulServiceBean.isEnableUsePowerTts())){
return;
}
// 判空健壮性校验
if (context != null && serviceType != null) {
// 构建意图 + 封装枚举参数
Intent intent = new Intent(context, ThoughtfulService.class);
intent.putExtra(EXTRA_SERVICE_TYPE, serviceType);
// 启动服务
context.startService(intent);
LogUtils.d(TAG, "【startServiceWithType】服务启动成功执行[" + serviceType.name() + "]任务");
} else {
LogUtils.d(TAG, "【startServiceWithType】上下文为空 或 服务类型枚举为空,跳过启动服务");
LogUtils.d(TAG, "【startServiceWithType】调用 | type=" + (serviceType == null ? "null" : serviceType.name()));
if (context == null || serviceType == null) {
LogUtils.d(TAG, "【startServiceWithType】空参数直接返回");
return;
}
// 1. 预先读取配置,不满足直接不启动服务(最关键拦截)
ThoughtfulServiceBean ttsBean = ThoughtfulServiceBean.loadBean(context, ThoughtfulServiceBean.class);
if (ttsBean == null) {
ttsBean = new ThoughtfulServiceBean();
}
// 充电TTS未开 → 不启动
if (serviceType == ServiceType.CHARGE_STATE && !ttsBean.isEnableChargeTts()) {
LogUtils.d(TAG, "【startServiceWithType】充电TTS未启用不启动服务");
return;
}
// 用电TTS未开 → 不启动
if (serviceType == ServiceType.DISCHARGE_STATE && !ttsBean.isEnableUsePowerTts()) {
LogUtils.d(TAG, "【startServiceWithType】用电TTS未启用不启动服务");
return;
}
// 2. 防止重复启动导致叠加播报
if (sIsPlaying) {
LogUtils.d(TAG, "【startServiceWithType】已有播报任务跳过本次启动");
return;
}
// 3. 真正启动
Intent intent = new Intent(context, ThoughtfulService.class);
intent.putExtra(EXTRA_SERVICE_TYPE, serviceType);
context.startService(intent);
LogUtils.d(TAG, "【startServiceWithType】服务启动成功");
}
// ====================================== 生命周期方法 - 绑定服务 (原逻辑保留) ======================================
// ====================================== 生命周期 ======================================
@Override
public IBinder onBind(Intent intent) {
LogUtils.d(TAG, "【onBind】服务绑定方法调用入参Intent" + intent);
return null;
}
// ====================================== 生命周期方法 - 启动服务【核心逻辑】接收枚举+分支执行任务 ======================================
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
LogUtils.d(TAG, "【onStartCommand】服务启动方法调用 | intent=" + intent + " | flags=" + flags + " | startId=" + startId);
// 判断意图非空,解析服务类型参数
if (intent != null) {
LogUtils.d(TAG, "【onStartCommand】Intent不为空,开始解析服务类型枚举参数");
// 获取传递的服务类型枚举
ServiceType serviceType = (ServiceType) intent.getSerializableExtra(EXTRA_SERVICE_TYPE);
// 根据服务类型,执行对应任务
if (serviceType != null) {
LogUtils.d(TAG, "【onStartCommand】解析到服务类型" + serviceType.name());
switch (serviceType) {
case CHARGE_STATE:
// 执行【充电状态】对应的业务任务
executeChargeStateTask();
break;
case DISCHARGE_STATE:
// 执行【放电状态】对应的业务任务
executeDischargeStateTask();
break;
default:
LogUtils.d(TAG, "【onStartCommand】未知的服务类型不执行任何任务");
break;
}
} else {
LogUtils.d(TAG, "【onStartCommand】未解析到有效服务类型参数参数为空");
}
} else {
LogUtils.d(TAG, "【onStartCommand】启动服务的Intent为空直接返回");
LogUtils.d(TAG, "【onStartCommand】进入");
if (intent == null) {
LogUtils.d(TAG, "【onStartCommand】intent = null停止");
stopSelf();
return START_NOT_STICKY;
}
// 返回默认策略,与原生逻辑一致
int result = super.onStartCommand(intent, flags, startId);
LogUtils.d(TAG, "【onStartCommand】服务执行完成,返回值:" + result);
return result;
// 再次防止重复播报(双重保险)
if (sIsPlaying) {
LogUtils.d(TAG, "【onStartCommand】已有播报,直接停止服务");
stopSelf();
return START_NOT_STICKY;
}
// 解析类型
ServiceType type = (ServiceType) intent.getSerializableExtra(EXTRA_SERVICE_TYPE);
if (type == null) {
LogUtils.d(TAG, "【onStartCommand】type = null停止");
stopSelf();
return START_NOT_STICKY;
}
// 二次校验开关(防止外部绕过 startServiceWithType 直接启动)
ThoughtfulServiceBean ttsBean = ThoughtfulServiceBean.loadBean(this, ThoughtfulServiceBean.class);
if (ttsBean == null) ttsBean = new ThoughtfulServiceBean();
boolean allowPlay = false;
if (type == ServiceType.CHARGE_STATE && ttsBean.isEnableChargeTts()) {
allowPlay = true;
}
if (type == ServiceType.DISCHARGE_STATE && ttsBean.isEnableUsePowerTts()) {
allowPlay = true;
}
if (!allowPlay) {
LogUtils.d(TAG, "【onStartCommand】TTS开关已关闭不执行播报");
stopSelf();
return START_NOT_STICKY;
}
// 执行任务
if (type == ServiceType.CHARGE_STATE) {
executeChargeStateTask();
} else if (type == ServiceType.DISCHARGE_STATE) {
executeDischargeStateTask();
}
return START_NOT_STICKY; // 重要:执行完自动销毁,不保留服务
}
// ====================================== 私有业务方法 充电/放电 分任务执行 ======================================
/**
* 执行【充电状态】的业务任务
* 可在此方法内编写 充电时的逻辑(语音提醒/电量监控/弹窗等)
*/
// ====================================== 充电任务 ======================================
private void executeChargeStateTask() {
LogUtils.d(TAG, "【executeChargeStateTask】执行充电状态】业务任务 >>> ");
//ToastUtils.show("【executeChargeStateTask】执行【充电状态】业务任务 >>> ");
// TODO 此处添加充电状态需要执行的业务逻辑代码
// 加载最新配置
AppConfigBean latestConfig = AppConfigUtils.getInstance(this).loadAppConfig();
if (latestConfig == null) {
LogUtils.e(TAG, "handleNotifyAppConfigUpdate() 终止 | 最新配置为空");
return;
}
if (latestConfig.isEnableChargeReminder()) {
int nChargeReminderValue = latestConfig.getChargeReminderValue();
String szRemind = String.format("限量充电提醒已启用,限量值为百分之%d。", nChargeReminderValue);
szRemind = szRemind + szRemind + szRemind;
TTSPlayService.startPlayTTS(this, szRemind);
}
LogUtils.d(TAG, "【executeChargeStateTask】执行充电任务");
sIsPlaying = true; // 锁定播报
try {
AppConfigBean config = AppConfigUtils.getInstance(this).loadAppConfig();
if (config == null) {
LogUtils.e(TAG, "配置为空,停止");
return;
}
ThoughtfulServiceBean ttsBean = ThoughtfulServiceBean.loadBean(this, ThoughtfulServiceBean.class);
if (ttsBean == null) ttsBean = new ThoughtfulServiceBean();
// 主提醒开关未开 → 直接不播
if (!config.isEnableChargeReminder()) {
LogUtils.d(TAG, "充电提醒总开关关闭,不播报");
return;
}
int limit = config.getChargeReminderValue();
int battery = App.sQuantityOfElectricity;
// 电量无效值 → 不拼接电量
String batteryStr = "";
if (battery >= 0 && battery <= 100 && ttsBean.isEnableChargeTtsWithBattary()) {
batteryStr = String.format("当前电量百分之%d。", battery);
}
String text = batteryStr + String.format("限量充电提醒已启用,限值百分之%d。", limit);
TTSPlayService.startPlayTTS(this, text);
LogUtils.d(TAG, "充电TTS已下发" + text);
} finally {
sIsPlaying = false; // 释放锁
stopSelf();
}
}
/**
* 执行【放电(耗电)状态】的业务任务
* 可在此方法内编写 放电时的逻辑(语音提醒/电量监控/弹窗等)
*/
// ====================================== 放电任务 ======================================
private void executeDischargeStateTask() {
LogUtils.d(TAG, "【executeDischargeStateTask】执行放电状态】业务任务 >>> ");
//ToastUtils.show("【executeDischargeStateTask】执行【放电状态】业务任务 >>> ");
// TODO 此处添加放电状态需要执行的业务逻辑代码
// 加载最新配置
AppConfigBean latestConfig = AppConfigUtils.getInstance(this).loadAppConfig();
if (latestConfig == null) {
LogUtils.e(TAG, "handleNotifyAppConfigUpdate() 终止 | 最新配置为空");
return;
}
LogUtils.d(TAG, "【executeDischargeStateTask】执行放电任务");
if (latestConfig.isEnableUsageReminder()) {
int nUsageReminderValue = latestConfig.getUsageReminderValue();
String szRemind = String.format("电量不足提醒已启用,低电值为百分之%d。", nUsageReminderValue);
//szRemind = szRemind + szRemind + szRemind;
TTSPlayService.startPlayTTS(this, szRemind);
}
sIsPlaying = true;
try {
AppConfigBean config = AppConfigUtils.getInstance(this).loadAppConfig();
if (config == null) {
LogUtils.e(TAG, "配置为空,停止");
return;
}
ThoughtfulServiceBean ttsBean = ThoughtfulServiceBean.loadBean(this, ThoughtfulServiceBean.class);
if (ttsBean == null) ttsBean = new ThoughtfulServiceBean();
// 主提醒开关未开 → 不播
if (!config.isEnableUsageReminder()) {
LogUtils.d(TAG, "低电提醒总开关关闭,不播报");
return;
}
int limit = config.getUsageReminderValue();
int battery = App.sQuantityOfElectricity;
String batteryStr = "";
if (battery >= 0 && battery <= 100 && ttsBean.isEnableUseageTtsWithBattary()) {
batteryStr = String.format("当前电量百分之%d。", battery);
}
String text = batteryStr + String.format("低电量提醒已启用,限值百分之%d。", limit);
TTSPlayService.startPlayTTS(this, text);
LogUtils.d(TAG, "放电TTS已下发" + text);
} finally {
sIsPlaying = false;
stopSelf();
}
}
@Override
public void onDestroy() {
super.onDestroy();
LogUtils.d(TAG, "【onDestroy】服务已销毁");
}
}

View File

@@ -62,6 +62,33 @@
android:onClick="onEnableUsePowerTts"
android:id="@+id/activitysettingsCheckBox1"/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="("
android:layout_marginLeft="10dp"/>
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="用电TTS加入电量提醒"
android:onClick="onEnableUseageTtsWithBattary"
android:id="@+id/activitysettingsCheckBox3"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=")"
android:layout_marginLeft="20dp"/>
</LinearLayout>
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -69,6 +96,33 @@
android:onClick="onEnableChargeTts"
android:id="@+id/activitysettingsCheckBox2"/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="("
android:layout_marginLeft="10dp"/>
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="充电TTS加入电量提醒"
android:onClick="onEnableChargeTtsWithBattary"
android:id="@+id/activitysettingsCheckBox4"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=")"
android:layout_marginLeft="20dp"/>
</LinearLayout>
</LinearLayout>
<LinearLayout