feat(GPS): 添加空转GPS模拟服务与动态源切换逻辑

1. 新增IdleGpsService,在空转模式下定时发送模拟GPS坐标(默认北京)
2. LocationActivity支持动态切换GPS源:空转时使用IdleGpsService,正常时使用MainService
3. 优化onResume逻辑,确保空转状态变更时GPS监听源实时同步
4. 统一反注册逻辑,避免多服务监听冲突
This commit is contained in:
2026-05-03 16:49:59 +08:00
parent f9ef5ab16e
commit 173290333d
2 changed files with 148 additions and 6 deletions

View File

@@ -25,6 +25,7 @@ import cc.winboll.studio.positions.MainActivity;
import cc.winboll.studio.positions.R;
import cc.winboll.studio.positions.adapters.PositionAdapter;
import cc.winboll.studio.positions.models.PositionModel;
import cc.winboll.studio.positions.services.IdleGpsService;
import cc.winboll.studio.positions.services.MainService;
import java.text.SimpleDateFormat;
@@ -340,17 +341,38 @@ public class LocationActivity extends WinBoLLActivity implements IWinBoLLActivit
};
}
/**
* 刷新GPS监听源根据空转状态自动切换
*/
private void refreshGpsListener() {
LogUtils.d(TAG, "refreshGpsListener invoke");
// 统一注销旧监听(防止重复注册)
IdleGpsService.getInstance().unregisterGpsUpdateListener(mGpsUpdateListener);
if (mMainService != null) {
try { mMainService.unregisterGpsUpdateListener(mGpsUpdateListener); } catch (Exception e) {}
}
// 重新注册正确的监听
registerGpsListener();
}
/**
* 注册GPS监听
*/
private void registerGpsListener() {
LogUtils.d(TAG, "registerGpsListener invoke");
if (isFinishing() || isDestroyed() || mMainService == null || mGpsUpdateListener == null) {
if (isFinishing() || isDestroyed() || mGpsUpdateListener == null) {
return;
}
try {
mMainService.registerGpsUpdateListener(mGpsUpdateListener);
LogUtils.d(TAG, "GPS监听注册成功");
if (App.isAppIdleRunning()) {
IdleGpsService.getInstance().registerGpsUpdateListener(mGpsUpdateListener);
LogUtils.d(TAG, "空转GPS监听注册成功");
} else {
if (mMainService != null) {
mMainService.registerGpsUpdateListener(mGpsUpdateListener);
LogUtils.d(TAG, "系统GPS监听注册成功");
}
}
} catch (final Exception e) {
LogUtils.e(TAG, "GPS注册异常 : " + e.getMessage());
}
@@ -361,12 +383,20 @@ public class LocationActivity extends WinBoLLActivity implements IWinBoLLActivit
*/
private void unregisterGpsListener() {
LogUtils.d(TAG, "unregisterGpsListener invoke");
if (mMainService == null || mGpsUpdateListener == null) {
if (mGpsUpdateListener == null) {
return;
}
try {
mMainService.unregisterGpsUpdateListener(mGpsUpdateListener);
LogUtils.d(TAG, "GPS监听反注册成功");
// 尝试从空转服务注销
IdleGpsService.getInstance().unregisterGpsUpdateListener(mGpsUpdateListener);
} catch (Exception e) {
// ignore
}
try {
// 尝试从主服务注销
if (mMainService != null) {
mMainService.unregisterGpsUpdateListener(mGpsUpdateListener);
}
} catch (final Exception e) {
LogUtils.e(TAG, "GPS反注册异常 : " + e.getMessage());
}
@@ -404,6 +434,7 @@ public class LocationActivity extends WinBoLLActivity implements IWinBoLLActivit
super.onResume();
LogUtils.d(TAG, "onResume invoke");
refreshIdleStatusTitle();
refreshGpsListener(); // 根据当前空转状态刷新GPS源
if (isServiceBound.get() && mMainService != null && !isAdapterInited.get()) {
syncDataFromMainService();

View File

@@ -0,0 +1,111 @@
package cc.winboll.studio.positions.services;
import android.os.Handler;
import android.os.Looper;
import cc.winboll.studio.positions.models.PositionModel;
import java.util.ArrayList;
import java.util.List;
/**
* 空转GPS模拟服务
* 在应用空转模式下模拟系统GPS服务向客户端发送坐标数据
*/
public class IdleGpsService {
private static final long MOCK_INTERVAL_MS = 1000; // 模拟坐标更新间隔
private static IdleGpsService instance;
private final List<MainService.GpsUpdateListener> listeners = new ArrayList<>();
private final Handler handler;
private final Runnable updateRunnable;
private final PositionModel mockPosition;
private boolean isRunning;
private IdleGpsService() {
handler = new Handler(Looper.getMainLooper());
mockPosition = new PositionModel();
mockPosition.setPositionId("mock_idle_pos");
mockPosition.setMemo("空转模拟坐标");
// 默认模拟坐标:北京
mockPosition.setLatitude(39.9042);
mockPosition.setLongitude(116.4074);
updateRunnable = new Runnable() {
@Override
public void run() {
if (isRunning) {
notifyListeners(mockPosition);
handler.postDelayed(this, MOCK_INTERVAL_MS);
}
}
};
}
public static IdleGpsService getInstance() {
if (instance == null) {
instance = new IdleGpsService();
}
return instance;
}
/**
* 注册GPS监听
*/
public void registerGpsUpdateListener(MainService.GpsUpdateListener listener) {
synchronized (listeners) {
if (!listeners.contains(listener)) {
listeners.add(listener);
}
}
if (!isRunning) {
startMockUpdate();
}
}
/**
* 注销GPS监听
*/
public void unregisterGpsUpdateListener(MainService.GpsUpdateListener listener) {
synchronized (listeners) {
listeners.remove(listener);
}
if (listeners.isEmpty() && isRunning) {
stopMockUpdate();
}
}
private void startMockUpdate() {
if (isRunning) return;
isRunning = true;
// 通知状态变更
notifyStatusChange("空转GPS服务已启动");
handler.post(updateRunnable);
}
private void stopMockUpdate() {
isRunning = false;
handler.removeCallbacks(updateRunnable);
notifyStatusChange("空转GPS服务已停止");
}
private void notifyListeners(PositionModel pos) {
synchronized (listeners) {
for (MainService.GpsUpdateListener listener : listeners) {
listener.onGpsPositionUpdated(pos);
}
}
}
private void notifyStatusChange(String status) {
synchronized (listeners) {
for (MainService.GpsUpdateListener listener : listeners) {
listener.onGpsStatusChanged(status);
}
}
}
public boolean isRunning() {
return isRunning;
}
}