20251212_211940_525
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
#Created by .winboll/winboll_app_build.gradle
|
||||
#Fri Dec 12 13:12:27 GMT 2025
|
||||
#Fri Dec 12 13:17:41 GMT 2025
|
||||
stageCount=1
|
||||
libraryProject=
|
||||
baseVersion=15.12
|
||||
publishVersion=15.12.0
|
||||
buildCount=60
|
||||
buildCount=61
|
||||
baseBetaVersion=15.12.1
|
||||
|
||||
@@ -22,12 +22,12 @@ import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import cc.winboll.studio.contacts.R;
|
||||
import cc.winboll.studio.contacts.adapters.PhoneConnectRuleAdapter;
|
||||
import cc.winboll.studio.contacts.bobulltoon.TomCat;
|
||||
import cc.winboll.studio.contacts.dun.Rules;
|
||||
import cc.winboll.studio.contacts.model.MainServiceBean;
|
||||
import cc.winboll.studio.contacts.model.PhoneConnectRuleBean;
|
||||
import cc.winboll.studio.contacts.model.RingTongBean;
|
||||
import cc.winboll.studio.contacts.model.SettingsBean;
|
||||
import cc.winboll.studio.contacts.bobulltoon.TomCat;
|
||||
import cc.winboll.studio.contacts.dun.Rules;
|
||||
import cc.winboll.studio.contacts.services.MainService;
|
||||
import cc.winboll.studio.contacts.views.DuInfoTextView;
|
||||
import cc.winboll.studio.libaes.interfaces.IWinBoLLActivity;
|
||||
@@ -40,12 +40,15 @@ import java.util.List;
|
||||
/**
|
||||
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
|
||||
* @Date 2025/02/21 05:37:42
|
||||
* @Describe Contacts 主窗口
|
||||
* @Describe Contacts 设置页面(完全适配 API 30 + Java 7 语法)
|
||||
* 核心优化:1. 移除高版本API依赖 2. Java7规范写法 3. 强化内存泄漏防护 4. 版本判断硬编码
|
||||
*/
|
||||
public class SettingsActivity extends WinBollActivity implements IWinBoLLActivity {
|
||||
|
||||
// ====================== 常量定义区 ======================
|
||||
public static final String TAG = "SettingsActivity";
|
||||
// API版本硬编码常量(替代Build.VERSION_CODES,适配API30)
|
||||
private static final int ANDROID_6_API = 23;
|
||||
|
||||
// ====================== 静态控件区 ======================
|
||||
static DuInfoTextView _DuInfoTextView;
|
||||
@@ -108,7 +111,15 @@ public class SettingsActivity extends WinBollActivity implements IWinBoLLActivit
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
LogUtils.d(TAG, "onDestroy: 设置页面开始销毁");
|
||||
_DuInfoTextView = null; // 清空静态引用,避免内存泄漏
|
||||
// 清空静态引用 + 置空所有控件引用,彻底避免内存泄漏
|
||||
_DuInfoTextView = null;
|
||||
mToolbar = null;
|
||||
mswMainService = null;
|
||||
msbVolume = null;
|
||||
mtvVolume = null;
|
||||
recyclerView = null;
|
||||
adapter = null;
|
||||
ruleList = null;
|
||||
LogUtils.d(TAG, "onDestroy: 设置页面销毁完成");
|
||||
}
|
||||
|
||||
@@ -117,11 +128,12 @@ public class SettingsActivity extends WinBollActivity implements IWinBoLLActivit
|
||||
LogUtils.d(TAG, "initToolbar: 初始化工具栏");
|
||||
mToolbar = (Toolbar) findViewById(R.id.activitymainToolbar1);
|
||||
setSupportActionBar(mToolbar);
|
||||
// 显示后退按钮
|
||||
// 显示后退按钮(添加空指针防护)
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setSubtitle(getTag());
|
||||
}
|
||||
// Java7 匿名内部类实现点击监听,禁止Lambda
|
||||
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
@@ -135,7 +147,14 @@ public class SettingsActivity extends WinBollActivity implements IWinBoLLActivit
|
||||
LogUtils.d(TAG, "initMainServiceSwitch: 初始化主服务开关");
|
||||
mswMainService = (Switch) findViewById(R.id.sw_mainservice);
|
||||
MainServiceBean mMainServiceBean = MainServiceBean.loadBean(this, MainServiceBean.class);
|
||||
mswMainService.setChecked(mMainServiceBean.isEnable());
|
||||
// 空指针防护:避免MainServiceBean为null导致崩溃
|
||||
if (mMainServiceBean != null) {
|
||||
mswMainService.setChecked(mMainServiceBean.isEnable());
|
||||
} else {
|
||||
mswMainService.setChecked(false);
|
||||
LogUtils.w(TAG, "initMainServiceSwitch: MainServiceBean为null,默认关闭开关");
|
||||
}
|
||||
|
||||
mswMainService.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View arg0) {
|
||||
@@ -155,6 +174,12 @@ public class SettingsActivity extends WinBollActivity implements IWinBoLLActivit
|
||||
mtvVolume = (TextView) findViewById(R.id.tv_volume);
|
||||
final AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
|
||||
|
||||
// 空指针防护:AudioManager可能为null
|
||||
if (audioManager == null) {
|
||||
LogUtils.e(TAG, "initVolumeSeekBar: AudioManager获取失败,跳过音量初始化");
|
||||
return;
|
||||
}
|
||||
|
||||
// 设置SeekBar最大值和初始进度
|
||||
mnStreamMaxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_RING);
|
||||
msbVolume.setMax(mnStreamMaxVolume);
|
||||
@@ -162,7 +187,7 @@ public class SettingsActivity extends WinBollActivity implements IWinBoLLActivit
|
||||
msbVolume.setProgress(mnStreamVolume);
|
||||
updateStreamVolumeTextView();
|
||||
|
||||
// 音量调节监听
|
||||
// 音量调节监听(Java7匿名内部类)
|
||||
msbVolume.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
@@ -207,27 +232,37 @@ public class SettingsActivity extends WinBollActivity implements IWinBoLLActivit
|
||||
swIsEnableDun = (Switch) findViewById(R.id.sw_IsEnableDun);
|
||||
|
||||
SettingsBean settingsModel = Rules.getInstance(this).getSettingsModel();
|
||||
etDunTotalCount.setText(Integer.toString(settingsModel.getDunTotalCount()));
|
||||
etDunResumeSecondCount.setText(Integer.toString(settingsModel.getDunResumeSecondCount()));
|
||||
etDunResumeCount.setText(Integer.toString(settingsModel.getDunResumeCount()));
|
||||
swIsEnableDun.setChecked(settingsModel.isEnableDun());
|
||||
// 空指针防护:避免SettingsModel为null
|
||||
if (settingsModel != null) {
|
||||
etDunTotalCount.setText(Integer.toString(settingsModel.getDunTotalCount()));
|
||||
etDunResumeSecondCount.setText(Integer.toString(settingsModel.getDunResumeSecondCount()));
|
||||
etDunResumeCount.setText(Integer.toString(settingsModel.getDunResumeCount()));
|
||||
swIsEnableDun.setChecked(settingsModel.isEnableDun());
|
||||
|
||||
boolean isEnableDun = settingsModel.isEnableDun();
|
||||
etDunTotalCount.setEnabled(!isEnableDun);
|
||||
etDunResumeSecondCount.setEnabled(!isEnableDun);
|
||||
etDunResumeCount.setEnabled(!isEnableDun);
|
||||
boolean isEnableDun = settingsModel.isEnableDun();
|
||||
etDunTotalCount.setEnabled(!isEnableDun);
|
||||
etDunResumeSecondCount.setEnabled(!isEnableDun);
|
||||
etDunResumeCount.setEnabled(!isEnableDun);
|
||||
} else {
|
||||
LogUtils.e(TAG, "initDunSettings: SettingsModel为null,云盾设置初始化失败");
|
||||
}
|
||||
}
|
||||
|
||||
private void initBoBullToonViews() {
|
||||
LogUtils.d(TAG, "initBoBullToonViews: 初始化BoBullToon相关控件");
|
||||
etBoBullToonURL = (EditText) findViewById(R.id.bobulltoonurl_et);
|
||||
etBoBullToonURL.setText(Rules.getInstance(this).getBoBullToonURL());
|
||||
etPhone = (EditText) findViewById(R.id.activitysettingsEditText1);
|
||||
// 空指针防护:避免Rules.getInstance返回null
|
||||
Rules rules = Rules.getInstance(this);
|
||||
if (rules != null) {
|
||||
etBoBullToonURL.setText(rules.getBoBullToonURL());
|
||||
}
|
||||
}
|
||||
|
||||
// ====================== 工具函数区 ======================
|
||||
private void updateStreamVolumeTextView() {
|
||||
mtvVolume.setText(String.format("%d/%d", mnStreamVolume, mnStreamMaxVolume));
|
||||
// Java7 字符串拼接,避免String.format可能的空指针
|
||||
mtvVolume.setText(mnStreamVolume + "/" + mnStreamMaxVolume);
|
||||
}
|
||||
|
||||
// ====================== 静态通知函数区 ======================
|
||||
@@ -249,15 +284,31 @@ public class SettingsActivity extends WinBollActivity implements IWinBoLLActivit
|
||||
etDunResumeCount.setEnabled(!isEnableDun);
|
||||
|
||||
SettingsBean settingsModel = Rules.getInstance(this).getSettingsModel();
|
||||
// 空指针防护:SettingsModel为null时直接返回
|
||||
if (settingsModel == null) {
|
||||
LogUtils.e(TAG, "onSW_IsEnableDun: SettingsModel为null,操作失败");
|
||||
swIsEnableDun.setChecked(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isEnableDun) {
|
||||
try {
|
||||
int totalCount = Integer.parseInt(etDunTotalCount.getText().toString());
|
||||
int resumeSecond = Integer.parseInt(etDunResumeSecondCount.getText().toString());
|
||||
int resumeCount = Integer.parseInt(etDunResumeCount.getText().toString());
|
||||
String totalCountStr = etDunTotalCount.getText().toString().trim();
|
||||
String resumeSecondStr = etDunResumeSecondCount.getText().toString().trim();
|
||||
String resumeCountStr = etDunResumeCount.getText().toString().trim();
|
||||
// 空字符串校验
|
||||
if (totalCountStr.isEmpty() || resumeSecondStr.isEmpty() || resumeCountStr.isEmpty()) {
|
||||
throw new NumberFormatException("参数不能为空");
|
||||
}
|
||||
int totalCount = Integer.parseInt(totalCountStr);
|
||||
int resumeSecond = Integer.parseInt(resumeSecondStr);
|
||||
int resumeCount = Integer.parseInt(resumeCountStr);
|
||||
settingsModel.setDunTotalCount(totalCount);
|
||||
settingsModel.setDunResumeSecondCount(resumeSecond);
|
||||
settingsModel.setDunResumeCount(resumeCount);
|
||||
ToastUtils.show((totalCount == 1) ? "电话骚扰防御力几乎为0。" : String.format("以下设置将在连拨%d次后接通电话。", totalCount));
|
||||
// Java7 条件判断 + 字符串拼接
|
||||
String toastMsg = (totalCount == 1) ? "电话骚扰防御力几乎为0。" : "以下设置将在连拨" + totalCount + "次后接通电话。";
|
||||
ToastUtils.show(toastMsg);
|
||||
LogUtils.d(TAG, "onSW_IsEnableDun: 云盾参数更新完成,totalCount=" + totalCount);
|
||||
} catch (NumberFormatException e) {
|
||||
LogUtils.e(TAG, "onSW_IsEnableDun: 云盾参数格式错误", e);
|
||||
@@ -284,9 +335,14 @@ public class SettingsActivity extends WinBollActivity implements IWinBoLLActivit
|
||||
|
||||
public void onAddNewConnectionRule(View view) {
|
||||
LogUtils.d(TAG, "onAddNewConnectionRule: 添加新的连接规则");
|
||||
Rules.getInstance(this).getPhoneBlacRuleBeanList().add(new PhoneConnectRuleBean());
|
||||
Rules.getInstance(this).saveRules();
|
||||
adapter.notifyDataSetChanged();
|
||||
Rules rules = Rules.getInstance(this);
|
||||
if (rules != null) {
|
||||
rules.getPhoneBlacRuleBeanList().add(new PhoneConnectRuleBean());
|
||||
rules.saveRules();
|
||||
adapter.notifyDataSetChanged();
|
||||
} else {
|
||||
LogUtils.e(TAG, "onAddNewConnectionRule: Rules实例为null,添加规则失败");
|
||||
}
|
||||
}
|
||||
|
||||
public void onDefaultPhone(View view) {
|
||||
@@ -297,7 +353,8 @@ public class SettingsActivity extends WinBollActivity implements IWinBoLLActivit
|
||||
|
||||
public void onCanDrawOverlays(View view) {
|
||||
LogUtils.d(TAG, "onCanDrawOverlays: 检查悬浮窗权限");
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) {
|
||||
// 版本判断硬编码(替代Build.VERSION_CODES.M),适配API30
|
||||
if (Build.VERSION.SDK_INT >= ANDROID_6_API && !Settings.canDrawOverlays(this)) {
|
||||
askForDrawOverlay();
|
||||
} else {
|
||||
ToastUtils.show("悬浮窗已开启");
|
||||
@@ -307,32 +364,44 @@ public class SettingsActivity extends WinBollActivity implements IWinBoLLActivit
|
||||
public void onCleanBoBullToonData(View view) {
|
||||
LogUtils.d(TAG, "onCleanBoBullToonData: 清理BoBullToon数据");
|
||||
TomCat tomCat = TomCat.getInstance(this);
|
||||
tomCat.cleanBoBullToon();
|
||||
ToastUtils.show("BoBullToon数据已清理");
|
||||
if (tomCat != null) {
|
||||
tomCat.cleanBoBullToon();
|
||||
ToastUtils.show("BoBullToon数据已清理");
|
||||
}
|
||||
}
|
||||
|
||||
public void onResetBoBullToonURL(View view) {
|
||||
LogUtils.d(TAG, "onResetBoBullToonURL: 重置BoBullToon URL");
|
||||
Rules.getInstance(this).resetDefaultBoBullToonURL();
|
||||
etBoBullToonURL.setText(Rules.getInstance(this).getBoBullToonURL());
|
||||
ToastUtils.show("已重置 BoBullToon URL。");
|
||||
Rules rules = Rules.getInstance(this);
|
||||
if (rules != null) {
|
||||
rules.resetDefaultBoBullToonURL();
|
||||
etBoBullToonURL.setText(rules.getBoBullToonURL());
|
||||
ToastUtils.show("已重置 BoBullToon URL。");
|
||||
}
|
||||
}
|
||||
|
||||
public void onDownloadBoBullToon(View view) {
|
||||
LogUtils.d(TAG, "onDownloadBoBullToon: 开始下载BoBullToon数据");
|
||||
Rules rules = Rules.getInstance(this);
|
||||
if (rules == null) {
|
||||
LogUtils.e(TAG, "onDownloadBoBullToon: Rules实例为null,下载失败");
|
||||
return;
|
||||
}
|
||||
String inputUrl = etBoBullToonURL.getText().toString().trim();
|
||||
String savedUrl = Rules.getInstance(this).getBoBullToonURL();
|
||||
String savedUrl = rules.getBoBullToonURL();
|
||||
if (!inputUrl.equals(savedUrl)) {
|
||||
Rules.getInstance(this).setBoBullToonURL(inputUrl);
|
||||
rules.setBoBullToonURL(inputUrl);
|
||||
LogUtils.d(TAG, "onDownloadBoBullToon: BoBullToon URL已更新为" + inputUrl);
|
||||
}
|
||||
|
||||
final TomCat tomCat = TomCat.getInstance(this);
|
||||
// Java7 匿名内部类实现Runnable,禁止Lambda
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (tomCat.downloadBoBullToon()) {
|
||||
if (tomCat != null && tomCat.downloadBoBullToon()) {
|
||||
LogUtils.d(TAG, "onDownloadBoBullToon: BoBullToon 下载成功");
|
||||
// 主线程更新UI(Java7 匿名内部类)
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -356,9 +425,10 @@ public class SettingsActivity extends WinBollActivity implements IWinBoLLActivit
|
||||
ToastUtils.show("请输入要查询的号码");
|
||||
return;
|
||||
}
|
||||
if (tomCat.loadPhoneBoBullToon()) {
|
||||
if (tomCat != null && tomCat.loadPhoneBoBullToon()) {
|
||||
boolean isBoBullToon = tomCat.isPhoneBoBullToon(phone);
|
||||
ToastUtils.show(isBoBullToon ? "It is a BoBullToon Phone!" : "Not in BoBullToon.");
|
||||
String toastMsg = isBoBullToon ? "It is a BoBullToon Phone!" : "Not in BoBullToon.";
|
||||
ToastUtils.show(toastMsg);
|
||||
LogUtils.d(TAG, "onSearchBoBullToonPhone: 号码" + phone + "查询结果:" + (isBoBullToon ? "是" : "否") + "为BoBullToon号码");
|
||||
} else {
|
||||
ToastUtils.show("没有下载 BoBullToon。");
|
||||
@@ -378,6 +448,7 @@ public class SettingsActivity extends WinBollActivity implements IWinBoLLActivit
|
||||
// ====================== 悬浮窗权限请求函数区 ======================
|
||||
private void askForDrawOverlay() {
|
||||
LogUtils.d(TAG, "askForDrawOverlay: 弹出悬浮窗权限请求对话框");
|
||||
// Java7 匿名内部类实现Dialog监听
|
||||
AlertDialog alertDialog = new AlertDialog.Builder(this)
|
||||
.setTitle("允许显示悬浮框")
|
||||
.setMessage("为了使电话监听服务正常工作,请允许这项权限")
|
||||
@@ -406,7 +477,8 @@ public class SettingsActivity extends WinBollActivity implements IWinBoLLActivit
|
||||
|
||||
private void openDrawOverlaySettings() {
|
||||
LogUtils.d(TAG, "openDrawOverlaySettings: 跳转悬浮窗管理设置界面");
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
// 版本判断硬编码
|
||||
if (Build.VERSION.SDK_INT >= ANDROID_6_API) {
|
||||
try {
|
||||
Context context = this;
|
||||
Class<?> clazz = Settings.class;
|
||||
|
||||
Reference in New Issue
Block a user