20251213_104727_568服务启动模块修改。

This commit is contained in:
2025-12-13 10:48:00 +08:00
parent b6a820b281
commit 61a20f6811
2 changed files with 129 additions and 280 deletions

View File

@@ -4,21 +4,16 @@ import android.Manifest;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.telecom.TelecomManager;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
@@ -41,7 +36,6 @@ import cc.winboll.studio.contacts.fragments.ContactsFragment;
import cc.winboll.studio.contacts.fragments.LogFragment;
import cc.winboll.studio.contacts.model.MainServiceBean;
import cc.winboll.studio.contacts.services.MainService;
import cc.winboll.studio.contacts.services.MyCallScreeningService;
import cc.winboll.studio.contacts.utils.PermissionUtils;
import cc.winboll.studio.contacts.views.DunTemperatureView;
import cc.winboll.studio.libaes.interfaces.IWinBoLLActivity;
@@ -57,7 +51,7 @@ import java.util.List;
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
* @Date 2025/08/30 14:32
* @Describe Contacts 主窗口(完全适配 API 30 + Java 7 语法)
* 核心优化1. 与MainService状态联动 2. 移除高版本API依赖 3. 强化资源释放 4. Java7规范写法
* 核心优化1. 移除电话状态监听 2. 移除通话筛选服务 3. 移除 MainService 绑定 4. 保留原有页面结构
*/
public final class MainActivity extends WinBollActivity implements IWinBoLLActivity, ViewPager.OnPageChangeListener, View.OnClickListener {
@@ -70,7 +64,6 @@ public final class MainActivity extends WinBollActivity implements IWinBoLLActiv
private static final int DIALER_REQUEST_CODE = 1;
private static final int REQUEST_REQUIRED_PERMISSIONS = 1002;
private static final int REQUEST_OVERLAY_PERMISSION = 1003;
private static final int REQUEST_CALL_SCREENING_PERMISSION = 1004;
// API版本硬编码常量Java 7兼容杜绝Build.VERSION_CODES高版本引用
private static final int ANDROID_6_API = 23;
@@ -98,13 +91,8 @@ public final class MainActivity extends WinBollActivity implements IWinBoLLActiv
// ====================== 5. 业务逻辑成员区 ======================
private MainServiceBean mMainServiceBean;
private int currentPoint = 0;
private TelephonyManager telephonyManager;
private MyPhoneStateListener phoneStateListener;
private List<Fragment> fragmentList;
private List<String> tabTitleList;
// 新增ServiceConnection用于与MainService绑定并传递窗口状态
private MainServiceConnection mMainServiceConnection;
private boolean mIsServiceBound = false;
// ====================== 6. 接口实现区 ======================
@Override
@@ -124,9 +112,6 @@ public final class MainActivity extends WinBollActivity implements IWinBoLLActiv
LogUtils.d(TAG, "===== onCreate: 主Activity开始创建 =====");
_MainActivity = this;
// 初始化ServiceConnection
mMainServiceConnection = new MainServiceConnection();
// 直接初始化UI原权限检查逻辑注释保留按需启用
initUIAndLogic(savedInstanceState);
LogUtils.d(TAG, "===== onCreate: 主Activity创建流程结束 =====");
@@ -145,15 +130,13 @@ public final class MainActivity extends WinBollActivity implements IWinBoLLActiv
mADsBannerView.resumeADs(MainActivity.this);
LogUtils.d(TAG, "onResume: 广告栏资源已恢复");
}
// 绑定MainService,用于传递窗口状态
bindMainService();
// 移除 MainService 绑定逻辑
}
@Override
protected void onPause() {
super.onPause();
// 解绑MainService,避免内存泄漏
unbindMainService();
// 移除 MainService 解绑逻辑
}
@Override
@@ -165,28 +148,8 @@ public final class MainActivity extends WinBollActivity implements IWinBoLLActiv
mADsBannerView.releaseAdResources();
LogUtils.d(TAG, "onDestroy: 广告栏资源已释放");
}
// 移除电话状态监听,防止内存泄漏
if (telephonyManager != null && phoneStateListener != null) {
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
LogUtils.d(TAG, "onDestroy: 电话状态监听器已移除");
}
// 解绑MainService并通知窗口销毁状态
unbindMainService();
// 最后尝试绑定一次,传递销毁状态(防止解绑后未传递)
final Intent intent = new Intent(this, MainService.class);
bindService(intent, new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
MainService.MyBinder binder = (MainService.MyBinder) service;
binder.setMainWindowDestroyed(true);
unbindService(this);
LogUtils.d(TAG, "onDestroy: 已通知MainService窗口销毁状态");
}
@Override
public void onServiceDisconnected(ComponentName name) {}
}, Context.BIND_AUTO_CREATE);
// 移除电话状态监听释放逻辑(已删除监听初始化,无需释放)
// 移除 MainService 解绑及状态传递逻辑
LogUtils.d(TAG, "===== onDestroy: 主Activity销毁完成 =====");
}
@@ -227,9 +190,7 @@ public final class MainActivity extends WinBollActivity implements IWinBoLLActiv
case REQUEST_OVERLAY_PERMISSION:
handleOverlayPermissionResult();
break;
case REQUEST_CALL_SCREENING_PERMISSION:
handleCallScreeningPermissionResult();
break;
// 移除 通话筛选权限回调(REQUEST_CALL_SCREENING_PERMISSION)分支
default:
LogUtils.w(TAG, "onActivityResult: 未知requestCode=" + requestCode);
break;
@@ -242,7 +203,9 @@ public final class MainActivity extends WinBollActivity implements IWinBoLLActiv
private void handleOverlayPermissionResult() {
if (PermissionUtils.isOverlayPermissionGranted(this)) {
LogUtils.d(TAG, "handleOverlayPermissionResult: 悬浮窗权限申请成功");
checkAndRequestRemainingPermissions();
// 移除 通话筛选权限检查(直接完成权限流程)
LogUtils.d(TAG, "handleOverlayPermissionResult: 所有权限已授予");
initUIAndLogic(null);
} else {
LogUtils.e(TAG, "handleOverlayPermissionResult: 悬浮窗权限申请失败");
showPermissionDeniedDialogAndExit("应用需要悬浮窗权限才能展示来电弹窗,请授予后重新打开应用。");
@@ -250,28 +213,12 @@ public final class MainActivity extends WinBollActivity implements IWinBoLLActiv
}
/**
* 处理通话筛选权限申请结果
*/
private void handleCallScreeningPermissionResult() {
if (PermissionUtils.isCallScreeningPermissionGranted(this)) {
LogUtils.d(TAG, "handleCallScreeningPermissionResult: 通话筛选权限申请成功");
initUIAndLogic(null);
} else {
LogUtils.e(TAG, "handleCallScreeningPermissionResult: 通话筛选权限申请失败");
showPermissionDeniedDialogAndExit("应用需要通话筛选权限监听外拨电话,请授予后重新打开应用。");
}
}
/**
* 检查并申请剩余权限(悬浮窗+通话筛选)
* 检查并申请剩余权限(仅保留悬浮窗,移除通话筛选权限
*/
private void checkAndRequestRemainingPermissions() {
if (!PermissionUtils.isOverlayPermissionGranted(this)) {
LogUtils.d(TAG, "checkAndRequestRemainingPermissions: 悬浮窗权限未授予,跳转设置页");
PermissionUtils.requestOverlayPermission(this, REQUEST_OVERLAY_PERMISSION);
} else if (Build.VERSION.SDK_INT >= ANDROID_10_API && !PermissionUtils.isCallScreeningPermissionGranted(this)) {
LogUtils.d(TAG, "checkAndRequestRemainingPermissions: 通话筛选权限未授予,跳转设置页");
PermissionUtils.requestCallScreeningPermission(this, REQUEST_CALL_SCREENING_PERMISSION);
} else {
LogUtils.d(TAG, "checkAndRequestRemainingPermissions: 所有权限已授予");
initUIAndLogic(null);
@@ -336,13 +283,11 @@ public final class MainActivity extends WinBollActivity implements IWinBoLLActiv
mADsBannerView = (ADsBannerView) findViewById(R.id.adsbanner);
LogUtils.d(TAG, "initUIAndLogic: 广告栏控件初始化完成");
// 4. 主服务初始化
// 4. 主服务初始化(保留启动逻辑,移除绑定相关)
initMainService();
LogUtils.d(TAG, "initUIAndLogic: 主服务初始化完成");
// 5. 电话状态监听初始化
initPhoneStateListener();
LogUtils.d(TAG, "initUIAndLogic: 电话状态监听器初始化完成");
// 5. 移除 电话状态监听初始化逻辑initPhoneStateListener() 调用删除)
// 左边盾值视图初始化Java7分步写法禁止链式调用
DunTemperatureView tempViewLeft = (DunTemperatureView) findViewById(R.id.dun_temp_view_left);
@@ -402,7 +347,7 @@ public final class MainActivity extends WinBollActivity implements IWinBoLLActiv
}
/**
* 初始化主服务(优化:延迟启动,降低主线程压力
* 初始化主服务(保留启动逻辑,移除绑定相关;优化启动方式为静态方法
*/
private void initMainService() {
LogUtils.d(TAG, "initMainService: 开始初始化主服务配置");
@@ -414,13 +359,13 @@ public final class MainActivity extends WinBollActivity implements IWinBoLLActiv
MainServiceBean.saveBean(this, mMainServiceBean);
}
// 检查服务状态并启动
// 检查服务状态并启动(使用静态方法,无绑定依赖)
if (mMainServiceBean.isEnable() && !isServiceRunning(MainService.class)) {
LogUtils.d(TAG, "initMainService: 主服务已启用且未运行延迟1秒启动");
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
MainService.startMainService(MainActivity.this);
MainService.startMainServiceAndSaveStatus(MainActivity.this);
LogUtils.d(TAG, "initMainService: 主服务启动任务执行");
}
}, 1000);
@@ -430,61 +375,7 @@ public final class MainActivity extends WinBollActivity implements IWinBoLLActiv
}
}
/**
* 初始化电话状态监听与通话筛选服务适配API30移除高版本依赖
*/
private void initPhoneStateListener() {
LogUtils.d(TAG, "initPhoneStateListener: 开始初始化电话监听");
telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
phoneStateListener = new MyPhoneStateListener();
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
// API 10+ 启动通话筛选服务(硬编码版本判断)
if (Build.VERSION.SDK_INT >= ANDROID_10_API) {
Intent screeningIntent = new Intent(this, MyCallScreeningService.class);
if (Build.VERSION.SDK_INT >= ANDROID_8_API) {
startForegroundService(screeningIntent);
LogUtils.d(TAG, "initPhoneStateListener: 以前台服务方式启动通话筛选服务");
} else {
startService(screeningIntent);
LogUtils.d(TAG, "initPhoneStateListener: 以普通服务方式启动通话筛选服务");
}
}
LogUtils.d(TAG, "initPhoneStateListener: 电话监听初始化完成");
}
// ====================== 10. MainService绑定/解绑工具方法 ======================
/**
* 绑定MainService用于传递窗口状态
*/
private void bindMainService() {
if (mIsServiceBound) {
return;
}
Intent intent = new Intent(this, MainService.class);
boolean bindSuccess = bindService(intent, mMainServiceConnection, Context.BIND_AUTO_CREATE);
if (bindSuccess) {
mIsServiceBound = true;
LogUtils.d(TAG, "bindMainService: 绑定MainService成功");
} else {
LogUtils.e(TAG, "bindMainService: 绑定MainService失败");
}
}
/**
* 解绑MainService
*/
private void unbindMainService() {
if (mIsServiceBound && mMainServiceConnection != null) {
try {
unbindService(mMainServiceConnection);
mIsServiceBound = false;
LogUtils.d(TAG, "unbindMainService: 解绑MainService成功");
} catch (IllegalArgumentException e) {
LogUtils.w(TAG, "unbindMainService: 服务未绑定,解绑失败", e);
}
}
}
// ====================== 10. 移除 MainService 绑定/解绑工具方法bindMainService/unbindMainService 完全删除) ======================
// ====================== 11. 菜单相关函数区 ======================
@Override
@@ -586,23 +477,8 @@ public final class MainActivity extends WinBollActivity implements IWinBoLLActiv
// ====================== 14. 内部类定义区Java 7 规范禁止Lambda ======================
/**
* MainService连接类,用于传递窗口状态
* 移除 MainServiceConnection 内部类(服务绑定相关,已删除绑定逻辑)
*/
private class MainServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
LogUtils.d(TAG, "MainServiceConnection: 与MainService连接成功");
MainService.MyBinder binder = (MainService.MyBinder) service;
// 通知MainService窗口处于活跃状态
binder.setMainWindowDestroyed(false);
}
@Override
public void onServiceDisconnected(ComponentName name) {
LogUtils.w(TAG, "MainServiceConnection: 与MainService连接断开");
mIsServiceBound = false;
}
}
/**
* ViewPager适配器静态内部类减少内存泄漏风险Java7泛型完整声明
@@ -635,29 +511,7 @@ public final class MainActivity extends WinBollActivity implements IWinBoLLActiv
}
/**
* 电话状态监听器Java7内部类规范写法
* 移除 MyPhoneStateListener 内部类(电话状态监听相关,已删除监听逻辑
*/
private class MyPhoneStateListener extends PhoneStateListener {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
String stateDesc = "";
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
stateDesc = "空闲";
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
stateDesc = "通话中";
break;
case TelephonyManager.CALL_STATE_RINGING:
stateDesc = "来电(" + incomingNumber + ")";
break;
default:
stateDesc = "未知状态(" + state + ")";
break;
}
LogUtils.d(TAG, "onCallStateChanged: 电话状态=" + stateDesc);
}
}
}

