优化运动状态检测模块,运动状态检测阈值标准未测定。
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
#Created by .winboll/winboll_app_build.gradle
|
#Created by .winboll/winboll_app_build.gradle
|
||||||
#Tue Nov 04 12:54:59 GMT 2025
|
#Wed Nov 05 08:47:36 GMT 2025
|
||||||
stageCount=18
|
stageCount=18
|
||||||
libraryProject=
|
libraryProject=
|
||||||
baseVersion=15.0
|
baseVersion=15.0
|
||||||
publishVersion=15.0.17
|
publishVersion=15.0.17
|
||||||
buildCount=20
|
buildCount=29
|
||||||
baseBetaVersion=15.0.18
|
baseBetaVersion=15.0.18
|
||||||
|
|||||||
@@ -3,13 +3,12 @@ package cc.winboll.studio.positions.services;
|
|||||||
/**
|
/**
|
||||||
* @Author ZhanGSKen<zhangsken@qq.com>
|
* @Author ZhanGSKen<zhangsken@qq.com>
|
||||||
* @Date 2024/07/19 14:30:57
|
* @Date 2024/07/19 14:30:57
|
||||||
* @Describe 应用主要服务组件类(适配运动状态GPS控制)
|
* @Describe 应用主要服务组件类(适配运动状态GPS控制+静止10秒切换)
|
||||||
*/
|
*/
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
|
||||||
import android.content.ServiceConnection;
|
import android.content.ServiceConnection;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.location.Location;
|
import android.location.Location;
|
||||||
@@ -25,7 +24,6 @@ import cc.winboll.studio.libappbase.LogUtils;
|
|||||||
import cc.winboll.studio.libappbase.ToastUtils;
|
import cc.winboll.studio.libappbase.ToastUtils;
|
||||||
import cc.winboll.studio.positions.models.PositionModel;
|
import cc.winboll.studio.positions.models.PositionModel;
|
||||||
import cc.winboll.studio.positions.models.PositionTaskModel;
|
import cc.winboll.studio.positions.models.PositionTaskModel;
|
||||||
import cc.winboll.studio.positions.receivers.MotionStatusReceiver;
|
|
||||||
import cc.winboll.studio.positions.utils.AppConfigsUtil;
|
import cc.winboll.studio.positions.utils.AppConfigsUtil;
|
||||||
import cc.winboll.studio.positions.utils.DistanceCalculatorUtil;
|
import cc.winboll.studio.positions.utils.DistanceCalculatorUtil;
|
||||||
import cc.winboll.studio.positions.utils.NotificationUtil;
|
import cc.winboll.studio.positions.utils.NotificationUtil;
|
||||||
@@ -38,83 +36,125 @@ import java.util.Set;
|
|||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import cc.winboll.studio.positions.utils.LocalMotionDetector;
|
||||||
|
|
||||||
public class MainService extends Service {
|
public class MainService extends Service implements LocalMotionDetector.MotionStatusCallback {
|
||||||
|
|
||||||
public static final String TAG = "MainService";
|
public static final String TAG = "MainService";
|
||||||
public static final String EXTRA_IS_SETTING_TO_ENABLE = "EXTRA_IS_SETTING_TO_ENABLE";
|
public static final String EXTRA_IS_SETTING_TO_ENABLE = "EXTRA_IS_SETTING_TO_ENABLE";
|
||||||
|
|
||||||
// ---------------------- 定时器相关变量 ----------------------
|
// ---------------------- 核心:LocalMotionDetector 实例(唯一运动状态检测工具) ----------------------
|
||||||
// 静止时GPS定时任务变量(Java 7 显式声明)
|
private LocalMotionDetector mMotionDetector; // 本地运动状态检测器
|
||||||
private ScheduledExecutorService gpsStaticTimer; // 静止时GPS定时获取线程池
|
private static final long GPS_STATIC_INTERVAL = 30; // 静止时GPS间隔(30秒)
|
||||||
private volatile boolean isGpsListening = false; // GPS是否处于持续监听状态
|
|
||||||
private static final long GPS_STATIC_DURATION = 3; // 静止时GPS单次获取超时时间(秒)
|
|
||||||
|
|
||||||
// GPS监听接口(Java 7 标准接口定义)
|
// ---------------------- 定时器相关变量 ----------------------
|
||||||
|
private ScheduledExecutorService gpsStaticTimer; // 静止时GPS定时任务
|
||||||
|
private volatile boolean isGpsListening = false; // GPS是否持续监听
|
||||||
|
private static final long GPS_STATIC_DURATION = 3; // 单次GPS获取超时(秒)
|
||||||
|
|
||||||
|
// ---------------------- 静止延迟切换配置(核心功能) ----------------------
|
||||||
|
private static final long STATIC_DELAY_MS = 10 * 1000; // 静止10秒后切换
|
||||||
|
private Handler staticDelayHandler; // 延迟执行切换逻辑的Handler
|
||||||
|
private volatile boolean isDelaySwitching = false; // 标记是否正在等待延迟切换
|
||||||
|
|
||||||
|
// GPS监听接口
|
||||||
public interface GpsUpdateListener {
|
public interface GpsUpdateListener {
|
||||||
void onGpsPositionUpdated(PositionModel currentGpsPos);
|
void onGpsPositionUpdated(PositionModel currentGpsPos);
|
||||||
void onGpsStatusChanged(String status);
|
void onGpsStatusChanged(String status);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 任务更新监听接口(Java 7 风格)
|
// 任务更新监听接口
|
||||||
public interface TaskUpdateListener {
|
public interface TaskUpdateListener {
|
||||||
void onTaskUpdated();
|
void onTaskUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 监听管理(弱引用+线程安全集合,适配Java 7)
|
// 监听管理
|
||||||
private final Set<WeakReference<GpsUpdateListener>> mGpsListeners = new HashSet<WeakReference<GpsUpdateListener>>();
|
private final Set<WeakReference<GpsUpdateListener>> mGpsListeners = new HashSet<WeakReference<GpsUpdateListener>>();
|
||||||
private final Set<WeakReference<TaskUpdateListener>> mTaskListeners = new HashSet<WeakReference<TaskUpdateListener>>();
|
private final Set<WeakReference<TaskUpdateListener>> mTaskListeners = new HashSet<WeakReference<TaskUpdateListener>>();
|
||||||
private final Object mListenerLock = new Object(); // 监听操作锁
|
private final Object mListenerLock = new Object();
|
||||||
|
|
||||||
// 原有核心变量(Java 7 显式初始化)
|
// 原有核心变量
|
||||||
private LocalBinder mLocalBinder; // 持有 LocalBinder 实例
|
private LocalBinder mLocalBinder;
|
||||||
private LocationManager mLocationManager;
|
private LocationManager mLocationManager;
|
||||||
private LocationListener mGpsLocationListener;
|
private LocationListener mGpsLocationListener;
|
||||||
private static final long GPS_UPDATE_INTERVAL = 2000; // GPS更新间隔:2秒
|
private static final long GPS_UPDATE_INTERVAL = 2000; // 实时GPS更新间隔:2秒
|
||||||
private static final float GPS_UPDATE_DISTANCE = 1; // GPS更新距离阈值:1米
|
private static final float GPS_UPDATE_DISTANCE = 1; // 实时GPS更新距离:1米
|
||||||
private boolean isGpsEnabled = false; // GPS是否启用标记
|
private boolean isGpsEnabled = false;
|
||||||
private boolean isGpsPermissionGranted = false; // 定位权限是否授予标记
|
private boolean isGpsPermissionGranted = false;
|
||||||
|
|
||||||
// 数据存储集合(Java 7 基础集合)
|
// 数据存储集合
|
||||||
private final ArrayList<PositionModel> mPositionList = new ArrayList<PositionModel>(); // 位置数据列表
|
private final ArrayList<PositionModel> mPositionList = new ArrayList<PositionModel>();
|
||||||
private final ArrayList<PositionTaskModel> mAllTasks = new ArrayList<PositionTaskModel>();// 任务数据列表
|
private final ArrayList<PositionTaskModel> mAllTasks = new ArrayList<PositionTaskModel>();
|
||||||
private static PositionModel _mCurrentGpsPosition; // 当前GPS定位数据
|
private static PositionModel _mCurrentGpsPosition;
|
||||||
|
|
||||||
// 服务相关变量(Java 7 显式声明)
|
// 服务相关变量
|
||||||
MyServiceConnection mMyServiceConnection;
|
MyServiceConnection mMyServiceConnection;
|
||||||
volatile static boolean _mIsServiceRunning; // 服务运行状态(volatile保证可见性)
|
volatile static boolean _mIsServiceRunning;
|
||||||
AppConfigsUtil mAppConfigsUtil;
|
AppConfigsUtil mAppConfigsUtil;
|
||||||
private ScheduledExecutorService distanceExecutor = Executors.newSingleThreadScheduledExecutor(); // 距离计算线程池
|
private ScheduledExecutorService distanceExecutor = Executors.newSingleThreadScheduledExecutor();
|
||||||
private final Set<String> mVisiblePositionIds = new HashSet<String>(); // 可见位置ID集合
|
private final Set<String> mVisiblePositionIds = new HashSet<String>();
|
||||||
|
|
||||||
// 单例+应用上下文(Java 7 静态变量)
|
// 单例+应用上下文
|
||||||
private static volatile MainService sInstance;
|
private static volatile MainService sInstance;
|
||||||
private static Context sAppContext;
|
private static Context sAppContext;
|
||||||
|
|
||||||
// 核心:运动状态Receiver(动态注册/注销,Java 7 显式声明)
|
|
||||||
private MotionStatusReceiver mMotionStatusReceiver;
|
// =========================================================================
|
||||||
private IntentFilter mMotionStatusFilter;
|
// 核心:运动状态回调(仅通过LocalMotionDetector触发,低运动归类为静止)
|
||||||
|
// =========================================================================
|
||||||
|
@Override
|
||||||
|
public void onMotionStatusChanged(boolean isWalking, String statusDesc) {
|
||||||
|
LogUtils.d(TAG, "运动状态回调:" + statusDesc + "(isWalking=" + isWalking + ")");
|
||||||
|
updateNotificationGpsStatus("当前状态:" + statusDesc);
|
||||||
|
|
||||||
|
// 仅行走状态切实时GPS,非行走(静止+低运动)统一按静止处理
|
||||||
|
if (isWalking) {
|
||||||
|
// 行走状态:立即切回实时GPS(取消未执行的延迟任务)
|
||||||
|
if (staticDelayHandler != null) {
|
||||||
|
staticDelayHandler.removeCallbacksAndMessages(null); // 清空延迟任务
|
||||||
|
isDelaySwitching = false; // 重置标记
|
||||||
|
}
|
||||||
|
stopGpsStaticTimer(); // 停止定时GPS
|
||||||
|
startGpsLocation(); // 启动实时GPS
|
||||||
|
LogUtils.d(TAG, "行走状态:已切换为实时GPS(2秒/1米)");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// 非行走状态:延迟10秒切换为定时GPS
|
||||||
|
if (isGpsListening && !isDelaySwitching) { // 仅实时GPS运行且无延迟任务时触发
|
||||||
|
isDelaySwitching = true;
|
||||||
|
staticDelayHandler.postDelayed(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
stopGpsLocation(); // 停止实时GPS
|
||||||
|
startGpsStaticTimer(GPS_STATIC_INTERVAL); // 启动30秒定时GPS
|
||||||
|
LogUtils.d(TAG, "静止/低运动10秒:已切换为30秒定时GPS");
|
||||||
|
isDelaySwitching = false; // 重置标记
|
||||||
|
}
|
||||||
|
}, STATIC_DELAY_MS);
|
||||||
|
LogUtils.d(TAG, "检测到静止/低运动:将在10秒后切换为定时GPS(若持续非行走)");
|
||||||
|
}
|
||||||
|
LogUtils.d(TAG, "静止/低运动状态:等待延迟切换GPS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// 静止GPS定时任务方法(Java 7 语法)
|
// 静止GPS定时任务方法(适配Java7)
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// 启动静止时GPS定时获取
|
// 启动静止时GPS定时获取(间隔:秒)
|
||||||
public void startGpsStaticTimer(long interval) {
|
public void startGpsStaticTimer(long intervalSeconds) {
|
||||||
// 先销毁旧定时器(避免重复创建)
|
|
||||||
stopGpsStaticTimer();
|
stopGpsStaticTimer();
|
||||||
|
|
||||||
// 创建单线程定时器
|
|
||||||
gpsStaticTimer = Executors.newSingleThreadScheduledExecutor();
|
gpsStaticTimer = Executors.newSingleThreadScheduledExecutor();
|
||||||
gpsStaticTimer.scheduleAtFixedRate(new Runnable() {
|
gpsStaticTimer.scheduleAtFixedRate(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
LogUtils.d(TAG, "静止时GPS定时任务触发:开始单次GPS获取");
|
LogUtils.d(TAG, "静止时GPS定时任务触发:开始单次GPS获取");
|
||||||
startSingleGpsRetrieve(); // 单次GPS获取
|
startSingleGpsRetrieve();
|
||||||
}
|
}
|
||||||
}, 0, interval, TimeUnit.MINUTES); // 立即执行第一次,之后按间隔执行
|
}, 0, intervalSeconds, TimeUnit.SECONDS);
|
||||||
|
|
||||||
LogUtils.d(TAG, "静止时GPS定时任务已启动(间隔:" + interval + "分钟)");
|
LogUtils.d(TAG, "静止时GPS定时任务已启动(间隔:" + intervalSeconds + "秒)");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 停止静止时GPS定时任务
|
// 停止静止时GPS定时任务
|
||||||
@@ -135,7 +175,7 @@ public class MainService extends Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 单次GPS获取(获取后关闭监听,Java 7 匿名内部类)
|
// 单次GPS获取(获取后关闭监听)
|
||||||
private void startSingleGpsRetrieve() {
|
private void startSingleGpsRetrieve() {
|
||||||
if (!checkGpsReady()) {
|
if (!checkGpsReady()) {
|
||||||
LogUtils.w(TAG, "单次GPS获取:GPS未就绪,跳过");
|
LogUtils.w(TAG, "单次GPS获取:GPS未就绪,跳过");
|
||||||
@@ -143,13 +183,11 @@ public class MainService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 注册临时GPS监听(仅获取一次位置)
|
|
||||||
mLocationManager.requestSingleUpdate(
|
mLocationManager.requestSingleUpdate(
|
||||||
LocationManager.GPS_PROVIDER,
|
LocationManager.GPS_PROVIDER,
|
||||||
new LocationListener() {
|
new LocationListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onLocationChanged(Location location) {
|
public void onLocationChanged(Location location) {
|
||||||
// 获取到位置:同步数据+关闭监听
|
|
||||||
if (location != null) {
|
if (location != null) {
|
||||||
PositionModel gpsPos = new PositionModel();
|
PositionModel gpsPos = new PositionModel();
|
||||||
gpsPos.setLatitude(location.getLatitude());
|
gpsPos.setLatitude(location.getLatitude());
|
||||||
@@ -159,7 +197,6 @@ public class MainService extends Service {
|
|||||||
syncCurrentGpsPosition(gpsPos);
|
syncCurrentGpsPosition(gpsPos);
|
||||||
LogUtils.d(TAG, "单次GPS获取成功:纬度=" + location.getLatitude());
|
LogUtils.d(TAG, "单次GPS获取成功:纬度=" + location.getLatitude());
|
||||||
}
|
}
|
||||||
// 移除监听(避免内存泄漏)
|
|
||||||
mLocationManager.removeUpdates(this);
|
mLocationManager.removeUpdates(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,24 +208,23 @@ public class MainService extends Service {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onProviderDisabled(String provider) {
|
public void onProviderDisabled(String provider) {
|
||||||
mLocationManager.removeUpdates(this); // 禁用时移除监听
|
mLocationManager.removeUpdates(this);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Looper.getMainLooper()
|
Looper.getMainLooper()
|
||||||
);
|
);
|
||||||
|
|
||||||
// 超时处理:指定时间内未获取则强制关闭
|
// 超时处理
|
||||||
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
|
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
// 移除所有临时监听
|
|
||||||
mLocationManager.removeUpdates(new LocationListener() {
|
mLocationManager.removeUpdates(new LocationListener() {
|
||||||
@Override public void onLocationChanged(Location location) {}
|
@Override public void onLocationChanged(Location location) {}
|
||||||
@Override public void onStatusChanged(String provider, int status, Bundle extras) {}
|
@Override public void onStatusChanged(String provider, int status, Bundle extras) {}
|
||||||
@Override public void onProviderEnabled(String provider) {}
|
@Override public void onProviderEnabled(String provider) {}
|
||||||
@Override public void onProviderDisabled(String provider) {}
|
@Override public void onProviderDisabled(String provider) {}
|
||||||
});
|
});
|
||||||
LogUtils.d(TAG, "单次GPS获取超时(" + GPS_STATIC_DURATION + "秒),已强制关闭监听");
|
LogUtils.d(TAG, "单次GPS获取超时(" + GPS_STATIC_DURATION + "秒)");
|
||||||
}
|
}
|
||||||
}, GPS_STATIC_DURATION * 1000);
|
}, GPS_STATIC_DURATION * 1000);
|
||||||
|
|
||||||
@@ -201,7 +237,7 @@ public class MainService extends Service {
|
|||||||
|
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// 任务操作核心接口(Java 7 实现)
|
// 任务操作核心接口
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
public void addTask(PositionTaskModel newTask) {
|
public void addTask(PositionTaskModel newTask) {
|
||||||
if (newTask == null || TextUtils.isEmpty(newTask.getPositionId())) {
|
if (newTask == null || TextUtils.isEmpty(newTask.getPositionId())) {
|
||||||
@@ -209,7 +245,6 @@ public class MainService extends Service {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 任务去重(Java 7 迭代器遍历)
|
|
||||||
boolean isDuplicate = false;
|
boolean isDuplicate = false;
|
||||||
Iterator<PositionTaskModel> taskIter = mAllTasks.iterator();
|
Iterator<PositionTaskModel> taskIter = mAllTasks.iterator();
|
||||||
while (taskIter.hasNext()) {
|
while (taskIter.hasNext()) {
|
||||||
@@ -236,7 +271,6 @@ public class MainService extends Service {
|
|||||||
return posTasks;
|
return posTasks;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 筛选任务(Java 7 迭代器遍历)
|
|
||||||
Iterator<PositionTaskModel> taskIter = mAllTasks.iterator();
|
Iterator<PositionTaskModel> taskIter = mAllTasks.iterator();
|
||||||
while (taskIter.hasNext()) {
|
while (taskIter.hasNext()) {
|
||||||
PositionTaskModel task = taskIter.next();
|
PositionTaskModel task = taskIter.next();
|
||||||
@@ -280,7 +314,6 @@ public class MainService extends Service {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 迭代器删除(Java 7 安全方式)
|
|
||||||
Iterator<PositionTaskModel> taskIter = mAllTasks.iterator();
|
Iterator<PositionTaskModel> taskIter = mAllTasks.iterator();
|
||||||
while (taskIter.hasNext()) {
|
while (taskIter.hasNext()) {
|
||||||
PositionTaskModel task = taskIter.next();
|
PositionTaskModel task = taskIter.next();
|
||||||
@@ -326,7 +359,6 @@ public class MainService extends Service {
|
|||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
final WeakReference<TaskUpdateListener> ref = iter.next();
|
final WeakReference<TaskUpdateListener> ref = iter.next();
|
||||||
if (ref.get() != null) {
|
if (ref.get() != null) {
|
||||||
// 主线程判断+切换(Java 7 匿名Runnable)
|
|
||||||
if (Looper.myLooper() == Looper.getMainLooper()) {
|
if (Looper.myLooper() == Looper.getMainLooper()) {
|
||||||
ref.get().onTaskUpdated();
|
ref.get().onTaskUpdated();
|
||||||
} else {
|
} else {
|
||||||
@@ -338,7 +370,7 @@ public class MainService extends Service {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
iter.remove(); // 清理已回收弱引用
|
iter.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -346,7 +378,7 @@ public class MainService extends Service {
|
|||||||
|
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// 服务基础方法(核心调整:动态注册/注销MotionStatusReceiver)
|
// 服务基础方法(初始化LocalMotionDetector,删除Receiver相关逻辑)
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
public static synchronized MainService getInstance(Context context) {
|
public static synchronized MainService getInstance(Context context) {
|
||||||
if (sInstance == null) {
|
if (sInstance == null) {
|
||||||
@@ -364,7 +396,7 @@ public class MainService extends Service {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBinder onBind(Intent intent) {
|
public IBinder onBind(Intent intent) {
|
||||||
return mLocalBinder; // 返回LocalBinder暴露服务
|
return mLocalBinder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -374,31 +406,29 @@ public class MainService extends Service {
|
|||||||
sInstance = this;
|
sInstance = this;
|
||||||
sAppContext = getApplicationContext();
|
sAppContext = getApplicationContext();
|
||||||
|
|
||||||
// 初始化LocalBinder
|
|
||||||
mLocalBinder = new LocalBinder(this);
|
mLocalBinder = new LocalBinder(this);
|
||||||
|
|
||||||
_mIsServiceRunning = false;
|
_mIsServiceRunning = false;
|
||||||
mAppConfigsUtil = AppConfigsUtil.getInstance(this);
|
mAppConfigsUtil = AppConfigsUtil.getInstance(this);
|
||||||
|
|
||||||
// 初始化服务连接
|
|
||||||
if (mMyServiceConnection == null) {
|
if (mMyServiceConnection == null) {
|
||||||
mMyServiceConnection = new MyServiceConnection();
|
mMyServiceConnection = new MyServiceConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化GPS监听(仅初始化,不启动)
|
// 初始化:LocalMotionDetector+延迟切换Handler(Java7兼容)
|
||||||
//initGpsLocationListener();
|
mMotionDetector = LocalMotionDetector.getInstance();
|
||||||
|
staticDelayHandler = new Handler(Looper.getMainLooper());
|
||||||
|
|
||||||
if (mAppConfigsUtil.isEnableMainService(true)) {
|
if (mAppConfigsUtil.isEnableMainService(true)) {
|
||||||
run(); // 启动服务核心逻辑
|
run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 服务核心运行方法(调整:启动服务时仅注册Receiver,不启动GPS)
|
// 服务核心运行方法(删除Receiver注册逻辑)
|
||||||
public void run() {
|
public void run() {
|
||||||
if (mAppConfigsUtil.isEnableMainService(true)) {
|
if (mAppConfigsUtil.isEnableMainService(true)) {
|
||||||
if (!_mIsServiceRunning) {
|
if (!_mIsServiceRunning) {
|
||||||
_mIsServiceRunning = true;
|
_mIsServiceRunning = true;
|
||||||
wakeupAndBindAssistant(); // 唤醒并绑定辅助服务
|
wakeupAndBindAssistant();
|
||||||
|
|
||||||
// 启动前台服务
|
// 启动前台服务
|
||||||
String initialStatus = "[ Positions ] is in Service.";
|
String initialStatus = "[ Positions ] is in Service.";
|
||||||
@@ -406,23 +436,15 @@ public class MainService extends Service {
|
|||||||
startForeground(NotificationUtil.FOREGROUND_SERVICE_NOTIFICATION_ID,
|
startForeground(NotificationUtil.FOREGROUND_SERVICE_NOTIFICATION_ID,
|
||||||
NotificationUtil.createForegroundServiceNotification(this, initialStatus));
|
NotificationUtil.createForegroundServiceNotification(this, initialStatus));
|
||||||
|
|
||||||
// 初始化LocationManager(仅初始化,不启动GPS)
|
// 初始化LocationManager
|
||||||
mLocationManager = (LocationManager) sInstance.getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
|
mLocationManager = (LocationManager) sInstance.getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
|
||||||
|
|
||||||
// 加载本地数据
|
// 加载本地数据
|
||||||
PositionModel.loadBeanList(MainService.this, mPositionList, PositionModel.class);
|
PositionModel.loadBeanList(MainService.this, mPositionList, PositionModel.class);
|
||||||
PositionTaskModel.loadBeanList(MainService.this, mAllTasks, PositionTaskModel.class);
|
PositionTaskModel.loadBeanList(MainService.this, mAllTasks, PositionTaskModel.class);
|
||||||
|
|
||||||
// 初始化运动状态Receiver(动态注册准备)
|
// 核心:启动LocalMotionDetector监测(唯一运动状态来源)
|
||||||
initMotionStatusReceiver();
|
mMotionDetector.startDetection(this, this);
|
||||||
|
|
||||||
// 动态注册MotionStatusReceiver(核心:交给Receiver控制GPS)
|
|
||||||
registerMotionStatusReceiver();
|
|
||||||
|
|
||||||
Intent triggerIntent = new Intent(MotionStatusReceiver.ACTION_MOTION_STATUS_RECEIVER);
|
|
||||||
triggerIntent.putExtra(MotionStatusReceiver.EXTRA_SENSORS_ENABLE, true);
|
|
||||||
sendBroadcast(triggerIntent);
|
|
||||||
LogUtils.d(TAG, "已发送自主触发广播,唤醒MotionStatusReceiver");
|
|
||||||
|
|
||||||
// 提示与日志
|
// 提示与日志
|
||||||
ToastUtils.show(initialStatus);
|
ToastUtils.show(initialStatus);
|
||||||
@@ -431,45 +453,6 @@ public class MainService extends Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化运动状态Receiver和IntentFilter
|
|
||||||
private void initMotionStatusReceiver() {
|
|
||||||
LogUtils.d(TAG, "initMotionStatusReceiver()");
|
|
||||||
mMotionStatusReceiver = new MotionStatusReceiver();
|
|
||||||
mMotionStatusFilter = new IntentFilter();
|
|
||||||
mMotionStatusFilter.addAction(MotionStatusReceiver.ACTION_MOTION_STATUS_RECEIVER);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 动态注册MotionStatusReceiver
|
|
||||||
private void registerMotionStatusReceiver() {
|
|
||||||
LogUtils.d(TAG, "registerMotionStatusReceiver()");
|
|
||||||
if (mMotionStatusReceiver != null && mMotionStatusFilter != null) {
|
|
||||||
try {
|
|
||||||
registerReceiver(mMotionStatusReceiver, mMotionStatusFilter);
|
|
||||||
LogUtils.d(TAG, "MotionStatusReceiver 动态注册成功");
|
|
||||||
} catch (Exception e) {
|
|
||||||
LogUtils.e(TAG, "MotionStatusReceiver 注册失败:" + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// 动态注销MotionStatusReceiver
|
|
||||||
//
|
|
||||||
private void unregisterMotionStatusReceiver() {
|
|
||||||
if (mMotionStatusReceiver != null) {
|
|
||||||
try {
|
|
||||||
unregisterReceiver(mMotionStatusReceiver);
|
|
||||||
mMotionStatusReceiver.forceCleanResources(); // 新增:强制清理传感器
|
|
||||||
LogUtils.d(TAG, "MotionStatusReceiver 注销并强制清理传感器");
|
|
||||||
} catch (Exception e) {
|
|
||||||
LogUtils.e(TAG, "MotionStatusReceiver 注销失败:" + e.getMessage());
|
|
||||||
} finally {
|
|
||||||
mMotionStatusReceiver = null;
|
|
||||||
mMotionStatusFilter = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isServiceRunning() {
|
public boolean isServiceRunning() {
|
||||||
return _mIsServiceRunning;
|
return _mIsServiceRunning;
|
||||||
}
|
}
|
||||||
@@ -479,37 +462,44 @@ public class MainService extends Service {
|
|||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
sInstance = null;
|
sInstance = null;
|
||||||
|
|
||||||
// 核心清理:1.注销MotionStatusReceiver 2.关闭GPS 3.停止定时任务
|
// 核心:停止LocalMotionDetector(避免传感器内存泄漏)
|
||||||
unregisterMotionStatusReceiver(); // 注销Receiver,避免内存泄漏
|
if (mMotionDetector != null) {
|
||||||
stopGpsLocation(); // 强制关闭GPS监听
|
mMotionDetector.stopDetection();
|
||||||
stopGpsStaticTimer(); // 停止静止时GPS定时任务
|
LogUtils.d(TAG, "LocalMotionDetector 已停止检测");
|
||||||
|
}
|
||||||
|
|
||||||
// 其他资源清理
|
// 清理延迟Handler任务(避免内存泄漏)
|
||||||
|
if (staticDelayHandler != null) {
|
||||||
|
staticDelayHandler.removeCallbacksAndMessages(null);
|
||||||
|
staticDelayHandler = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 原有清理逻辑(已删除Receiver注销代码)
|
||||||
|
stopGpsLocation();
|
||||||
|
stopGpsStaticTimer();
|
||||||
clearAllData();
|
clearAllData();
|
||||||
stopForeground(true);
|
stopForeground(true);
|
||||||
|
|
||||||
// 清理所有监听者
|
|
||||||
synchronized (mListenerLock) {
|
synchronized (mListenerLock) {
|
||||||
mGpsListeners.clear();
|
mGpsListeners.clear();
|
||||||
mTaskListeners.clear();
|
mTaskListeners.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 销毁线程池
|
|
||||||
if (distanceExecutor != null && !distanceExecutor.isShutdown()) {
|
if (distanceExecutor != null && !distanceExecutor.isShutdown()) {
|
||||||
distanceExecutor.shutdown();
|
distanceExecutor.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 重置状态变量
|
|
||||||
_mIsServiceRunning = false;
|
_mIsServiceRunning = false;
|
||||||
isGpsEnabled = false;
|
isGpsEnabled = false;
|
||||||
isGpsListening = false;
|
isGpsListening = false;
|
||||||
|
isDelaySwitching = false;
|
||||||
mLocationManager = null;
|
mLocationManager = null;
|
||||||
LogUtils.d(TAG, "MainService 销毁完成,所有资源已清理");
|
LogUtils.d(TAG, "MainService 销毁完成,所有资源已清理");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// 位置操作方法(Java 7 语法)
|
// 位置操作方法
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
public ArrayList<PositionModel> getPositionList() {
|
public ArrayList<PositionModel> getPositionList() {
|
||||||
return mPositionList;
|
return mPositionList;
|
||||||
@@ -519,7 +509,6 @@ public class MainService extends Service {
|
|||||||
return _mCurrentGpsPosition;
|
return _mCurrentGpsPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 对外提供:判断GPS是否处于持续监听状态(给MotionStatusReceiver调用)
|
|
||||||
public boolean isGpsListening() {
|
public boolean isGpsListening() {
|
||||||
return isGpsListening;
|
return isGpsListening;
|
||||||
}
|
}
|
||||||
@@ -529,7 +518,6 @@ public class MainService extends Service {
|
|||||||
LogUtils.w(TAG, "removePosition:参数无效");
|
LogUtils.w(TAG, "removePosition:参数无效");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 迭代器遍历删除
|
|
||||||
Iterator<PositionModel> iter = mPositionList.iterator();
|
Iterator<PositionModel> iter = mPositionList.iterator();
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
PositionModel pos = iter.next();
|
PositionModel pos = iter.next();
|
||||||
@@ -546,7 +534,6 @@ public class MainService extends Service {
|
|||||||
LogUtils.w(TAG, "updatePosition:参数无效");
|
LogUtils.w(TAG, "updatePosition:参数无效");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 基础for循环查找并更新
|
|
||||||
for (int i = 0; i < mPositionList.size(); i++) {
|
for (int i = 0; i < mPositionList.size(); i++) {
|
||||||
PositionModel oldPos = mPositionList.get(i);
|
PositionModel oldPos = mPositionList.get(i);
|
||||||
if (updatedPos.getPositionId().equals(oldPos.getPositionId())) {
|
if (updatedPos.getPositionId().equals(oldPos.getPositionId())) {
|
||||||
@@ -573,7 +560,6 @@ public class MainService extends Service {
|
|||||||
LogUtils.w(TAG, "addPosition:位置为空");
|
LogUtils.w(TAG, "addPosition:位置为空");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 位置去重(增强for循环)
|
|
||||||
boolean isDuplicate = false;
|
boolean isDuplicate = false;
|
||||||
for (PositionModel pos : mPositionList) {
|
for (PositionModel pos : mPositionList) {
|
||||||
if (newPos.getPositionId().equals(pos.getPositionId())) {
|
if (newPos.getPositionId().equals(pos.getPositionId())) {
|
||||||
@@ -613,7 +599,6 @@ public class MainService extends Service {
|
|||||||
LogUtils.d(TAG, "syncCurrentGpsPosition:成功(纬度=" + position.getLatitude() + ",经度=" + position.getLongitude() + ")");
|
LogUtils.d(TAG, "syncCurrentGpsPosition:成功(纬度=" + position.getLatitude() + ",经度=" + position.getLongitude() + ")");
|
||||||
notifyAllGpsListeners(position);
|
notifyAllGpsListeners(position);
|
||||||
|
|
||||||
// 服务运行中同步通知栏状态
|
|
||||||
if (_mIsServiceRunning) {
|
if (_mIsServiceRunning) {
|
||||||
syncGpsStatusToNotification();
|
syncGpsStatusToNotification();
|
||||||
}
|
}
|
||||||
@@ -623,14 +608,12 @@ public class MainService extends Service {
|
|||||||
if (!_mIsServiceRunning || _mCurrentGpsPosition == null) {
|
if (!_mIsServiceRunning || _mCurrentGpsPosition == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 格式化通知内容
|
|
||||||
final String gpsStatus = String.format(
|
final String gpsStatus = String.format(
|
||||||
"GPS位置:北纬%.4f° 东经%.4f° | 可见位置:%d个",
|
"GPS位置:北纬%.4f° 东经%.4f° | 可见位置:%d个",
|
||||||
_mCurrentGpsPosition.getLatitude(),
|
_mCurrentGpsPosition.getLatitude(),
|
||||||
_mCurrentGpsPosition.getLongitude(),
|
_mCurrentGpsPosition.getLongitude(),
|
||||||
mVisiblePositionIds.size()
|
mVisiblePositionIds.size()
|
||||||
);
|
);
|
||||||
// 主线程切换
|
|
||||||
if (Looper.myLooper() == Looper.getMainLooper()) {
|
if (Looper.myLooper() == Looper.getMainLooper()) {
|
||||||
NotificationUtil.updateForegroundServiceStatus(this, gpsStatus);
|
NotificationUtil.updateForegroundServiceStatus(this, gpsStatus);
|
||||||
} else {
|
} else {
|
||||||
@@ -645,7 +628,7 @@ public class MainService extends Service {
|
|||||||
|
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// 服务生命周期+辅助服务相关(Java 7 语法)
|
// 服务生命周期+辅助服务相关
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
@Override
|
@Override
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
@@ -653,24 +636,18 @@ public class MainService extends Service {
|
|||||||
if (intent != null) {
|
if (intent != null) {
|
||||||
isSettingToEnable = intent.getBooleanExtra(EXTRA_IS_SETTING_TO_ENABLE, false);
|
isSettingToEnable = intent.getBooleanExtra(EXTRA_IS_SETTING_TO_ENABLE, false);
|
||||||
if (isSettingToEnable) {
|
if (isSettingToEnable) {
|
||||||
run(); // 重启服务核心逻辑(重新注册Receiver)
|
run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据是否自启动返回对应启动模式
|
|
||||||
return isSettingToEnable ? Service.START_STICKY : super.onStartCommand(intent, flags, startId);
|
return isSettingToEnable ? Service.START_STICKY : super.onStartCommand(intent, flags, startId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 服务连接内部类
|
|
||||||
private class MyServiceConnection implements ServiceConnection {
|
private class MyServiceConnection implements ServiceConnection {
|
||||||
@Override
|
@Override
|
||||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
public void onServiceConnected(ComponentName name, IBinder service) {}
|
||||||
// 空实现(如需绑定辅助服务可补充逻辑)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onServiceDisconnected(ComponentName name) {
|
public void onServiceDisconnected(ComponentName name) {
|
||||||
// 辅助服务断开时重新绑定
|
|
||||||
if (mAppConfigsUtil.isEnableMainService(true)) {
|
if (mAppConfigsUtil.isEnableMainService(true)) {
|
||||||
wakeupAndBindAssistant();
|
wakeupAndBindAssistant();
|
||||||
}
|
}
|
||||||
@@ -678,9 +655,7 @@ public class MainService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void wakeupAndBindAssistant() {
|
void wakeupAndBindAssistant() {
|
||||||
// 检查辅助服务是否存活
|
|
||||||
if (!ServiceUtil.isServiceAlive(getApplicationContext(), AssistantService.class.getName())) {
|
if (!ServiceUtil.isServiceAlive(getApplicationContext(), AssistantService.class.getName())) {
|
||||||
// 启动+绑定辅助服务
|
|
||||||
startService(new Intent(MainService.this, AssistantService.class));
|
startService(new Intent(MainService.this, AssistantService.class));
|
||||||
bindService(new Intent(MainService.this, AssistantService.class), mMyServiceConnection, Context.BIND_IMPORTANT);
|
bindService(new Intent(MainService.this, AssistantService.class), mMyServiceConnection, Context.BIND_IMPORTANT);
|
||||||
}
|
}
|
||||||
@@ -688,28 +663,25 @@ public class MainService extends Service {
|
|||||||
|
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// GPS相关核心方法(Java 7 语法,仅保留Receiver调用的启动/停止逻辑)
|
// GPS相关核心方法
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
public MainService() {
|
public MainService() {
|
||||||
distanceExecutor = Executors.newSingleThreadScheduledExecutor();
|
distanceExecutor = Executors.newSingleThreadScheduledExecutor();
|
||||||
initGpsLocationListener();
|
initGpsLocationListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化GPS监听(仅创建Listener,不注册)
|
|
||||||
private void initGpsLocationListener() {
|
private void initGpsLocationListener() {
|
||||||
LogUtils.d(TAG, "initGpsLocationListener");
|
LogUtils.d(TAG, "initGpsLocationListener");
|
||||||
mGpsLocationListener = new LocationListener() {
|
mGpsLocationListener = new LocationListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onLocationChanged(Location location) {
|
public void onLocationChanged(Location location) {
|
||||||
if (location != null) {
|
if (location != null) {
|
||||||
// 封装GPS位置
|
|
||||||
PositionModel gpsPos = new PositionModel();
|
PositionModel gpsPos = new PositionModel();
|
||||||
gpsPos.setLatitude(location.getLatitude());
|
gpsPos.setLatitude(location.getLatitude());
|
||||||
gpsPos.setLongitude(location.getLongitude());
|
gpsPos.setLongitude(location.getLongitude());
|
||||||
gpsPos.setPositionId("CURRENT_GPS_POS");
|
gpsPos.setPositionId("CURRENT_GPS_POS");
|
||||||
gpsPos.setMemo("实时GPS位置");
|
gpsPos.setMemo("实时GPS位置");
|
||||||
|
|
||||||
// 同步位置+校验任务
|
|
||||||
syncCurrentGpsPosition(gpsPos);
|
syncCurrentGpsPosition(gpsPos);
|
||||||
DistanceCalculatorUtil.getInstance(MainService.this).checkAllTaskTriggerCondition(gpsPos);
|
DistanceCalculatorUtil.getInstance(MainService.this).checkAllTaskTriggerCondition(gpsPos);
|
||||||
LogUtils.d(TAG, "GPS位置更新:纬度=" + location.getLatitude() + ",经度=" + location.getLongitude());
|
LogUtils.d(TAG, "GPS位置更新:纬度=" + location.getLatitude() + ",经度=" + location.getLongitude());
|
||||||
@@ -720,7 +692,6 @@ public class MainService extends Service {
|
|||||||
public void onStatusChanged(String provider, int status, Bundle extras) {
|
public void onStatusChanged(String provider, int status, Bundle extras) {
|
||||||
if (provider.equals(LocationManager.GPS_PROVIDER)) {
|
if (provider.equals(LocationManager.GPS_PROVIDER)) {
|
||||||
String statusDesc = "";
|
String statusDesc = "";
|
||||||
// Java 7 基础switch
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case LocationProvider.AVAILABLE:
|
case LocationProvider.AVAILABLE:
|
||||||
statusDesc = "GPS状态:已就绪(可用)";
|
statusDesc = "GPS状态:已就绪(可用)";
|
||||||
@@ -745,8 +716,7 @@ public class MainService extends Service {
|
|||||||
String statusDesc = "GPS已开启(用户手动打开)";
|
String statusDesc = "GPS已开启(用户手动打开)";
|
||||||
LogUtils.d(TAG, statusDesc);
|
LogUtils.d(TAG, statusDesc);
|
||||||
notifyAllGpsStatusListeners(statusDesc);
|
notifyAllGpsStatusListeners(statusDesc);
|
||||||
updateNotificationGpsStatus("GPS已开启,等待Receiver控制启动...");
|
updateNotificationGpsStatus("GPS已开启,等待运动状态触发...");
|
||||||
// 不主动启动GPS,由Receiver根据运动状态控制
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -766,20 +736,15 @@ public class MainService extends Service {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// GPS就绪检查(给Receiver调用的GPS操作做前置判断)
|
|
||||||
private boolean checkGpsReady() {
|
private boolean checkGpsReady() {
|
||||||
// 检查定位权限
|
|
||||||
isGpsPermissionGranted = checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
|
isGpsPermissionGranted = checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
|
||||||
== PackageManager.PERMISSION_GRANTED;
|
== PackageManager.PERMISSION_GRANTED;
|
||||||
|
|
||||||
// 初始化LocationManager
|
|
||||||
if (mLocationManager == null) {
|
if (mLocationManager == null) {
|
||||||
mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
|
mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
|
||||||
}
|
}
|
||||||
// 检查GPS是否启用
|
|
||||||
isGpsEnabled = mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
|
isGpsEnabled = mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
|
||||||
|
|
||||||
// 权限未授予处理
|
|
||||||
if (!isGpsPermissionGranted) {
|
if (!isGpsPermissionGranted) {
|
||||||
String tip = "GPS准备失败:缺少精确定位权限";
|
String tip = "GPS准备失败:缺少精确定位权限";
|
||||||
LogUtils.e(TAG, tip);
|
LogUtils.e(TAG, tip);
|
||||||
@@ -788,7 +753,6 @@ public class MainService extends Service {
|
|||||||
ToastUtils.show("请授予定位权限,否则无法获取GPS位置");
|
ToastUtils.show("请授予定位权限,否则无法获取GPS位置");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// GPS未启用处理
|
|
||||||
if (!isGpsEnabled) {
|
if (!isGpsEnabled) {
|
||||||
String tip = "GPS准备失败:系统GPS未开启";
|
String tip = "GPS准备失败:系统GPS未开启";
|
||||||
LogUtils.e(TAG, tip);
|
LogUtils.e(TAG, tip);
|
||||||
@@ -802,14 +766,13 @@ public class MainService extends Service {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 启动GPS持续监听(仅Receiver可调用)
|
// 启动GPS持续监听(运动状态回调调用)
|
||||||
public void startGpsLocation() {
|
public void startGpsLocation() {
|
||||||
if (!checkGpsReady() || isGpsListening) {
|
if (!checkGpsReady() || isGpsListening) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 注册GPS位置更新
|
|
||||||
mLocationManager.requestLocationUpdates(
|
mLocationManager.requestLocationUpdates(
|
||||||
LocationManager.GPS_PROVIDER,
|
LocationManager.GPS_PROVIDER,
|
||||||
GPS_UPDATE_INTERVAL,
|
GPS_UPDATE_INTERVAL,
|
||||||
@@ -818,10 +781,9 @@ public class MainService extends Service {
|
|||||||
Looper.getMainLooper()
|
Looper.getMainLooper()
|
||||||
);
|
);
|
||||||
|
|
||||||
// 标记GPS进入持续监听状态
|
|
||||||
isGpsListening = true;
|
isGpsListening = true;
|
||||||
|
|
||||||
// 获取最后已知GPS位置
|
// 获取最后已知位置
|
||||||
Location lastKnownLocation = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
|
Location lastKnownLocation = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
|
||||||
if (lastKnownLocation != null) {
|
if (lastKnownLocation != null) {
|
||||||
PositionModel lastGpsPos = new PositionModel();
|
PositionModel lastGpsPos = new PositionModel();
|
||||||
@@ -853,9 +815,8 @@ public class MainService extends Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 停止GPS持续监听(仅Receiver可调用)
|
// 停止GPS持续监听(运动状态回调调用)
|
||||||
public void stopGpsLocation() {
|
public void stopGpsLocation() {
|
||||||
// 校验参数:避免空指针+权限未授予时调用
|
|
||||||
if (mLocationManager != null && mGpsLocationListener != null && isGpsPermissionGranted) {
|
if (mLocationManager != null && mGpsLocationListener != null && isGpsPermissionGranted) {
|
||||||
try {
|
try {
|
||||||
mLocationManager.removeUpdates(mGpsLocationListener);
|
mLocationManager.removeUpdates(mGpsLocationListener);
|
||||||
@@ -878,7 +839,6 @@ public class MainService extends Service {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 格式化通知内容
|
|
||||||
final String triggerContent = String.format(
|
final String triggerContent = String.format(
|
||||||
"任务触发:%s\n位置:%s\n当前距离:%.1f米(条件:%s%d米)",
|
"任务触发:%s\n位置:%s\n当前距离:%.1f米(条件:%s%d米)",
|
||||||
task.getTaskDescription(),
|
task.getTaskDescription(),
|
||||||
@@ -888,10 +848,8 @@ public class MainService extends Service {
|
|||||||
task.getDiscussDistance()
|
task.getDiscussDistance()
|
||||||
);
|
);
|
||||||
|
|
||||||
// 更新前台通知
|
|
||||||
updateNotificationGpsStatus(triggerContent);
|
updateNotificationGpsStatus(triggerContent);
|
||||||
|
|
||||||
// 显示Toast(主线程安全)
|
|
||||||
if (Looper.myLooper() == Looper.getMainLooper()) {
|
if (Looper.myLooper() == Looper.getMainLooper()) {
|
||||||
ToastUtils.show(triggerContent);
|
ToastUtils.show(triggerContent);
|
||||||
NotificationUtil.show(MainService.this, task.getTaskId(), task.getPositionId(), task.getTaskDescription());
|
NotificationUtil.show(MainService.this, task.getTaskId(), task.getPositionId(), task.getTaskDescription());
|
||||||
@@ -910,7 +868,6 @@ public class MainService extends Service {
|
|||||||
// 更新前台通知的GPS状态
|
// 更新前台通知的GPS状态
|
||||||
void updateNotificationGpsStatus(final String statusText) {
|
void updateNotificationGpsStatus(final String statusText) {
|
||||||
if (_mIsServiceRunning) {
|
if (_mIsServiceRunning) {
|
||||||
// 主线程判断+切换(Java7匿名内部类)
|
|
||||||
if (Looper.myLooper() == Looper.getMainLooper()) {
|
if (Looper.myLooper() == Looper.getMainLooper()) {
|
||||||
NotificationUtil.updateForegroundServiceStatus(this, statusText);
|
NotificationUtil.updateForegroundServiceStatus(this, statusText);
|
||||||
} else {
|
} else {
|
||||||
@@ -926,7 +883,7 @@ public class MainService extends Service {
|
|||||||
|
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// GPS监听通知相关方法(Java7语法,给外部监听者回调)
|
// GPS监听通知相关方法
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
public void notifyAllGpsListeners(PositionModel currentGpsPos) {
|
public void notifyAllGpsListeners(PositionModel currentGpsPos) {
|
||||||
if (currentGpsPos == null || mGpsListeners.isEmpty()) {
|
if (currentGpsPos == null || mGpsListeners.isEmpty()) {
|
||||||
@@ -940,7 +897,7 @@ public class MainService extends Service {
|
|||||||
if (listener != null) {
|
if (listener != null) {
|
||||||
notifySingleListener(listener, currentGpsPos);
|
notifySingleListener(listener, currentGpsPos);
|
||||||
} else {
|
} else {
|
||||||
iter.remove(); // 清理已回收监听者
|
iter.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -969,7 +926,6 @@ public class MainService extends Service {
|
|||||||
WeakReference<GpsUpdateListener> ref = iter.next();
|
WeakReference<GpsUpdateListener> ref = iter.next();
|
||||||
final GpsUpdateListener listener = ref.get();
|
final GpsUpdateListener listener = ref.get();
|
||||||
if (listener != null) {
|
if (listener != null) {
|
||||||
// 主线程切换,避免UI异常(Java7匿名Runnable)
|
|
||||||
if (Looper.myLooper() == Looper.getMainLooper()) {
|
if (Looper.myLooper() == Looper.getMainLooper()) {
|
||||||
listener.onGpsStatusChanged(status);
|
listener.onGpsStatusChanged(status);
|
||||||
} else {
|
} else {
|
||||||
@@ -981,7 +937,7 @@ public class MainService extends Service {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
iter.remove(); // 清理无效弱引用
|
iter.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -995,7 +951,6 @@ public class MainService extends Service {
|
|||||||
synchronized (mListenerLock) {
|
synchronized (mListenerLock) {
|
||||||
mGpsListeners.add(new WeakReference<GpsUpdateListener>(listener));
|
mGpsListeners.add(new WeakReference<GpsUpdateListener>(listener));
|
||||||
LogUtils.d(TAG, "GPS监听注册成功,当前数量:" + mGpsListeners.size());
|
LogUtils.d(TAG, "GPS监听注册成功,当前数量:" + mGpsListeners.size());
|
||||||
// 注册后推送当前GPS位置(避免监听者遗漏初始数据)
|
|
||||||
if (_mCurrentGpsPosition != null) {
|
if (_mCurrentGpsPosition != null) {
|
||||||
notifySingleListener(listener, _mCurrentGpsPosition);
|
notifySingleListener(listener, _mCurrentGpsPosition);
|
||||||
}
|
}
|
||||||
@@ -1021,9 +976,9 @@ public class MainService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// LocalBinder 定义(与Activity绑定用,Java7内部类)
|
// LocalBinder 定义(无修改)
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
public class LocalBinder extends android.os.Binder {
|
public class LocalBinder extends android.os.Binder {
|
||||||
private MainService mService;
|
private MainService mService;
|
||||||
|
|
||||||
@@ -1032,7 +987,7 @@ public class MainService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public MainService getService() {
|
public MainService getService() {
|
||||||
return mService; // 暴露MainService实例给绑定的Activity
|
return mService;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,168 @@
|
|||||||
|
package cc.winboll.studio.positions.utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
|
||||||
|
* @Date 2025/11/05 15:49
|
||||||
|
* @Describe LocalMotionDetector
|
||||||
|
*/
|
||||||
|
import android.content.Context;
|
||||||
|
import android.hardware.Sensor;
|
||||||
|
import android.hardware.SensorEvent;
|
||||||
|
import android.hardware.SensorEventListener;
|
||||||
|
import android.hardware.SensorManager;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.util.Log;
|
||||||
|
import cc.winboll.studio.libappbase.LogUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 本机运动状态监测工具(无联网,纯传感器)
|
||||||
|
*/
|
||||||
|
public class LocalMotionDetector implements SensorEventListener {
|
||||||
|
public static final String TAG = "LocalMotionDetector";
|
||||||
|
|
||||||
|
// 配置参数(重点修改:调高运动阈值,适配坐立持机场景)
|
||||||
|
private static final float MOTION_THRESHOLD = 1.8f; // 从0.5f调高到1.8f(过滤坐立轻微晃动)
|
||||||
|
private static final long STATUS_CHECK_INTERVAL = 3000; // 3秒判断一次状态
|
||||||
|
private static final int STEP_CHANGE_THRESHOLD = 2; // 3秒≥2步判定行走
|
||||||
|
|
||||||
|
private SensorManager mSensorManager;
|
||||||
|
private Sensor mAccelerometer;
|
||||||
|
private Sensor mStepCounter;
|
||||||
|
private Handler mMainHandler;
|
||||||
|
private MotionStatusCallback mCallback;
|
||||||
|
|
||||||
|
private boolean mIsDetecting = false;
|
||||||
|
private float mLastAccelMagnitude = 0f;
|
||||||
|
private int mLastStepCount = 0;
|
||||||
|
private int mCurrentStepCount = 0;
|
||||||
|
private boolean mIsWalking = false;
|
||||||
|
|
||||||
|
// 单例模式
|
||||||
|
private static LocalMotionDetector sInstance;
|
||||||
|
public static LocalMotionDetector getInstance() {
|
||||||
|
if (sInstance == null) {
|
||||||
|
synchronized (LocalMotionDetector.class) {
|
||||||
|
if (sInstance == null) {
|
||||||
|
sInstance = new LocalMotionDetector();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private LocalMotionDetector() {
|
||||||
|
mMainHandler = new Handler(Looper.getMainLooper());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开始监测运动状态
|
||||||
|
*/
|
||||||
|
public void startDetection(Context context, MotionStatusCallback callback) {
|
||||||
|
if (mIsDetecting) return;
|
||||||
|
mCallback = callback;
|
||||||
|
mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
|
||||||
|
|
||||||
|
// 初始化传感器
|
||||||
|
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
|
||||||
|
mStepCounter = mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
|
||||||
|
|
||||||
|
// 注册传感器监听
|
||||||
|
if (mAccelerometer != null) {
|
||||||
|
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL, mMainHandler);
|
||||||
|
}
|
||||||
|
if (mStepCounter != null) {
|
||||||
|
mSensorManager.registerListener(this, mStepCounter, SensorManager.SENSOR_DELAY_NORMAL, mMainHandler);
|
||||||
|
LogUtils.d(TAG, "计步传感器已启动");
|
||||||
|
} else {
|
||||||
|
LogUtils.d(TAG, "设备不支持计步传感器,仅用加速度判断");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 启动定时状态检测
|
||||||
|
mMainHandler.postDelayed(mStatusCheckRunnable, STATUS_CHECK_INTERVAL);
|
||||||
|
mIsDetecting = true;
|
||||||
|
LogUtils.d(TAG, "运动状态监测已启动");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 停止监测
|
||||||
|
*/
|
||||||
|
public void stopDetection() {
|
||||||
|
if (!mIsDetecting) return;
|
||||||
|
if (mSensorManager != null) {
|
||||||
|
mSensorManager.unregisterListener(this);
|
||||||
|
}
|
||||||
|
mMainHandler.removeCallbacksAndMessages(null);
|
||||||
|
mIsDetecting = false;
|
||||||
|
mIsWalking = false;
|
||||||
|
mCallback = null;
|
||||||
|
LogUtils.d(TAG, "运动状态监测已停止");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSensorChanged(SensorEvent event) {
|
||||||
|
if (!mIsDetecting) return;
|
||||||
|
switch (event.sensor.getType()) {
|
||||||
|
case Sensor.TYPE_ACCELEROMETER:
|
||||||
|
// 计算加速度幅度(保留原逻辑,阈值已调高)
|
||||||
|
float accelX = Math.abs(event.values[0]);
|
||||||
|
float accelY = Math.abs(event.values[1]);
|
||||||
|
float accelZ = Math.abs(event.values[2]);
|
||||||
|
mLastAccelMagnitude = accelX + accelY + accelZ;
|
||||||
|
break;
|
||||||
|
case Sensor.TYPE_STEP_COUNTER:
|
||||||
|
// 累计步数
|
||||||
|
mCurrentStepCount = (int) event.values[0];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定时判断运动状态(优化逻辑:计步为0时,即使有轻微加速度也判定为静止)
|
||||||
|
*/
|
||||||
|
private final Runnable mStatusCheckRunnable = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (!mIsDetecting || mCallback == null) return;
|
||||||
|
|
||||||
|
//LogUtils.d(TAG, "mStatusCheckRunnable run");
|
||||||
|
|
||||||
|
boolean newIsWalking = false;
|
||||||
|
// 结合计步器+加速度判断(优化:优先计步,无步数时严格按高阈值判断)
|
||||||
|
if (mStepCounter != null) {
|
||||||
|
int stepChange = mCurrentStepCount - mLastStepCount;
|
||||||
|
// 只有“步数达标” 或 “无步数但加速度远超坐立幅度”,才判定为行走
|
||||||
|
newIsWalking = (stepChange >= STEP_CHANGE_THRESHOLD)
|
||||||
|
&& (mLastAccelMagnitude >= MOTION_THRESHOLD); // 增加步数+加速度双重校验
|
||||||
|
mLastStepCount = mCurrentStepCount;
|
||||||
|
} else {
|
||||||
|
// 无计步器时,仅用高阈值判断
|
||||||
|
newIsWalking = mLastAccelMagnitude >= MOTION_THRESHOLD;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 状态变化时回调
|
||||||
|
if (newIsWalking != mIsWalking) {
|
||||||
|
mIsWalking = newIsWalking;
|
||||||
|
String statusDesc = mIsWalking ? "行走状态" : "静止/低运动状态";
|
||||||
|
LogUtils.d(TAG, "运动状态变化:" + statusDesc + " | 加速度幅度:" + mLastAccelMagnitude); // 增加日志便于调试
|
||||||
|
mCallback.onMotionStatusChanged(mIsWalking, statusDesc);
|
||||||
|
}
|
||||||
|
|
||||||
|
LogUtils.d(TAG, String.format("运动状态 newIsWalking %s", newIsWalking));
|
||||||
|
|
||||||
|
// 循环检测
|
||||||
|
mMainHandler.postDelayed(this, STATUS_CHECK_INTERVAL);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 运动状态回调接口
|
||||||
|
*/
|
||||||
|
public interface MotionStatusCallback {
|
||||||
|
void onMotionStatusChanged(boolean isWalking, String statusDesc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user