You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 05:43:27