View File

@@ -59,7 +59,7 @@ public class MainService extends Service {
private static MainService sMainServiceInstance;
private static volatile TomCat sTomCatInstance;
// ====================== 成员变量区(新增主窗口销毁状态标记) ======================
// ====================== 成员变量区 ======================
private volatile boolean mIsServiceRunning;
private MainServiceBean mMainServiceBean;
private MainServiceThread mMainServiceThread;
@@ -70,24 +70,16 @@ public class MainService extends Service {
private MainReceiver mMainReceiver;
private Timer mStreamVolumeCheckTimer;
private Handler mDelayHandler;
// 核心:标记主窗口是否已销毁,阻断后续无效服务启动
private boolean mIsMainWindowDestroyed = false;
// ====================== Binder 内部类Java 7 规范写法,新增窗口状态设置方法) ======================
// ====================== Binder 内部类 ======================
public class MyBinder extends Binder {
public MainService getService() {
LogUtils.d(TAG, "MyBinder.getService: 获取 MainService 实例");
return MainService.this;
}
// 对外暴露:设置主窗口销毁状态
public void setMainWindowDestroyed(boolean isDestroyed) {
mIsMainWindowDestroyed = isDestroyed;
LogUtils.w(TAG, "MyBinder.setMainWindowDestroyed: 主窗口销毁状态更新为 " + isDestroyed);
}
}
// ====================== ServiceConnection 内部类Java 7 匿名内部类规范) ======================
// ====================== ServiceConnection 内部类 ======================
private class MyServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
@@ -114,8 +106,8 @@ public class MainService extends Service {
mAssistantService = null;
mIsBound = false;
// 新增:主窗口销毁后,不再重试绑定守护服务
if (mMainServiceBean != null && mMainServiceBean.isEnable() && !mIsMainWindowDestroyed) {
// 服务启用则重试绑定
if (mMainServiceBean != null && mMainServiceBean.isEnable()) {
LogUtils.d(TAG, "MyServiceConnection.onServiceDisconnected: 重新唤醒并绑定守护服务");
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
@@ -124,12 +116,12 @@ public class MainService extends Service {
}
}, RETRY_DELAY_MS);
} else {
LogUtils.w(TAG, "MyServiceConnection.onServiceDisconnected: 主窗口已销毁/服务未启用,跳过重试");
LogUtils.w(TAG, "MyServiceConnection.onServiceDisconnected: 服务未启用,跳过重试");
}
}
}
// ====================== 对外静态方法区(强化参数校验,添加日志) ======================
// ====================== 对外静态方法区 ======================
public static boolean isPhoneInBoBullToon(String phone) {
if (sTomCatInstance != null && phone != null && !phone.isEmpty()) {
return sTomCatInstance.isPhoneBoBullToon(phone);
@@ -204,10 +196,9 @@ public class MainService extends Service {
startMainService(context);
}
// ====================== 成员方法区(新增服务启动前置校验 + 延迟启动封装) ======================
// ====================== 成员方法区 ======================
/**
* 补充缺失的 appenMessage 方法
* 用于接收并处理消息,支持日志打印和通过 Handler 转发到主线程
*/
public void appenMessage(String message) {
String msg = message == null ? "null" : message;
@@ -222,17 +213,10 @@ public class MainService extends Service {
}
/**
* 服务启动前置校验(核心:阻断无效启动)
* @param serviceClass 待启动服务类
* @return true=允许启动 false=禁止启动
* 服务启动前置校验
*/
private boolean canStartService(Class<?> serviceClass) {
// 1. 主窗口已销毁 → 禁止启动
if (mIsMainWindowDestroyed) {
LogUtils.w(TAG, "canStartService: 主窗口已销毁,禁止启动 " + serviceClass.getSimpleName());
return false;
}
// 2. 服务未启用/已运行 → 禁止启动
// 服务未启用/已运行 → 禁止启动
if (mMainServiceBean == null || !mMainServiceBean.isEnable()) {
LogUtils.w(TAG, "canStartService: 主服务未启用,禁止启动 " + serviceClass.getSimpleName());
return false;
@@ -241,7 +225,7 @@ public class MainService extends Service {
LogUtils.d(TAG, "canStartService: " + serviceClass.getSimpleName() + " 已运行,跳过启动");
return false;
}
// 3. Android 12+ 应用后台 → 禁止启动非核心服务
// Android 12+ 应用后台 → 禁止启动非核心服务
if (Build.VERSION.SDK_INT >= ANDROID_12_API && !AppForegroundUtils.isAppForeground(this)) {
LogUtils.w(TAG, "canStartService: Android 12+ 应用后台,禁止启动 " + serviceClass.getSimpleName());
return false;
@@ -250,8 +234,7 @@ public class MainService extends Service {
}
/**
* 延迟启动非核心服务(降低主线程负载,避免前台服务超时)
* @param serviceClass 待启动服务类
* 延迟启动非核心服务
*/
private void delayStartNonCoreService(final Class<?> serviceClass) {
if (!canStartService(serviceClass)) {
@@ -276,15 +259,15 @@ public class MainService extends Service {
}
/**
* 创建前台服务通知Java 7 分步构建,强化版本兼容 + 异常防护)
* 创建前台服务通知
*/
private Notification createForegroundNotification() {
// 1. 创建通知渠道Android 8.0+ 必需,添加空指针防护
// 1. 创建通知渠道Android 8.0+ 必需)
if (Build.VERSION.SDK_INT >= ANDROID_8_API) {
NotificationChannel channel = new NotificationChannel(
FOREGROUND_CHANNEL_ID,
"拨号主服务",
NotificationManager.IMPORTANCE_LOW
FOREGROUND_CHANNEL_ID,
"拨号主服务",
NotificationManager.IMPORTANCE_LOW
);
channel.setDescription("主服务后台运行,保障拨号功能正常");
channel.setSound(null, null);
@@ -299,14 +282,13 @@ public class MainService extends Service {
}
}
// 2. 构建通知Java 7 分步设置,禁止链式调用简化)
// 2. 构建通知
Notification.Builder builder;
if (Build.VERSION.SDK_INT >= ANDROID_8_API) {
builder = new Notification.Builder(this, FOREGROUND_CHANNEL_ID);
} else {
builder = new Notification.Builder(this);
}
// 关键:确保图标资源存在,否则通知创建失败导致前台服务启动超时
builder.setSmallIcon(R.drawable.ic_launcher);
builder.setContentTitle("拨号服务运行中");
builder.setContentText("正在后台保障通话监听与号码识别");
@@ -317,14 +299,14 @@ public class MainService extends Service {
}
/**
* 启动通话监听服务(重构:改为延迟启动非核心服务)
* 启动通话监听服务
*/
private void startPhoneCallListener() {
delayStartNonCoreService(CallListenerService.class);
}
/**
* 检查服务是否正在运行(通用工具方法,避免重复代码)
* 检查服务是否正在运行
*/
private boolean isServiceRunning(Class<?> serviceClass) {
if (serviceClass == null) {
@@ -346,7 +328,7 @@ public class MainService extends Service {
return false;
}
// ====================== Service 生命周期方法区(核心优化:优先启动前台服务) ======================
// ====================== Service 生命周期方法区 ======================
@Override
public void onCreate() {
super.onCreate();
@@ -354,38 +336,16 @@ public class MainService extends Service {
sMainServiceInstance = this;
mIsServiceRunning = false;
// ========== 核心优化 1优先启动前台服务放在 onCreate 最前端,避免业务逻辑阻塞导致超时 ==========
try {
Notification foregroundNotification = createForegroundNotification();
if (Build.VERSION.SDK_INT >= ANDROID_10_API) {
startForeground(FOREGROUND_NOTIFICATION_ID, foregroundNotification, FOREGROUND_SERVICE_TYPE_DATA_SYNC);
LogUtils.d(TAG, "onCreate: 主服务已启动为前台服务dataSync 类型API30+");
} else {
startForeground(FOREGROUND_NOTIFICATION_ID, foregroundNotification);
LogUtils.d(TAG, "onCreate: 主服务已启动为前台服务(低版本兼容)");
}
} catch (IllegalArgumentException e) {
LogUtils.e(TAG, "onCreate: 启动前台服务失败,类型不匹配", e);
stopSelf();
return;
} catch (Exception e) {
LogUtils.e(TAG, "onCreate: 启动前台服务异常", e);
stopSelf();
return;
}
// ========== 初始化核心组件 ==========
// 仅初始化核心组件
mMainServiceBean = MainServiceBean.loadBean(this, MainServiceBean.class);
mMyServiceConnection = new MyServiceConnection();
mMainServiceHandler = new MainServiceHandler(this);
mDelayHandler = new Handler(Looper.getMainLooper()); // 初始化延迟 Handler
mDelayHandler = new Handler(Looper.getMainLooper());
// 初始化铃声音量检查定时器
initVolumeCheckTimer();
// 启动主服务核心逻辑
mainService();
LogUtils.d(TAG, "===== onCreate: 主服务创建完成 =====");
LogUtils.d(TAG, "===== onCreate: 主服务创建完成(仅初始化组件) =====");
}
@Override
@@ -397,97 +357,132 @@ public class MainService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
LogUtils.d(TAG, "onStartCommand: 服务被启动 | startId=" + startId);
// 主窗口销毁后,不再执行核心逻辑
if (!mIsMainWindowDestroyed) {
mainService();
}
mainService();
return (mMainServiceBean != null && mMainServiceBean.isEnable()) ? START_STICKY : super.onStartCommand(intent, flags, startId);
}
// ====================== onDestroy强制全量清理不改动 Bean 配置 ======================
@Override
public void onDestroy() {
super.onDestroy();
LogUtils.d(TAG, "===== onDestroy: 主服务开始销毁 =====");
LogUtils.d(TAG, "===== onDestroy: 主服务开始销毁(强制清理所有资源) =====");
// 释放延迟 Handler 资源
// 1. 强制标记服务为未运行
mIsServiceRunning = false;
// 2. 释放延迟 Handler 资源
if (mDelayHandler != null) {
mDelayHandler.removeCallbacksAndMessages(null);
mDelayHandler = null;
}
// 释放定时器资源
// 3. 释放定时器资源
cancelVolumeCheckTimer();
// 仅配置禁用时执行资源释放逻辑
if (mMainServiceBean != null && !mMainServiceBean.isEnable()) {
mIsServiceRunning = false;
// 解除守护服务绑定
if (mIsBound && mMyServiceConnection != null) {
try {
unbindService(mMyServiceConnection);
LogUtils.d(TAG, "onDestroy: 解除守护服务绑定成功");
} catch (IllegalArgumentException e) {
LogUtils.w(TAG, "onDestroy: 解除绑定失败,服务未绑定", e);
}
mIsBound = false;
// 4. 强制解除守护服务绑定
if (mIsBound && mMyServiceConnection != null) {
try {
unbindService(mMyServiceConnection);
LogUtils.d(TAG, "onDestroy: 解除守护服务绑定成功");
} catch (IllegalArgumentException e) {
LogUtils.w(TAG, "onDestroy: 解除绑定失败,服务未绑定", e);
}
// 注销广播接收器
if (mMainReceiver != null) {
mMainReceiver.unregisterAction(this);
mMainReceiver = null;
LogUtils.d(TAG, "onDestroy: 广播接收器已注销");
}
// 停止子服务
if (mMainServiceThread != null) {
mMainServiceThread.setIsExit(true);
mMainServiceThread = null;
}
stopService(new Intent(this, AssistantService.class));
stopService(new Intent(this, CallListenerService.class));
mIsBound = false;
mMyServiceConnection = null;
}
// 清空静态实例,避免内存泄漏
// 5. 强制注销广播接收器
if (mMainReceiver != null) {
mMainReceiver.unregisterAction(this);
mMainReceiver = null;
LogUtils.d(TAG, "onDestroy: 广播接收器已注销");
}
// 6. 强制停止主业务线程
if (mMainServiceThread != null) {
mMainServiceThread.setIsExit(true);
mMainServiceThread = null;
}
// 7. 强制停止所有子服务
stopService(new Intent(this, AssistantService.class));
stopService(new Intent(this, CallListenerService.class));
LogUtils.d(TAG, "onDestroy: 所有子服务已强制停止");
// 8. 清空静态实例,避免内存泄漏(不改动 Bean 配置)
sMainServiceInstance = null;
sTomCatInstance = null;
LogUtils.d(TAG, "===== onDestroy: 主服务销毁完成 =====");
mMainServiceHandler = null;
mAssistantService = null;
mMainServiceBean = null;
LogUtils.d(TAG, "===== onDestroy: 主服务销毁完成资源全清理Bean 配置无改动) =====");
}
// ====================== 核心业务逻辑方法区 ======================
// ====================== 核心业务逻辑:优先判断运行状态 → 再校验配置启用状态 ======================
private void mainService() {
LogUtils.d(TAG, "mainService: 执行核心业务逻辑");
// 重新加载配置,确保使用最新状态
mMainServiceBean = MainServiceBean.loadBean(this, MainServiceBean.class);
if (mMainServiceBean == null || !mMainServiceBean.isEnable() || mIsServiceRunning) {
LogUtils.d(TAG, "mainService: 无需启动 | 配置启用=" + (mMainServiceBean != null && mMainServiceBean.isEnable()) + " | 服务运行中=" + mIsServiceRunning);
// 第一步:优先判断服务是否已运行,已运行则直接退出(不做任何动作)
if (mIsServiceRunning) {
LogUtils.d(TAG, "mainService: 服务已处于运行状态,直接退出");
return;
}
// 标记服务为运行状态
mIsServiceRunning = true;
LogUtils.i(TAG, "mainService: 主服务开始运行");
// 第二步:加载最新配置,校验服务是否启用(未启用则退出)
mMainServiceBean = MainServiceBean.loadBean(this, MainServiceBean.class);
if (mMainServiceBean == null || !mMainServiceBean.isEnable()) {
LogUtils.w(TAG, "mainService: 服务配置未启用/配置加载失败,退出启动流程");
return;
}
// 1. 绑定守护服务(核心服务,立即启动)
// 第三步:配置启用且服务未运行,执行启动流程
mIsServiceRunning = true;
LogUtils.i(TAG, "mainService: 服务未运行且配置已启用,开始启动核心流程");
// 1. 启动前台服务(优先执行,避免超时)
try {
Notification foregroundNotification = createForegroundNotification();
if (Build.VERSION.SDK_INT >= ANDROID_10_API) {
startForeground(FOREGROUND_NOTIFICATION_ID, foregroundNotification, FOREGROUND_SERVICE_TYPE_DATA_SYNC);
LogUtils.d(TAG, "mainService: 主服务已启动为前台服务dataSync 类型API30+");
} else {
startForeground(FOREGROUND_NOTIFICATION_ID, foregroundNotification);
LogUtils.d(TAG, "mainService: 主服务已启动为前台服务(低版本兼容)");
}
} catch (IllegalArgumentException e) {
LogUtils.e(TAG, "mainService: 启动前台服务失败,类型不匹配", e);
mIsServiceRunning = false;
stopSelf();
return;
} catch (Exception e) {
LogUtils.e(TAG, "mainService: 启动前台服务异常", e);
mIsServiceRunning = false;
stopSelf();
return;
}
// 2. 绑定守护服务
wakeupAndBindAssistant();
// 2. 初始化业务组件
// 3. 初始化业务组件
initTomCat();
initMainReceiver();
Rules.getInstance(this).loadRules();
LogUtils.d(TAG, "mainService: 黑白名单规则已加载");
// 3. 延迟启动话监听服务(非核心服务,降低主线程负载)
// 4. 启动话监听服务
startPhoneCallListener();
// 4. 启动主业务线程
// 5. 启动主业务线程
mMainServiceThread = MainServiceThread.getInstance(this, mMainServiceHandler);
mMainServiceThread.start();
LogUtils.i(TAG, "mainService: 主业务线程已启动");
LogUtils.i(TAG, "mainService: 核心流程启动完成,主服务正常运行");
}
private void wakeupAndBindAssistant() {
if (mMyServiceConnection == null || mIsMainWindowDestroyed) {
LogUtils.e(TAG, "wakeupAndBindAssistant: 初始化失败/主窗口已销毁,绑定失败");
if (mMyServiceConnection == null) {
LogUtils.e(TAG, "wakeupAndBindAssistant: 初始化失败,绑定失败");
return;
}
Intent intent = new Intent(this, AssistantService.class);
@@ -529,7 +524,7 @@ public class MainService extends Service {
LogUtils.d(TAG, "checkAndRestoreRingerVolume: 铃音配置未存在,已初始化默认配置");
}
// 检查并恢复音量,添加权限异常捕获
// 检查并恢复音量
try {
int currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_RING);
int configVolume = ringTongBean.getStreamVolume();