基本完成传感器陀螺仪启动,与接收器接收功能。

This commit is contained in:
ZhanGSKen
2025-11-04 20:56:31 +08:00
parent 2d3cee1121
commit 566e84f53f
4 changed files with 472 additions and 205 deletions

View File

@@ -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

View File

@@ -3,24 +3,24 @@
xmlns:android="http://schemas.android.com/apk/res/android"
package="cc.winboll.studio.positions">
<!-- 1. 声明GPS权限 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- 前台服务权限(可选,提升后台定位稳定性,避免服务被回收) -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- 只能在前台获取精确的位置信息 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!-- 只有在前台运行时才能获取大致位置信息 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<!-- 拥有完全的网络访问权限 -->
<uses-permission android:name="android.permission.INTERNET"/>
<!-- 在后台使用位置信息 -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
<!-- 运行前台服务 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<!-- 运行“location”类型的前台服务 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION"/>
<!-- 拥有完全的网络访问权限 -->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-feature
android:name="android.hardware.location.gps"
android:required="false"/>
@@ -59,22 +59,28 @@
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version"/>
<service android:name=".services.MainService"/>
<service
android:name=".services.MainService"
android:exported="false"/>
<service android:name=".services.AssistantService"/>
<service
android:name=".services.AssistantService"
android:exported="false"/>
<service android:name=".services.DistanceRefreshService"/>
<service
android:name=".services.DistanceRefreshService"
android:exported="false"/>
<receiver android:name="cc.winboll.studio.positions.receivers.MotionStatusReceiver">
<intent-filter>
<action android:name="cc.winboll.studio.positions.receivers.MotionStatusReceiver"/>
</intent-filter>
</receiver>
<!-- 2. 注册运动状态Receiver -->
<receiver
android:name="cc.winboll.studio.positions.receivers.MotionStatusReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="cc.winboll.studio.positions.ACTION_MOTION_STATUS" />
</intent-filter>
</receiver>
</application>
</manifest>

View File

@@ -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); // 强制停止传感器
}
}

View File

@@ -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<GpsUpdateListener> 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 {
}