定位功能调试记录(RouteTracker App)
Created|Updated
|Word Count:635|Reading Time:2mins|Post Views:
定位功能调试记录(RouteTracker App)
📅 日期
2025年4月3日
🧪 目标
实现 Android App 中基于 Google Maps 的实时定位功能,使用 FusedLocationProviderClient 获取设备位置并在地图上展示。
🧭 过程记录
✅ 地图与定位功能初步实现
- 使用
GoogleMap 成功加载地图;
- 使用
FusedLocationProviderClient 调用 requestLocationUpdates;
- 模拟器设置权限和配置正确;
- 日志打印如下:
1 2 3 4 5
| MAP: 地图准备好了 MAP: 权限检查通过 MAP: 准备启动 requestLocationUpdates MAP: 已经调用 requestLocationUpdates MAP: lastLocation 为 null
|
🛑 问题一:无定位更新
现象
- 地图加载正常,但始终没有位置回调;
- 日志中
lastLocation == null;
- 手动发送定位无效;
adb shell dumpsys location 显示所有 provider 都是 OFF 或无有效定位。
原因
- 使用的系统镜像为 x86_64 + API 36,但未正确配置模拟定位模块;
Extended Controls > Location 无法控制 GPS;
- 模拟器系统无 Google APIs 或定位模拟能力未启用。
解决方案
- 重新创建模拟器,选择 带 Google Play 或 Google APIs 的系统镜像;
- 确认 AVD 为
x86_64 架构;
- 启动新模拟器后,
adb shell dumpsys location 显示 fused provider 正常工作;
- 使用
Extended Controls > Location 成功发送模拟坐标,北京坐标展示成功 ✅。
🛑 问题二:App 闪退 onDestroy()
错误信息
1 2
| Caused by: java.lang.IllegalStateException: FragmentManager has been destroyed at com.example.routetracker.MapsActivity.onDestroy(MapsActivity.kt:151)
|
原因
- App 页面销毁后,仍尝试操作 fragment 或未清理
LocationCallback。
解决方案
在 MapsActivity.kt 的 onDestroy() 中添加:
1 2 3 4
| override fun onDestroy() { super.onDestroy() fusedLocationClient.removeLocationUpdates(locationCallback) }
|
✅ 最终状态
- 地图成功加载;
- 蓝点与精度圆在北京显示;
- 无闪退;
- 模拟器定位稳定更新。
🧩 关键代码片段
初始化 fusedLocationClient
1 2 3 4 5 6
| private lateinit var fusedLocationClient: FusedLocationProviderClient
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) fusedLocationClient = LocationServices.getFusedLocationProviderClient(this) }
|
配置 LocationRequest 和监听器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| val locationRequest = LocationRequest.Builder( Priority.PRIORITY_HIGH_ACCURACY, 3000 ) .setMinUpdateDistanceMeters(1f) .setGranularity(Granularity.GRANULARITY_FINE) .setWaitForAccurateLocation(false) .build()
val locationCallback = object : LocationCallback() { override fun onLocationResult(result: LocationResult) { for (location in result.locations) { Log.d("MAP", "📍 新位置:${location.latitude}, ${location.longitude}") } } }
|
启动监听
1 2 3 4 5 6 7 8 9 10 11
| val task = fusedLocationClient.requestLocationUpdates( locationRequest, locationCallback, Looper.getMainLooper() )
task.addOnSuccessListener { Log.d("MAP", "✅ requestLocationUpdates 注册成功") }.addOnFailureListener { Log.e("MAP", "❌ 注册失败:${it.message}", it) }
|
onDestroy 清理监听
1 2 3 4
| override fun onDestroy() { super.onDestroy() fusedLocationClient.removeLocationUpdates(locationCallback) }
|
📌 建议
- 后续定位采样建议使用高精度 + 合理间隔(如 3 秒 + 最小 1 米);
- 可以记录位置轨迹为
LatLng 列表,绘制 Polyline;
- 页面销毁时清理所有监听资源;
- 推荐使用
lifecycle-aware API(如 LifecycleService 或 LocationComponent)进行封装。