使用LocationManagerAPI实现的自定义位置追踪类无法正常工作
问题排查:NetworkLocationTracker始终返回0.0经纬度
我基于LocationManagerAPI写了一个NetworkLocationTracker类用来追踪手机位置,测试代码启动追踪后循环10次获取经纬度,但一直得到0.0、0.0的结果。已经开启定位服务,权限配置正确且无报错,求排查类中的问题。
类代码
import android.annotation.SuppressLint import android.content.Context import android.location.Location import android.location.LocationListener import android.location.LocationManager import android.util.Log class NetworkLocationTracker { private var latitude: Double = 0.0 private var longitude: Double = 0.0 private var locationManager: LocationManager private var locationListener: LocationListener? = null constructor(context: Context) { this.locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager this.locationListener = object : LocationListener { override fun onLocationChanged(location: Location) { setLatitude(location.latitude) setLongitude(location.longitude) } } } @SuppressLint("MissingPermission") fun startLocationTracking() { if(this.locationListener != null) { this.locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0L, 0f, this.locationListener as LocationListener) } } fun stopLocationTracking() { if (this.locationListener != null) { this.locationManager.removeUpdates(this.locationListener as LocationListener) this.locationListener = null } } fun getLatitude(): Double { return this.latitude } fun getLongitude(): Double { return this.longitude } fun setLatitude(latitude: Double) { this.latitude = latitude } fun setLongitude(longitude: Double) { this.longitude = longitude } }
测试代码
var nlt = NetworkLocationTracker(this) nlt.startLocationTracking() for(i in 1..10) { Thread.sleep(1000) Log.d("Debug", "${nlt.getLatitude()} ${nlt.getLongitude()}") } nlt.stopLocationTracking()
问题分析与修复方案
1. 未检查网络定位提供者可用性
调用requestLocationUpdates前,必须确认NETWORK_PROVIDER已被系统启用,否则不会触发位置回调。添加检查逻辑:
@SuppressLint("MissingPermission") fun startLocationTracking() { if (locationListener == null) return // 检查网络定位是否可用 val isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) if (!isNetworkEnabled) { Log.e("LocationTracker", "网络定位提供者未启用") return } locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0L, 0f, locationListener!!) // 同时获取最后已知位置 getLastKnownLocation() }
2. 未获取最后已知位置
位置更新回调可能存在延迟,启动追踪时先尝试读取缓存的最后位置,避免初始值一直为0.0:
@SuppressLint("MissingPermission") private fun getLastKnownLocation() { val lastLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER) lastLocation?.let { latitude = it.latitude longitude = it.longitude } }
3. 主线程阻塞导致回调无法执行
测试代码中的Thread.sleep(1000)如果在主线程执行,会阻塞UI线程,导致LocationListener的回调无法被调度执行。改用协程实现延迟读取(需依赖kotlinx-coroutines-android):
lifecycleScope.launch { val nlt = NetworkLocationTracker(this@MainActivity) nlt.startLocationTracking() repeat(10) { delay(1000) Log.d("Debug", "${nlt.getLatitude()} ${nlt.getLongitude()}") } nlt.stopLocationTracking() }
4. 线程安全问题
latitude和longitude在回调线程和读取线程之间共享,没有可见性保证,需要用volatile修饰:
@Volatile private var latitude: Double = 0.0 @Volatile private var longitude: Double = 0.0
5. 适配过时的LocationListener方法
onLocationChanged(Location)已过时,建议替换为新的回调方法:
this.locationListener = object : LocationListener { override fun onLocationChanged(locations: List<Location>) { locations.firstOrNull()?.let { latitude = it.latitude longitude = it.longitude } } // 实现其他必需的过时方法(可留空) @Deprecated("Deprecated in Java") override fun onLocationChanged(location: Location) {} override fun onStatusChanged(provider: String?, status: Int, extras: Bundle?) {} override fun onProviderEnabled(provider: String) {} override fun onProviderDisabled(provider: String) {} }
修改后的完整类代码
import android.annotation.SuppressLint import android.content.Context import android.location.Location import android.location.LocationListener import android.location.LocationManager import android.os.Bundle import android.util.Log class NetworkLocationTracker(private val context: Context) { @Volatile private var latitude: Double = 0.0 @Volatile private var longitude: Double = 0.0 private val locationManager: LocationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager private var locationListener: LocationListener? = null @SuppressLint("MissingPermission") fun startLocationTracking() { if (locationListener != null) stopLocationTracking() val isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) if (!isNetworkEnabled) { Log.e("LocationTracker", "网络定位提供者未启用") return } locationListener = object : LocationListener { override fun onLocationChanged(locations: List<Location>) { locations.firstOrNull()?.let { latitude = it.latitude longitude = it.longitude Log.d("LocationTracker", "位置更新:${it.latitude}, ${it.longitude}") } } @Deprecated("Deprecated in Java") override fun onLocationChanged(location: Location) {} override fun onStatusChanged(provider: String?, status: Int, extras: Bundle?) {} override fun onProviderEnabled(provider: String) {} override fun onProviderDisabled(provider: String) {} } locationManager.requestLocationUpdates( LocationManager.NETWORK_PROVIDER, 0L, 0f, locationListener!! ) // 获取最后已知位置 getLastKnownLocation() } @SuppressLint("MissingPermission") private fun getLastKnownLocation() { val lastLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER) lastLocation?.let { latitude = it.latitude longitude = it.longitude Log.d("LocationTracker", "最后已知位置:${it.latitude}, ${it.longitude}") } } fun stopLocationTracking() { locationListener?.let { locationManager.removeUpdates(it) locationListener = null } } fun getLatitude(): Double = latitude fun getLongitude(): Double = longitude }
内容的提问来源于stack exchange,提问作者Phisma
相关产品推荐
相关产品推荐

