diff --git a/positions/build.properties b/positions/build.properties
index c367a46..f7130a2 100644
--- a/positions/build.properties
+++ b/positions/build.properties
@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
-#Tue Oct 28 20:03:59 HKT 2025
+#Tue Nov 04 12:54:59 GMT 2025
stageCount=18
libraryProject=
baseVersion=15.0
publishVersion=15.0.17
-buildCount=0
+buildCount=20
baseBetaVersion=15.0.18
diff --git a/positions/src/main/AndroidManifest.xml b/positions/src/main/AndroidManifest.xml
index 72ceca0..db82105 100644
--- a/positions/src/main/AndroidManifest.xml
+++ b/positions/src/main/AndroidManifest.xml
@@ -3,24 +3,24 @@
xmlns:android="http://schemas.android.com/apk/res/android"
package="cc.winboll.studio.positions">
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
@@ -59,22 +59,28 @@
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version"/>
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
diff --git a/positions/src/main/java/cc/winboll/studio/positions/receivers/MotionStatusReceiver.java b/positions/src/main/java/cc/winboll/studio/positions/receivers/MotionStatusReceiver.java
index c3f6e89..7ff5e8b 100644
--- a/positions/src/main/java/cc/winboll/studio/positions/receivers/MotionStatusReceiver.java
+++ b/positions/src/main/java/cc/winboll/studio/positions/receivers/MotionStatusReceiver.java
@@ -9,116 +9,353 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
import android.os.Build;
+import android.os.Handler;
+import android.os.Looper;
import android.text.TextUtils;
import cc.winboll.studio.libappbase.LogUtils;
+import cc.winboll.studio.libappbase.ToastUtils;
import cc.winboll.studio.positions.services.MainService;
import cc.winboll.studio.positions.utils.ServiceUtil;
/**
* 运动状态监听Receiver
- * 功能:接收运动状态广播,控制GPS权限申请与GPS监听开关
+ * 功能:1.持续监听传感器(不关闭) 2.每5秒计算运动状态 3.按状态切换GPS模式(实时/30秒定时)
*/
-public class MotionStatusReceiver extends BroadcastReceiver {
- public static final String TAG = "MotionStatusReceiver";
+public class MotionStatusReceiver extends BroadcastReceiver implements SensorEventListener {
+ public static final String TAG = "MotionStatusReceiver";
- // 运动状态广播Action(需与运动状态发送方保持一致,如传感器服务)
- public static final String ACTION_MOTION_STATUS = "cc.winboll.studio.positions.ACTION_MOTION_STATUS";
- // 运动状态Extra键:0=静止/低运动,1=行走/高运动
- public static final String EXTRA_MOTION_STATUS = "EXTRA_MOTION_STATUS";
- // 静止时GPS定时获取间隔(单位:分钟,可配置)
- public static final long GPS_STATIC_INTERVAL = 1;
+ // 广播Action
+ public static final String ACTION_MOTION_STATUS_RECEIVER = "cc.winboll.studio.positions.receivers.MotionStatusReceiver";
+ public static final String EXTRA_SENSORS_ENABLE = "EXTRA_SENSORS_ENABLE";
+ // 传感器启动状态标志位
+ boolean mIsSensorsEnable = false;
+ // 运动状态常量
+ private static final int MOTION_STATUS_STATIC = 0; // 静止/低运动
+ private static final int MOTION_STATUS_WALKING = 1; // 行走/高速运动
+ // 配置参数(按需求调整)
+ private static final float ACCELEROMETER_THRESHOLD = 0.8f; // 加速度阈值
+ private static final float GYROSCOPE_THRESHOLD = 0.5f; // 陀螺仪阈值
+ private static final long STATUS_CALC_INTERVAL = 5000; // 运动状态计算间隔(5秒)
+ private static final long GPS_STATIC_INTERVAL = 30; // 静止时GPS间隔(30秒)
+ // 核心对象
+ private volatile SensorManager mSensorManager;
+ private Sensor mAccelerometer;
+ private Sensor mGyroscope;
+ private volatile boolean mIsSensorListening = false; // 传感器是否持续监听
+ private int mCurrentMotionStatus = MOTION_STATUS_STATIC; // 当前运动状态
+ private Handler mMainHandler; // 主线程Handler(用于定时计算)
+ private Context mBroadcastContext; // 广播上下文
+ // 传感器数据缓存(用于5秒内数据汇总,避免单次波动误判)
+ private float mAccelMax = 0f; // 5秒内加速度最大值
+ private float mGyroMax = 0f; // 5秒内陀螺仪最大值
- @Override
- public void onReceive(Context context, Intent intent) {
- if (context == null || intent == null || !TextUtils.equals(intent.getAction(), ACTION_MOTION_STATUS)) {
- LogUtils.w(TAG, "无效广播:Action不匹配或上下文为空");
- return;
- }
+ @Override
+ public void onReceive(Context context, Intent intent) {
- // 1. 获取运动状态(0=静止/低运动,1=行走/高运动)
- int motionStatus = intent.getIntExtra(EXTRA_MOTION_STATUS, 0);
- LogUtils.d(TAG, "接收运动状态:" + (motionStatus == 1 ? "行走中" : "静止/低运动"));
+ LogUtils.d(TAG, "===== 接收器启动:onReceive() 开始执行 =====");
+ this.mBroadcastContext = context;
+ mMainHandler = new Handler(Looper.getMainLooper());
- // 2. 绑定并获取MainService实例(确保服务已启动)
- MainService mainService = getMainService(context);
- if (mainService == null) {
- LogUtils.e(TAG, "MainService未启动,无法控制GPS状态");
- return;
- }
+ if (TextUtils.equals(intent.getAction(), ACTION_MOTION_STATUS_RECEIVER)) {
+ boolean isSettingEnable = intent.getBooleanExtra(EXTRA_SENSORS_ENABLE, false);
+ if (mIsSensorsEnable == false && isSettingEnable == true) {
+ mIsSensorsEnable = true;
+ // 1. 初始化传感器(必执行)
+ initSensors();
+
- // 3. 根据运动状态处理GPS逻辑
- if (motionStatus == 1) {
- // 3.1 行走中:申请GPS权限(若未授予)+ 开启持续GPS监听
- handleWalkingStatus(mainService, context);
- } else {
- // 3.2 静止/低运动:关闭持续GPS监听 + 启动定时GPS获取
- handleStaticStatus(mainService);
- }
- }
+ if (mAccelerometer == null || mGyroscope == null) {
+ LogUtils.e(TAG, "设备缺少加速度/陀螺仪,无法持续监听");
+ cleanResources(false); // 传感器不可用才清理
+ return;
+ }
- /**
- * 处理行走状态:申请GPS权限+开启持续GPS监听
- */
- private void handleWalkingStatus(MainService mainService, Context context) {
- // 检查GPS权限(Android 6.0+动态权限)
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
- context.checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
- != PackageManager.PERMISSION_GRANTED) {
- // 发送权限申请广播(由Activity接收并发起申请,Receiver无法直接申请权限)
- Intent permissionIntent = new Intent("cc.winboll.studio.positions.ACTION_REQUEST_GPS_PERMISSION");
- permissionIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
- context.sendBroadcast(permissionIntent);
- LogUtils.d(TAG, "行走中:GPS权限未授予,已发送权限申请广播");
- return;
- }
+ // 2. 校验参数
+ if (context == null || intent == null) {
+ LogUtils.d(TAG, "onReceive():无效参数,终止处理");
+ cleanResources(false);
+ return;
+ }
+ LogUtils.d(TAG, "onReceive():接收到广播Action=" + intent.getAction());
- // 权限已授予:开启持续GPS监听(调用MainService原有方法)
- if (!mainService.isGpsListening()) { // 需在MainService中新增isGpsListening()方法
- mainService.startGpsLocation();
- LogUtils.d(TAG, "行走中:已开启持续GPS监听");
- }
+ // 3. 启动持续传感器监听(核心:不关闭,重复调用无影响)
+ startSensorListening();
- // 停止静止时的GPS定时任务(避免重复获取)
- mainService.stopGpsStaticTimer();
- }
-
- /**
- * 处理静止状态:关闭持续GPS监听+启动定时GPS获取
- */
- private void handleStaticStatus(MainService mainService) {
- // 关闭持续GPS监听(避免耗电)
- if (mainService.isGpsListening()) {
- mainService.stopGpsLocation();
- LogUtils.d(TAG, "静止中:已关闭持续GPS监听");
- }
-
- // 启动定时GPS获取(获取一次后关闭,间隔GPS_STATIC_INTERVAL分钟)
- mainService.startGpsStaticTimer(GPS_STATIC_INTERVAL);
- }
-
- /**
- * 获取MainService实例(通过绑定服务或单例,确保线程安全)
- */
- private MainService getMainService(Context context) {
- // 方式1:若MainService单例有效,直接获取(推荐)
- MainService singleton = MainService.getInstance(context);
- if (singleton != null && singleton.isServiceRunning()) {
- return singleton;
- }
-
- // 方式2:若单例无效,尝试绑定服务(备用,需处理绑定回调)
- if (!ServiceUtil.isServiceAlive(context, MainService.class.getName())) {
- // 启动服务(若未运行)
- context.startService(new Intent(context, MainService.class));
- // 等待服务启动(短延时,实际项目建议用ServiceConnection异步绑定)
- try {
- Thread.sleep(500);
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
+ // 4. 启动5秒定时计算运动状态(核心:持续触发状态判断)
+ startStatusCalcTimer();
}
}
- return MainService.getInstance(context);
- }
+
+
+ // 5. 处理外部广播触发(可选,保留外部控制能力)
+// if (TextUtils.equals(intent.getAction(), ACTION_MOTION_STATUS_RECEIVER)) {
+// int motionStatus = intent.getIntExtra(EXTRA_MOTION_STATUS, MOTION_STATUS_STATIC);
+// String statusDesc = motionStatus == MOTION_STATUS_WALKING ? "高速运动" : "静止/低运动";
+// LogUtils.d(TAG, "外部广播触发,强制设置运动状态:" + statusDesc);
+// mCurrentMotionStatus = motionStatus;
+// handleMotionStatus(mCurrentMotionStatus); // 立即执行GPS切换
+// }
+ }
+
+ /**
+ * 初始化传感器(持续监听,复用实例)
+ */
+ private void initSensors() {
+ LogUtils.d(TAG, "initSensors():初始化传感器");
+ if (mSensorManager != null || mBroadcastContext == null) return;
+
+ mSensorManager = (SensorManager) mBroadcastContext.getSystemService(Context.SENSOR_SERVICE);
+ if (mSensorManager == null) {
+ LogUtils.e(TAG, "设备不支持传感器服务");
+ return;
+ }
+ // 获取传感器实例(持续复用,不销毁)
+ mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
+ mGyroscope = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
+
+ LogUtils.d(TAG, "传感器初始化结果:加速度=" + (mAccelerometer != null) + ",陀螺仪=" + (mGyroscope != null));
+ }
+
+ /**
+ * 启动传感器持续监听(核心:不关闭,注册一次一直生效)
+ */
+ private void startSensorListening() {
+ if (mSensorManager == null || mAccelerometer == null || mGyroscope == null) return;
+
+ if (!mIsSensorListening) {
+ // 注册传感器监听(持续生效,直到服务销毁才注销)
+ mSensorManager.registerListener(
+ this,
+ mAccelerometer,
+ SensorManager.SENSOR_DELAY_NORMAL, // 正常延迟,平衡性能与精度
+ mMainHandler
+ );
+ mSensorManager.registerListener(
+ this,
+ mGyroscope,
+ SensorManager.SENSOR_DELAY_NORMAL,
+ mMainHandler
+ );
+ mIsSensorListening = true;
+ LogUtils.d(TAG, "startSensorListening():传感器持续监听已启动(不关闭)");
+ }
+ }
+
+ /**
+ * 启动5秒定时计算运动状态(核心:周期性汇总传感器数据)
+ */
+ private void startStatusCalcTimer() {
+ if (mMainHandler == null) return;
+
+ // 移除旧任务(避免重复注册)
+ mMainHandler.removeCallbacks(mStatusCalcRunnable);
+ // 启动定时任务(每5秒执行一次)
+ mMainHandler.postDelayed(mStatusCalcRunnable, STATUS_CALC_INTERVAL);
+ LogUtils.d(TAG, "startStatusCalcTimer():5秒运动状态计算定时器已启动");
+ }
+
+ /**
+ * 运动状态计算任务(5秒执行一次)
+ */
+ private final Runnable mStatusCalcRunnable = new Runnable() {
+ @Override
+ public void run() {
+ // 1. 基于5秒内缓存的最大传感器数据判断状态
+ boolean isHighMotion = (mAccelMax > ACCELEROMETER_THRESHOLD) && (mGyroMax > GYROSCOPE_THRESHOLD);
+ int newMotionStatus = isHighMotion ? MOTION_STATUS_WALKING : MOTION_STATUS_STATIC;
+
+ // 2. 状态变化时才处理(避免频繁切换GPS)
+ if (newMotionStatus != mCurrentMotionStatus) {
+ mCurrentMotionStatus = newMotionStatus;
+ String statusDesc = isHighMotion ? "高速运动" : "静止/低运动";
+ LogUtils.d(TAG, "运动状态更新(5秒计算):" + statusDesc
+ + "(加速度最大值=" + mAccelMax + ",陀螺仪最大值=" + mGyroMax + ")");
+ handleMotionStatus(newMotionStatus); // 切换GPS模式
+ } else {
+ LogUtils.d(TAG, "运动状态无变化(5秒计算):" + (isHighMotion ? "高速运动" : "静止/低运动"));
+ }
+
+ // 3. 重置传感器数据缓存,准备下一个5秒周期
+ mAccelMax = 0f;
+ mGyroMax = 0f;
+
+ // 4. 循环执行定时任务(核心:持续计算)
+ mMainHandler.postDelayed(this, STATUS_CALC_INTERVAL);
+ }
+ };
+
+ /**
+ * 传感器数据变化回调(核心:实时缓存最大数据)
+ */
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ if (event == null) return;
+
+ // 实时缓存5秒内的最大传感器数据(避免单次波动误判)
+ switch (event.sensor.getType()) {
+ case Sensor.TYPE_ACCELEROMETER:
+ float accelTotal = Math.abs(event.values[0]) + Math.abs(event.values[1]) + Math.abs(event.values[2]);
+ if (accelTotal > mAccelMax) mAccelMax = accelTotal; // 缓存最大值
+ LogUtils.d(TAG, "加速度传感器实时数据:合值=" + accelTotal + "(当前5秒最大值=" + mAccelMax + ")");
+ break;
+ case Sensor.TYPE_GYROSCOPE:
+ float gyroTotal = Math.abs(event.values[0]) + Math.abs(event.values[1]) + Math.abs(event.values[2]);
+ if (gyroTotal > mGyroMax) mGyroMax = gyroTotal; // 缓存最大值
+ LogUtils.d(TAG, "陀螺仪实时数据:合值=" + gyroTotal + "(当前5秒最大值=" + mGyroMax + ")");
+ break;
+ }
+ }
+
+ /**
+ * 处理运动状态(核心:按状态切换GPS模式)
+ */
+ private void handleMotionStatus(int motionStatus) {
+ LogUtils.d(TAG, "handleMotionStatus():开始处理运动状态,切换GPS模式");
+ if (mBroadcastContext == null) {
+ LogUtils.w(TAG, "上下文为空,无法处理GPS");
+ return;
+ }
+
+ MainService mainService = getMainService();
+ if (mainService == null) {
+ LogUtils.e(TAG, "MainService未启动,GPS控制失败");
+ return;
+ }
+
+ if (motionStatus == MOTION_STATUS_WALKING) {
+ // 高速运动:启动GPS实时更新(2秒/1米)
+ handleHighMotionGPS(mainService);
+ } else {
+ // 静止/低运动:启动GPS30秒定时更新
+ handleStaticGPS(mainService);
+ }
+ }
+
+ /**
+ * 高速运动GPS处理:实时更新
+ */
+ private void handleHighMotionGPS(MainService mainService) {
+ // 动态权限判断(Android 6.0+)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
+ mBroadcastContext.checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
+ != PackageManager.PERMISSION_GRANTED) {
+ sendPermissionRequestBroadcast();
+ return;
+ }
+
+ // 启动实时GPS(已启动则不重复操作)
+ if (!mainService.isGpsListening()) {
+ mainService.startGpsLocation(); // 实时更新(2秒/1米)
+ mainService.stopGpsStaticTimer(); // 停止定时GPS
+ LogUtils.d(TAG, "高速运动:已启动GPS实时更新");
+ }
+ }
+
+ /**
+ * 静止/低运动GPS处理:30秒定时更新
+ */
+ private void handleStaticGPS(MainService mainService) {
+ // 停止实时GPS(已停止则不重复操作)
+ if (mainService.isGpsListening()) {
+ mainService.stopGpsLocation(); // 停止实时更新
+ LogUtils.d(TAG, "静止/低运动:已停止GPS实时更新");
+ }
+
+ // 启动30秒定时GPS(已启动则不重复操作)
+ mainService.startGpsStaticTimer(GPS_STATIC_INTERVAL); // 30秒一次
+ LogUtils.d(TAG, "静止/低运动:已启动GPS30秒定时更新");
+ }
+
+ /**
+ * 获取MainService实例(复用逻辑)
+ */
+ private MainService getMainService() {
+ if (mBroadcastContext == null) return null;
+
+ // 优先获取单例
+ MainService singleton = MainService.getInstance(mBroadcastContext);
+ if (singleton != null && singleton.isServiceRunning()) {
+ return singleton;
+ }
+
+ // 启动服务并重试
+ if (!ServiceUtil.isServiceAlive(mBroadcastContext, MainService.class.getName())) {
+ mBroadcastContext.startService(new Intent(mBroadcastContext, MainService.class));
+ try {
+ Thread.sleep(500); // 等待服务启动
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ return MainService.getInstance(mBroadcastContext);
+ }
+
+ /**
+ * 发送GPS权限申请广播(Receiver无法直接申请)
+ */
+ private void sendPermissionRequestBroadcast() {
+ Intent permissionIntent = new Intent("cc.winboll.studio.positions.ACTION_REQUEST_GPS_PERMISSION");
+ permissionIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
+ mBroadcastContext.sendBroadcast(permissionIntent);
+ LogUtils.d(TAG, "GPS权限缺失,已发送申请广播");
+ }
+
+ /**
+ * 资源清理(核心:传感器不关闭,仅清理Handler和上下文)
+ * @param isForceStopSensor 是否强制停止传感器(仅服务销毁时传true)
+ */
+ private void cleanResources(boolean isForceStopSensor) {
+ // 1. 停止定时计算任务
+ if (mMainHandler != null) {
+ mMainHandler.removeCallbacksAndMessages(null);
+ mMainHandler = null;
+ LogUtils.d(TAG, "cleanResources():已停止运动状态计算定时器");
+ }
+
+ // 2. 强制停止传感器(仅当外部触发销毁时执行,正常情况不关闭)
+ if (isForceStopSensor && mSensorManager != null && mIsSensorListening) {
+ mSensorManager.unregisterListener(this);
+ mIsSensorListening = false;
+ LogUtils.d(TAG, "cleanResources():已强制停止传感器监听");
+ }
+
+ // 3. 置空上下文(避免内存泄漏)
+ mBroadcastContext = null;
+ }
+
+ /**
+ * 传感器精度变化回调(日志监控)
+ */
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ String sensorType = sensor.getType() == Sensor.TYPE_ACCELEROMETER ? "加速度" : "陀螺仪";
+ String accuracyDesc = getAccuracyDesc(accuracy);
+ LogUtils.d(TAG, sensorType + "传感器精度变化:" + accuracyDesc);
+ }
+
+ /**
+ * 传感器精度描述转换
+ */
+ private String getAccuracyDesc(int accuracy) {
+ switch (accuracy) {
+ case SensorManager.SENSOR_STATUS_ACCURACY_HIGH: return "高";
+ case SensorManager.SENSOR_STATUS_ACCURACY_MEDIUM: return "中";
+ case SensorManager.SENSOR_STATUS_ACCURACY_LOW: return "低";
+ case SensorManager.SENSOR_STATUS_UNRELIABLE: return "不可靠";
+ default: return "未知";
+ }
+ }
+
+ /**
+ * 补充:Receiver销毁时强制清理(需在MainService注销时调用)
+ */
+ public void forceCleanResources() {
+ cleanResources(true); // 强制停止传感器
+ }
}
diff --git a/positions/src/main/java/cc/winboll/studio/positions/services/MainService.java b/positions/src/main/java/cc/winboll/studio/positions/services/MainService.java
index 773d288..e1c7293 100644
--- a/positions/src/main/java/cc/winboll/studio/positions/services/MainService.java
+++ b/positions/src/main/java/cc/winboll/studio/positions/services/MainService.java
@@ -9,6 +9,7 @@ import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.location.Location;
@@ -24,6 +25,7 @@ import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.ToastUtils;
import cc.winboll.studio.positions.models.PositionModel;
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.DistanceCalculatorUtil;
import cc.winboll.studio.positions.utils.NotificationUtil;
@@ -43,10 +45,7 @@ public class MainService extends Service {
public static final String EXTRA_IS_SETTING_TO_ENABLE = "EXTRA_IS_SETTING_TO_ENABLE";
// ---------------------- 定时器相关变量 ----------------------
- private ScheduledExecutorService taskCheckTimer; // 任务校验定时器
- private static final long TASK_CHECK_INTERVAL = 1; // 定时间隔(1分钟)
- private static final long TASK_CHECK_INIT_DELAY = 1; // 初始延迟(1分钟)
- // 新增:静止时GPS定时任务变量(Java 7 显式声明)
+ // 静止时GPS定时任务变量(Java 7 显式声明)
private ScheduledExecutorService gpsStaticTimer; // 静止时GPS定时获取线程池
private volatile boolean isGpsListening = false; // GPS是否处于持续监听状态
private static final long GPS_STATIC_DURATION = 3; // 静止时GPS单次获取超时时间(秒)
@@ -92,47 +91,15 @@ public class MainService extends Service {
private static volatile MainService sInstance;
private static Context sAppContext;
+ // 核心:运动状态Receiver(动态注册/注销,Java 7 显式声明)
+ private MotionStatusReceiver mMotionStatusReceiver;
+ private IntentFilter mMotionStatusFilter;
+
// =========================================================================
- // 定时器初始化方法(任务校验+静止GPS定时)
+ // 静止GPS定时任务方法(Java 7 语法)
// =========================================================================
- /*private void initTaskCheckTimer() {
- // 先销毁旧定时器(避免重复创建)
- if (taskCheckTimer != null && !taskCheckTimer.isShutdown()) {
- taskCheckTimer.shutdown();
- }
-
- // 创建单线程定时器(任务串行执行)
- taskCheckTimer = Executors.newSingleThreadScheduledExecutor();
- taskCheckTimer.scheduleAtFixedRate(new Runnable() {
- @Override
- public void run() {
- LogUtils.d(TAG, "定时任务触发:开始校验任务(间隔1分钟)");
- DistanceCalculatorUtil.getInstance(MainService.this).checkAllTaskTriggerCondition(MainService._mCurrentGpsPosition);
- }
- }, TASK_CHECK_INIT_DELAY, TASK_CHECK_INTERVAL, TimeUnit.MINUTES);
-
- LogUtils.d(TAG, "任务校验定时器已启动(间隔:" + TASK_CHECK_INTERVAL + "分钟)");
- }*/
-
- /*private void destroyTaskCheckTimer() {
- if (taskCheckTimer != null && !taskCheckTimer.isShutdown()) {
- taskCheckTimer.shutdown(); // 优雅关闭
- try {
- if (!taskCheckTimer.awaitTermination(1, TimeUnit.SECONDS)) {
- taskCheckTimer.shutdownNow(); // 强制关闭
- }
- } catch (InterruptedException e) {
- taskCheckTimer.shutdownNow();
- Thread.currentThread().interrupt(); // 恢复中断状态
- } finally {
- taskCheckTimer = null;
- LogUtils.d(TAG, "任务校验定时器已销毁");
- }
- }
- }*/
-
- // 新增:启动静止时GPS定时获取(Java 7 语法,无Lambda)
+ // 启动静止时GPS定时获取
public void startGpsStaticTimer(long interval) {
// 先销毁旧定时器(避免重复创建)
stopGpsStaticTimer();
@@ -150,7 +117,7 @@ public class MainService extends Service {
LogUtils.d(TAG, "静止时GPS定时任务已启动(间隔:" + interval + "分钟)");
}
- // 新增:停止静止时GPS定时任务
+ // 停止静止时GPS定时任务
public void stopGpsStaticTimer() {
if (gpsStaticTimer != null && !gpsStaticTimer.isShutdown()) {
gpsStaticTimer.shutdown();
@@ -168,7 +135,7 @@ public class MainService extends Service {
}
}
- // 新增:单次GPS获取(获取后关闭监听,Java 7 匿名内部类)
+ // 单次GPS获取(获取后关闭监听,Java 7 匿名内部类)
private void startSingleGpsRetrieve() {
if (!checkGpsReady()) {
LogUtils.w(TAG, "单次GPS获取:GPS未就绪,跳过");
@@ -379,7 +346,7 @@ public class MainService extends Service {
// =========================================================================
- // 原有基础方法(Java 7 语法适配)
+ // 服务基础方法(核心调整:动态注册/注销MotionStatusReceiver)
// =========================================================================
public static synchronized MainService getInstance(Context context) {
if (sInstance == null) {
@@ -418,15 +385,19 @@ public class MainService extends Service {
mMyServiceConnection = new MyServiceConnection();
}
+ // 初始化GPS监听(仅初始化,不启动)
+ //initGpsLocationListener();
+
if (mAppConfigsUtil.isEnableMainService(true)) {
run(); // 启动服务核心逻辑
}
}
+ // 服务核心运行方法(调整:启动服务时仅注册Receiver,不启动GPS)
public void run() {
if (mAppConfigsUtil.isEnableMainService(true)) {
if (!_mIsServiceRunning) {
- _mIsServiceRunning = true;
+ _mIsServiceRunning = true;
wakeupAndBindAssistant(); // 唤醒并绑定辅助服务
// 启动前台服务
@@ -435,25 +406,70 @@ public class MainService extends Service {
startForeground(NotificationUtil.FOREGROUND_SERVICE_NOTIFICATION_ID,
NotificationUtil.createForegroundServiceNotification(this, initialStatus));
- // 初始化GPS相关
+ // 初始化LocationManager(仅初始化,不启动GPS)
mLocationManager = (LocationManager) sInstance.getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
- initGpsLocationListener();
- startGpsLocation();
// 加载本地数据
PositionModel.loadBeanList(MainService.this, mPositionList, PositionModel.class);
PositionTaskModel.loadBeanList(MainService.this, mAllTasks, PositionTaskModel.class);
+ // 初始化运动状态Receiver(动态注册准备)
+ initMotionStatusReceiver();
+
+ // 动态注册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);
LogUtils.i(TAG, initialStatus);
-
- // 启动任务校验定时器
- //initTaskCheckTimer();
}
}
}
+ // 初始化运动状态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() {
return _mIsServiceRunning;
}
@@ -463,8 +479,12 @@ public class MainService extends Service {
super.onDestroy();
sInstance = null;
- // 清理资源
- stopGpsLocation();
+ // 核心清理:1.注销MotionStatusReceiver 2.关闭GPS 3.停止定时任务
+ unregisterMotionStatusReceiver(); // 注销Receiver,避免内存泄漏
+ stopGpsLocation(); // 强制关闭GPS监听
+ stopGpsStaticTimer(); // 停止静止时GPS定时任务
+
+ // 其他资源清理
clearAllData();
stopForeground(true);
@@ -474,9 +494,7 @@ public class MainService extends Service {
mTaskListeners.clear();
}
- // 销毁所有定时器与线程池
- //destroyTaskCheckTimer();
- stopGpsStaticTimer(); // 新增:销毁静止时GPS定时任务
+ // 销毁线程池
if (distanceExecutor != null && !distanceExecutor.isShutdown()) {
distanceExecutor.shutdown();
}
@@ -484,8 +502,9 @@ public class MainService extends Service {
// 重置状态变量
_mIsServiceRunning = false;
isGpsEnabled = false;
- isGpsListening = false; // 新增:重置GPS监听状态
+ isGpsListening = false;
mLocationManager = null;
+ LogUtils.d(TAG, "MainService 销毁完成,所有资源已清理");
}
@@ -500,7 +519,7 @@ public class MainService extends Service {
return _mCurrentGpsPosition;
}
- // 新增:判断GPS是否处于持续监听状态(给Receiver调用)
+ // 对外提供:判断GPS是否处于持续监听状态(给MotionStatusReceiver调用)
public boolean isGpsListening() {
return isGpsListening;
}
@@ -606,10 +625,10 @@ public class MainService extends Service {
}
// 格式化通知内容
final String gpsStatus = String.format(
- "GPS位置:北纬%.4f° 东经%.4f° | 可见位置:%d个",
- _mCurrentGpsPosition.getLatitude(),
- _mCurrentGpsPosition.getLongitude(),
- mVisiblePositionIds.size()
+ "GPS位置:北纬%.4f° 东经%.4f° | 可见位置:%d个",
+ _mCurrentGpsPosition.getLatitude(),
+ _mCurrentGpsPosition.getLongitude(),
+ mVisiblePositionIds.size()
);
// 主线程切换
if (Looper.myLooper() == Looper.getMainLooper()) {
@@ -634,7 +653,7 @@ public class MainService extends Service {
if (intent != null) {
isSettingToEnable = intent.getBooleanExtra(EXTRA_IS_SETTING_TO_ENABLE, false);
if (isSettingToEnable) {
- run(); // 重启服务核心逻辑
+ run(); // 重启服务核心逻辑(重新注册Receiver)
}
}
@@ -669,13 +688,14 @@ public class MainService extends Service {
// =========================================================================
- // GPS相关核心方法(Java 7 语法,匿名内部类实现)
+ // GPS相关核心方法(Java 7 语法,仅保留Receiver调用的启动/停止逻辑)
// =========================================================================
public MainService() {
distanceExecutor = Executors.newSingleThreadScheduledExecutor();
initGpsLocationListener();
}
+ // 初始化GPS监听(仅创建Listener,不注册)
private void initGpsLocationListener() {
LogUtils.d(TAG, "initGpsLocationListener");
mGpsLocationListener = new LocationListener() {
@@ -725,8 +745,8 @@ public class MainService extends Service {
String statusDesc = "GPS已开启(用户手动打开)";
LogUtils.d(TAG, statusDesc);
notifyAllGpsStatusListeners(statusDesc);
- updateNotificationGpsStatus("GPS已开启,正在获取位置...");
- startGpsLocation();
+ updateNotificationGpsStatus("GPS已开启,等待Receiver控制启动...");
+ // 不主动启动GPS,由Receiver根据运动状态控制
}
}
@@ -734,7 +754,7 @@ public class MainService extends Service {
public void onProviderDisabled(String provider) {
if (provider.equals(LocationManager.GPS_PROVIDER)) {
isGpsEnabled = false;
- isGpsListening = false; // 新增:GPS禁用时重置监听状态
+ isGpsListening = false;
_mCurrentGpsPosition = null;
String statusDesc = "GPS已关闭(用户手动关闭)";
LogUtils.w(TAG, statusDesc);
@@ -746,10 +766,11 @@ public class MainService extends Service {
};
}
+ // GPS就绪检查(给Receiver调用的GPS操作做前置判断)
private boolean checkGpsReady() {
// 检查定位权限
isGpsPermissionGranted = checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
- == PackageManager.PERMISSION_GRANTED;
+ == PackageManager.PERMISSION_GRANTED;
// 初始化LocationManager
if (mLocationManager == null) {
@@ -781,22 +802,23 @@ public class MainService extends Service {
return true;
}
+ // 启动GPS持续监听(仅Receiver可调用)
public void startGpsLocation() {
- if (!checkGpsReady()) {
+ if (!checkGpsReady() || isGpsListening) {
return;
}
try {
// 注册GPS位置更新
mLocationManager.requestLocationUpdates(
- LocationManager.GPS_PROVIDER,
- GPS_UPDATE_INTERVAL,
- GPS_UPDATE_DISTANCE,
- mGpsLocationListener,
- Looper.getMainLooper()
+ LocationManager.GPS_PROVIDER,
+ GPS_UPDATE_INTERVAL,
+ GPS_UPDATE_DISTANCE,
+ mGpsLocationListener,
+ Looper.getMainLooper()
);
- // 新增:标记GPS进入持续监听状态
+ // 标记GPS进入持续监听状态
isGpsListening = true;
// 获取最后已知GPS位置
@@ -820,17 +842,18 @@ public class MainService extends Service {
LogUtils.e(TAG, error);
notifyAllGpsStatusListeners(error);
isGpsPermissionGranted = false;
- isGpsListening = false; // 新增:异常时重置监听状态
+ isGpsListening = false;
updateNotificationGpsStatus("定位权限异常,无法获取GPS");
} catch (Exception e) {
String error = "启动GPS失败:" + e.getMessage();
LogUtils.e(TAG, error);
notifyAllGpsStatusListeners(error);
- isGpsListening = false; // 新增:异常时重置监听状态
+ isGpsListening = false;
updateNotificationGpsStatus("GPS启动失败,尝试重试...");
}
}
+ // 停止GPS持续监听(仅Receiver可调用)
public void stopGpsLocation() {
// 校验参数:避免空指针+权限未授予时调用
if (mLocationManager != null && mGpsLocationListener != null && isGpsPermissionGranted) {
@@ -839,12 +862,12 @@ public class MainService extends Service {
String tip = "GPS定位已停止(移除监听器)";
LogUtils.d(TAG, tip);
notifyAllGpsStatusListeners(tip);
- isGpsListening = false; // 新增:停止监听时重置状态
+ isGpsListening = false;
} catch (Exception e) {
String error = "停止GPS失败:" + e.getMessage();
LogUtils.e(TAG, error);
notifyAllGpsStatusListeners(error);
- isGpsListening = false; // 新增:异常时重置状态
+ isGpsListening = false;
}
}
}
@@ -857,12 +880,12 @@ public class MainService extends Service {
// 格式化通知内容
final String triggerContent = String.format(
- "任务触发:%s\n位置:%s\n当前距离:%.1f米(条件:%s%d米)",
- task.getTaskDescription(),
- bindPos.getMemo(),
- currentDistance,
- task.isGreaterThan() ? ">" : "<",
- task.getDiscussDistance()
+ "任务触发:%s\n位置:%s\n当前距离:%.1f米(条件:%s%d米)",
+ task.getTaskDescription(),
+ bindPos.getMemo(),
+ currentDistance,
+ task.isGreaterThan() ? ">" : "<",
+ task.getDiscussDistance()
);
// 更新前台通知
@@ -887,7 +910,7 @@ public class MainService extends Service {
// 更新前台通知的GPS状态
void updateNotificationGpsStatus(final String statusText) {
if (_mIsServiceRunning) {
- // 主线程判断+切换
+ // 主线程判断+切换(Java7匿名内部类)
if (Looper.myLooper() == Looper.getMainLooper()) {
NotificationUtil.updateForegroundServiceStatus(this, statusText);
} else {
@@ -903,7 +926,7 @@ public class MainService extends Service {
// =========================================================================
- // GPS监听通知相关方法(Java 7 语法)
+ // GPS监听通知相关方法(Java7语法,给外部监听者回调)
// =========================================================================
public void notifyAllGpsListeners(PositionModel currentGpsPos) {
if (currentGpsPos == null || mGpsListeners.isEmpty()) {
@@ -946,7 +969,7 @@ public class MainService extends Service {
WeakReference ref = iter.next();
final GpsUpdateListener listener = ref.get();
if (listener != null) {
- // 主线程切换,避免UI异常
+ // 主线程切换,避免UI异常(Java7匿名Runnable)
if (Looper.myLooper() == Looper.getMainLooper()) {
listener.onGpsStatusChanged(status);
} else {
@@ -999,7 +1022,7 @@ public class MainService extends Service {
// =========================================================================
- // LocalBinder 定义(与Activity绑定用,Java 7 内部类)
+ // LocalBinder 定义(与Activity绑定用,Java7内部类)
// =========================================================================
public class LocalBinder extends android.os.Binder {
private MainService mService;
@@ -1015,3 +1038,4 @@ public class MainService extends Service {
}
+