开启服务后实时位置更新完成

This commit is contained in:
ZhanGSKen
2025-10-01 20:27:02 +08:00
parent 70a5405077
commit 829268a9cc
4 changed files with 437 additions and 3 deletions

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Wed Oct 01 08:48:18 GMT 2025
#Wed Oct 01 12:10:23 GMT 2025
stageCount=4
libraryProject=
baseVersion=15.0
publishVersion=15.0.3
buildCount=56
buildCount=58
baseBetaVersion=15.0.4

View File

@@ -49,6 +49,7 @@ public class App extends GlobalApplication {
@Override
public void onCreate() {
super.onCreate();
setIsDebuging(BuildConfig.DEBUG);
// 初始化 Toast 框架
ToastUtils.init(this);

View File

@@ -1 +1,433 @@
//package cc.winboll.studio.positions.services;
//
///**
// * @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
// * @Date 2025/09/30 19:53
// * @Describe 位置距离服务:管理数据+定时计算距离+适配AdapterJava 7 兼容)+ GPS信号加载
// */
//import android.app.Service;
//import android.content.Context;
//import android.content.Intent;
//import android.content.pm.PackageManager;
//import android.location.Location;
//import android.location.LocationListener;
//import android.location.LocationManager;
//import android.os.Binder;
//import android.os.Build;
//import android.os.Bundle;
//import android.os.IBinder;
//import android.os.Looper;
//import android.widget.Toast;
//import cc.winboll.studio.libappbase.LogUtils;
//import cc.winboll.studio.positions.adapters.PositionAdapter;
//import cc.winboll.studio.positions.models.AppConfigsModel;
//import cc.winboll.studio.positions.models.PositionModel;
//import cc.winboll.studio.positions.models.PositionTaskModel;
//import cc.winboll.studio.positions.utils.NotificationUtil;
//import java.util.ArrayList;
//import java.util.HashSet;
//import java.util.Iterator;
//import java.util.Set;
//import java.util.concurrent.Executors;
//import java.util.concurrent.ScheduledExecutorService;
//import java.util.concurrent.TimeUnit;
//
///**
// * 核心职责:
// * 1. 实现 PositionAdapter.DistanceServiceInterface 接口解耦Adapter与服务
// * 2. 单例式管理位置/任务数据,提供安全增删改查接口
// * 3. 后台单线程定时计算可见位置距离主线程回调更新UI
// * 4. 内置GPS信号加载通过LocationManager实时获取位置解决“等待GPS信号”问题
// * 5. 服务启动时启动前台通知保活后台GPS功能符合系统规范
// * 6. 严格Java 7语法无Lambda/Stream显式迭代器/匿名内部类
// */
//public class DistanceRefreshService extends Service {
// public static final String TAG = "DistanceRefreshService";
//
//
// // 服务状态与配置
// private boolean isServiceRunning = false;
//
// private static final int REFRESH_INTERVAL = 3; // 距离刷新间隔(秒)
// // 前台通知相关记录是否已启动前台服务避免重复调用startForeground
// private boolean isForegroundServiceStarted = false;
//
//
//
// // 服务绑定与UI回调
// private final IBinder mBinder = new DistanceBinder();
//
//
//
//
// /**
// * 在主线程显示Toast避免子线程无法显示Toast的问题
// */
// private void showToastOnMainThread(final String message) {
// if (Looper.myLooper() == Looper.getMainLooper()) {
// Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
// } else {
// new android.os.Handler(Looper.getMainLooper()).post(new Runnable() {
// @Override
// public void run() {
// Toast.makeText(DistanceRefreshService.this, message, Toast.LENGTH_SHORT).show();
// }
// });
// }
// }
//
// // ---------------------- Binder 内部类(供外部绑定服务) ----------------------
// public class DistanceBinder extends Binder {
// /**
// * 外部绑定后获取服务实例(安全暴露服务引用)
// */
// public DistanceRefreshService getService() {
// return DistanceRefreshService.this;
// }
// }
//
//
//
// @Override
// public void onCreate() {
// super.onCreate();
//
// // 初始化GPS管理器提前获取系统服务避免启动时延迟
// mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
// LogUtils.d(TAG, "服务 onCreate初始化完成等待启动命令");
// run();
// }
//
// @Override
// public int onStartCommand(Intent intent, int flags, int startId) {
// run();
// AppConfigsModel bean = AppConfigsModel.loadBean(DistanceRefreshService.this, AppConfigsModel.class);
// boolean isEnableService = (bean == null) ? false : bean.isEnableMainService();
// // 服务启用时返回START_STICKY被杀死后尝试重启禁用时返回默认值
// return isEnableService ? Service.START_STICKY : super.onStartCommand(intent, flags, startId);
// }
//
// public void run() {
// // 仅服务未运行时启动(避免重复启动)
// if (!isServiceRunning) {
// isServiceRunning = true;
//
//
//
// startDistanceRefreshTask(); // 启动定时距离计算
// startForegroundNotification(); // 启动前台通知
//
// LogUtils.d(TAG, "服务 onStartCommand启动成功刷新间隔=" + REFRESH_INTERVAL + "秒,前台通知+GPS已启动");
// } else {
// LogUtils.w(TAG, "服务 onStartCommand已在运行无需重复启动前台通知" + (isForegroundServiceStarted ? "已启动" : "未启动") + " | GPS" + (isGpsEnabled ? "已开启" : "未开启") + "");
// // 异常场景恢复:补全未启动的组件
// if (!isForegroundServiceStarted) {
// startForegroundNotification();
// LogUtils.d(TAG, "服务 run前台通知未启动已恢复");
// }
// if (isServiceRunning && !isGpsEnabled) {
// startGpsLocation();
// LogUtils.d(TAG, "服务 runGPS未启动已恢复");
// }
// }
// }
//
// @Override
// public IBinder onBind(Intent intent) {
// return null; // 按你的业务逻辑返回无绑定需求则保留null
// //LogUtils.d(TAG, "服务 onBind外部绑定成功运行状态" + (isServiceRunning ? "是" : "否") + " | GPS状态" + (isGpsEnabled ? "可用" : "不可用") + "");
// //return mBinder; // 返回Binder实例供外部获取服务
// }
//
// /*@Override
// public boolean onUnbind(Intent intent) {
// LogUtils.d(TAG, "服务 onUnbind外部解绑清理回调与可见位置");
// // 解绑后清理资源,避免内存泄漏
// mDistanceReceiver = null;
// mVisiblePositionIds.clear();
// // 解绑时不停止GPS服务仍在后台运行需持续获取位置
// return super.onUnbind(intent);
// }*/
//
// @Override
// public void onDestroy() {
// super.onDestroy();
//
// LogUtils.d(TAG, "服务 onDestroy销毁完成资源已释放GPS+前台通知+线程池)");
// }
//
// // ---------------------- 前台服务通知管理与GPS状态联动优化 ----------------------
// /**
// * 启动前台服务通知调用NotificationUtils创建通知确保仅启动一次
// */
// private void startForegroundNotification() {
// // 1. 校验避免重复调用startForeground系统不允许重复启动
// if (isForegroundServiceStarted) {
// LogUtils.w(TAG, "startForegroundNotification前台通知已启动无需重复执行");
// return;
// }
//
// try {
//// 2. 初始化通知状态文本根据GPS初始状态动态显示避免固定“等待”
// String initialStatus;
// if (isGpsPermissionGranted && isGpsEnabled) {
// initialStatus = "GPS已就绪正在获取位置刷新间隔" + REFRESH_INTERVAL + "秒)";
// } else if (!isGpsPermissionGranted) {
// initialStatus = "缺少定位权限无法获取GPS位置";
// } else {
// initialStatus = "GPS未开启请在设置中打开";
// }
//
//
//// 5. 标记前台服务已启动
// isForegroundServiceStarted = true;
// LogUtils.d(TAG, "startForegroundNotification前台服务通知启动成功初始状态" + initialStatus);
//
// } catch (Exception e) {
//// 捕获异常(如上下文失效、通知渠道未创建)
// isForegroundServiceStarted = false;
// LogUtils.d(TAG, "startForegroundNotification前台通知启动失败" + e);
// }
// }
//
//
//
// /**
//
// - 主线程回调Adapter更新UI避免跨线程操作UI异常
// */
// /*private void notifyDistanceUpdateToUI(final String positionId) {
// if (Looper.myLooper() == Looper.getMainLooper()) {
// if (mDistanceReceiver != null) {
// mDistanceReceiver.onDistanceUpdate(positionId);
// }
// } else {
// new android.os.Handler(Looper.getMainLooper()).post(new Runnable() {
// @Override
// public void run() {
// if (mDistanceReceiver != null) {
// mDistanceReceiver.onDistanceUpdate(positionId);
// }
// }
// });
// }
// }*/
//
//
//
//
//
//// ---------------------- 实现 PositionAdapter.DistanceServiceInterface 接口 ----------------------
//
// public ArrayList getPositionList() {
// if (!isServiceRunning) {
// LogUtils.w(TAG, "getPositionList服务未运行返回空列表");
// return new ArrayList();
// }
// return new ArrayList(mPositionList);
// }
//
//
// public ArrayList getPositionTasksList() {
// if (!isServiceRunning) {
// LogUtils.w(TAG, "getPositionTasksList服务未运行返回空列表");
// return new ArrayList();
// }
// return new ArrayList(mTaskList);
// }
//
//
//
//
// /*public void setOnDistanceUpdateReceiver(PositionAdapter.OnDistanceUpdateReceiver receiver) {
// this.mDistanceReceiver = receiver;
// LogUtils.d(TAG, "setOnDistanceUpdateReceiver回调接收器已设置" + (receiver != null ? "有效" : "无效") + "");
// }*/
//
// public void addVisibleDistanceView(String positionId) {
// if (!isServiceRunning || positionId == null) {
// LogUtils.w(TAG, "addVisibleDistanceView服务未运行/位置ID无效添加失败");
// return;
// }
// if (mVisiblePositionIds.add(positionId)) {
// LogUtils.d(TAG, "addVisibleDistanceView添加成功位置ID=" + positionId + ",当前可见数=" + mVisiblePositionIds.size() + "");
//// 新增:添加可见位置后,立即更新通知(显示最新可见数量)
// if (isForegroundServiceStarted && mCurrentGpsPosition != null) {
// syncGpsStatusToNotification();
// }
// }
// }
//
// public void removeVisibleDistanceView(String positionId) {
// if (positionId == null) {
// LogUtils.w(TAG, "removeVisibleDistanceView位置ID为空移除失败");
// return;
// }
// if (mVisiblePositionIds.remove(positionId)) {
// int remainingCount = mVisiblePositionIds.size();
// LogUtils.d(TAG, "removeVisibleDistanceView移除成功位置ID=" + positionId + ",当前可见数=" + remainingCount + "");
//// 新增:移除可见位置后,更新通知(同步数量变化)
// if (isForegroundServiceStarted && mCurrentGpsPosition != null) {
// syncGpsStatusToNotification();
// }
// }
// }
//
// public void clearVisibleDistanceViews() {
// mVisiblePositionIds.clear();
// LogUtils.d(TAG, "clearVisibleDistanceViews所有可见位置已清空");
//// 新增:清空可见位置后,更新通知(提示计算暂停)
// if (isForegroundServiceStarted) {
// updateNotificationGpsStatus("无可见位置,距离计算暂停");
// }
// }
//
//// ---------------------- 数据管理接口(修复原有语法错误+优化逻辑) ----------------------
// /**
//
// - 获取服务运行状态
// */
// public boolean isServiceRunning() {
// return isServiceRunning;
// }
//
// /**
//
// - 添加位置(修复迭代器泛型缺失问题)
// */
// public void addPosition(PositionModel position) {
// if (!isServiceRunning || position == null || position.getPositionId() == null) {
// LogUtils.w(TAG, "addPosition服务未运行/数据无效,添加失败");
// return;
// }// 修复显式声明PositionModel泛型避免类型转换警告
// boolean isDuplicate = false;
// Iterator posIter = mPositionList.iterator();
// while (posIter.hasNext()) {
// PositionModel existingPos = (PositionModel)posIter.next();
// if (position.getPositionId().equals(existingPos.getPositionId())) {
// isDuplicate = true;
// break;
// }
// }if (!isDuplicate) {
// mPositionList.add(position);
// LogUtils.d(TAG, "addPosition添加成功位置ID=" + position.getPositionId() + ",总数=" + mPositionList.size() + "");
// } else {
// LogUtils.w(TAG, "addPosition位置ID=" + position.getPositionId() + "已存在,添加失败");
// }
// }
//
// /**
//
// - 删除位置(修复任务删除时的类型转换错误)
// */
// public void removePosition(String positionId) {
// if (!isServiceRunning || positionId == null) {
// LogUtils.w(TAG, "removePosition服务未运行/位置ID无效删除失败");
// return;
// }// 1. 删除位置
// boolean isRemoved = false;
// Iterator posIter = mPositionList.iterator();
// while (posIter.hasNext()) {
// PositionModel pos = (PositionModel)posIter.next();
// if (positionId.equals(pos.getPositionId())) {
// posIter.remove();
// isRemoved = true;
// break;
// }
// }if (isRemoved) {
//// 修复任务列表迭代时用PositionTaskModel泛型原错误用PositionModel导致转换失败
// Iterator taskIter = mTaskList.iterator();
// while (taskIter.hasNext()) {
// PositionTaskModel task = (PositionTaskModel)taskIter.next();
// if (positionId.equals(task.getPositionId())) {
// taskIter.remove();
// }
// }// 3. 移除可见位置
// mVisiblePositionIds.remove(positionId);
// LogUtils.d(TAG, "removePosition删除成功位置ID=" + positionId + ",剩余位置数=" + mPositionList.size() + ",剩余任务数=" + mTaskList.size() + "");
// } else {
// LogUtils.w(TAG, "removePosition位置ID=" + positionId + "不存在,删除失败");
// }
// }
//
// /**
//
// - 更新位置信息(修复代码格式+迭代器泛型)
// */
// public void updatePosition(PositionModel updatedPosition) {
// if (!isServiceRunning || updatedPosition == null || updatedPosition.getPositionId() == null) {
// LogUtils.w(TAG, "updatePosition服务未运行/数据无效,更新失败");
// return;
// }boolean isUpdated = false;
// Iterator posIter = mPositionList.iterator();
// while (posIter.hasNext()) {
// PositionModel pos = (PositionModel)posIter.next();
// if (updatedPosition.getPositionId().equals(pos.getPositionId())) {
// pos.setMemo(updatedPosition.getMemo());
// pos.setIsEnableRealPositionDistance(updatedPosition.isEnableRealPositionDistance());
// if (!updatedPosition.isEnableRealPositionDistance()) {
// pos.setRealPositionDistance(-1);
// //notifyDistanceUpdateToUI(pos.getPositionId());
// }
// isUpdated = true;
// break;
// }
// }if (isUpdated) {
// LogUtils.d(TAG, "updatePosition更新成功位置ID=" + updatedPosition.getPositionId() + "");
// } else {
// LogUtils.w(TAG, "updatePosition位置ID=" + updatedPosition.getPositionId() + "不存在,更新失败");
// }
// }
//
// /**
//
// - 同步任务列表(修复泛型缺失+代码格式)
// */
// public void syncAllPositionTasks(ArrayList tasks) {
// if (!isServiceRunning || tasks == null) {
// LogUtils.w(TAG, "syncAllPositionTasks服务未运行/任务列表为空,同步失败");
// return;
// }// 1. 清空旧任务
// mTaskList.clear();
//// 2. 添加新任务(修复泛型+去重逻辑)
// Set taskIdSet = new HashSet();
// Iterator taskIter = tasks.iterator();
// while (taskIter.hasNext()) {
// PositionTaskModel task = (PositionTaskModel)taskIter.next();
// if (task != null && task.getTaskId() != null && !taskIdSet.contains(task.getTaskId())) {
// taskIdSet.add(task.getTaskId());
// mTaskList.add(task);
// }
// }LogUtils.d(TAG, "syncAllPositionTasks同步成功接收任务数=" + tasks.size() + ",去重后=" + mTaskList.size() + "");
// }
//
//
//
//
//// ---------------------- 补充修复LocationProvider引用缺失问题避免编译错误 ----------------------
//// 注原代码中onStatusChanged使用LocationProvider枚举需补充静态导入或显式声明
//// 此处通过内部静态类定义解决系统API引用问题兼容Java 7语法
// private static class LocationProvider {
// public static final int AVAILABLE = 2;
// public static final int OUT_OF_SERVICE = 0;
// public static final int TEMPORARILY_UNAVAILABLE = 1;
// }
//
//// ---------------------- 补充Context引用工具避免服务销毁后Context失效 ----------------------
// /*private Context getSafeContext() {
// // 服务未销毁时返回自身Context已销毁时返回应用Context避免内存泄漏
// if (isDestroyed()) {
// return getApplicationContext();
// }
// return this;
// }*/
//
//// 注isDestroyed()为API 17+方法,若需兼容更低版本,可添加版本判断
// /*private boolean isDestroyed() {
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
// return super.isDestroyed();
// }
// // 低版本通过状态标记间接判断服务销毁时会置为false
// return !isServiceRunning && !isForegroundServiceStarted;
// }*/
//}

View File

@@ -410,6 +410,7 @@ public class MainService extends Service {
* 初始化GPS位置监听器系统GPS位置变化时触发实时更新当前位置
*/
private void initGpsLocationListener() {
LogUtils.d(TAG, "initGpsLocationListener()");
// Java 7 匿名内部类实现 LocationListener接收GPS位置回调
mGpsLocationListener = new LocationListener() {
// GPS位置发生变化时回调核心更新当前GPS位置