Compare commits
	
		
			5 Commits
		
	
	
		
			377ec4de09
			...
			positions-
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 2d3cee1121 | |||
|   | 2be6d5e122 | ||
| 6376ff4ccf | |||
|   | dd20060754 | ||
|   | 298b337392 | 
| @@ -1,8 +1,8 @@ | ||||
| #Created by .winboll/winboll_app_build.gradle | ||||
| #Tue Oct 28 13:36:57 HKT 2025 | ||||
| stageCount=16 | ||||
| #Tue Oct 28 20:03:59 HKT 2025 | ||||
| stageCount=18 | ||||
| libraryProject= | ||||
| baseVersion=15.0 | ||||
| publishVersion=15.0.15 | ||||
| publishVersion=15.0.17 | ||||
| buildCount=0 | ||||
| baseBetaVersion=15.0.16 | ||||
| baseBetaVersion=15.0.18 | ||||
|   | ||||
| @@ -3,6 +3,9 @@ | ||||
|     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" /> | ||||
|  | ||||
| @@ -61,6 +64,17 @@ | ||||
|         <service android:name=".services.AssistantService"/> | ||||
|  | ||||
|         <service android:name=".services.DistanceRefreshService"/> | ||||
|  | ||||
|  | ||||
| 		<!-- 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> | ||||
|   | ||||
| @@ -0,0 +1,124 @@ | ||||
| package cc.winboll.studio.positions.receivers; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen&豆包大模型<zhangsken@qq.com> | ||||
|  * @Date 2025/10/28 19:07 | ||||
|  * @Describe MotionStatusReceiver | ||||
|  */ | ||||
| import android.content.BroadcastReceiver; | ||||
| import android.content.Context; | ||||
| import android.content.Intent; | ||||
| import android.content.pm.PackageManager; | ||||
| import android.os.Build; | ||||
| import android.text.TextUtils; | ||||
| import cc.winboll.studio.libappbase.LogUtils; | ||||
| import cc.winboll.studio.positions.services.MainService; | ||||
| import cc.winboll.studio.positions.utils.ServiceUtil; | ||||
|  | ||||
| /** | ||||
|  * 运动状态监听Receiver | ||||
|  * 功能:接收运动状态广播,控制GPS权限申请与GPS监听开关 | ||||
|  */ | ||||
| public class MotionStatusReceiver extends BroadcastReceiver { | ||||
| 	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; | ||||
|  | ||||
| 	@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; | ||||
| 		} | ||||
|  | ||||
| 		// 1. 获取运动状态(0=静止/低运动,1=行走/高运动) | ||||
| 		int motionStatus = intent.getIntExtra(EXTRA_MOTION_STATUS, 0); | ||||
| 		LogUtils.d(TAG, "接收运动状态:" + (motionStatus == 1 ? "行走中" : "静止/低运动")); | ||||
|  | ||||
| 		// 2. 绑定并获取MainService实例(确保服务已启动) | ||||
| 		MainService mainService = getMainService(context); | ||||
| 		if (mainService == null) { | ||||
| 			LogUtils.e(TAG, "MainService未启动,无法控制GPS状态"); | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		// 3. 根据运动状态处理GPS逻辑 | ||||
| 		if (motionStatus == 1) { | ||||
| 			// 3.1 行走中:申请GPS权限(若未授予)+ 开启持续GPS监听 | ||||
| 			handleWalkingStatus(mainService, context); | ||||
| 		} else { | ||||
| 			// 3.2 静止/低运动:关闭持续GPS监听 + 启动定时GPS获取 | ||||
| 			handleStaticStatus(mainService); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * 处理行走状态:申请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; | ||||
| 		} | ||||
|  | ||||
| 		// 权限已授予:开启持续GPS监听(调用MainService原有方法) | ||||
| 		if (!mainService.isGpsListening()) { // 需在MainService中新增isGpsListening()方法 | ||||
| 			mainService.startGpsLocation(); | ||||
| 			LogUtils.d(TAG, "行走中:已开启持续GPS监听"); | ||||
| 		} | ||||
|  | ||||
| 		// 停止静止时的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(); | ||||
| 			} | ||||
| 		} | ||||
| 		return MainService.getInstance(context); | ||||
| 	} | ||||
| } | ||||
|  | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -111,17 +111,15 @@ public class DistanceCalculatorUtil { | ||||
| 			LogUtils.d(TAG, "传入坐标参数为空,退出函数。"); | ||||
| 			return; | ||||
| 		} | ||||
| 		if (mGpsPositionCalculated == null) { | ||||
| 			mGpsPositionCalculated = currentGpsPosition; | ||||
| 			LogUtils.d(TAG, "最后计算位置记录为空,现在使用新坐标为初始化。"); | ||||
| 		} | ||||
|  | ||||
| 		// 计算频率控制模块 | ||||
| 		// | ||||
| 		// 计算与最近一次GPS计算的时间间隔 | ||||
| 		long nCalculatedTimeBettween = System.currentTimeMillis() - mLastCalculatedTime; | ||||
| 		// 计算跳跃距离 | ||||
| 		double jumpDistance = calculateHaversineDistance(mGpsPositionCalculated.getLatitude(), mGpsPositionCalculated.getLongitude(), currentGpsPosition.getLatitude(), currentGpsPosition.getLongitude()); | ||||
| 		double gpsPositionCalculatedLatitude = mGpsPositionCalculated == null ?0.0f: mGpsPositionCalculated.getLatitude(); | ||||
| 		double gpsPositionCalculatedLongitude = mGpsPositionCalculated == null ?0.0f: mGpsPositionCalculated.getLongitude(); | ||||
| 		double jumpDistance = calculateHaversineDistance(gpsPositionCalculatedLatitude, gpsPositionCalculatedLongitude, currentGpsPosition.getLatitude(), currentGpsPosition.getLongitude()); | ||||
| 		if (jumpDistance < mMinjumpDistance) { | ||||
| 			LogUtils.d(TAG, String.format("checkAllTaskTriggerCondition:跳跃距离%f,小于50米。", jumpDistance)); | ||||
| 			// 跳跃距离小于最小有效跳跃值 | ||||
| @@ -132,22 +130,33 @@ public class DistanceCalculatorUtil { | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		LogUtils.d(TAG, String.format("checkAllTaskTriggerCondition:跳跃距离%f,与上次计算间隔%d,启动任务数据计算。", jumpDistance, nCalculatedTimeBettween)); | ||||
| 		if (mGpsPositionCalculated == null) { | ||||
| 			mGpsPositionCalculated = currentGpsPosition; | ||||
| 			LogUtils.d(TAG, "最后计算位置记录为空,现在使用新坐标为初始化。"); | ||||
| 		} | ||||
|  | ||||
| 		LogUtils.d(TAG, String.format("checkAllTaskTriggerCondition:跳跃距离%f,与上次计算间隔%d,现在启动任务数据计算。", jumpDistance, nCalculatedTimeBettween)); | ||||
|  | ||||
| 		// 获取位置任务基础数据 | ||||
| 		MainService mainService = MainService.getInstance(mContext); | ||||
| 		mPositionList = mainService.getPositionList(); | ||||
| 		mAllTasks = mainService.getAllTasks(); | ||||
|  | ||||
| 		// 任务为空,跳过校验。 | ||||
|         if (mPositionList.isEmpty() || mAllTasks.isEmpty()) { | ||||
|             LogUtils.d(TAG, "checkAllTaskTriggerCondition:任务数据为空,跳过校验。"); | ||||
| 		// 位置数据为空,跳过校验。 | ||||
|         if (mPositionList.isEmpty()) { | ||||
|             LogUtils.d(TAG, "checkAllTaskTriggerCondition:位置数据为空,跳过距离计算。"); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
| 		// 更新所有位置点的位置距离数据 | ||||
| 		refreshRealPositionDistance(currentGpsPosition); | ||||
|  | ||||
| 		// 任务数据为空,跳过校验。 | ||||
|         if (mAllTasks.isEmpty()) { | ||||
|             LogUtils.d(TAG, "checkAllTaskTriggerCondition:任务数据为空,跳过任务提醒检查计算。"); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // 迭代器遍历任务(Java 7 安全遍历,避免并发修改异常) | ||||
|         Iterator<PositionTaskModel> taskIter = mAllTasks.iterator(); | ||||
|         while (taskIter.hasNext()) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user