如何实现GPS状态变化监听器

9
在我的应用程序中,我每5分钟向服务器发送位置更新。为此,我使用gms LocationListener。这很好用。我在服务内运行它。如果用户关闭了GPS,则它将无法工作。即使在打开GPS后仍在服务中运行,它也将等待完成5分钟的更新时间。因此,当用户打开GPS时,我希望它可以触发onLocationUpdate Listener。
为此,我已经在我的服务中初始化了GpsStatus.Listener,并实现了onStatusChange()函数,但是在我从打开到关闭/关闭到打开GPS状态之后,该函数没有触发。 代码:
public class LocationUpdateService extends Service implements GpsStatus.Listener, com.google.android.gms.location.LocationListener{
    onCreate(Bundle b){
        super.onCreate();
        registerGpsStatusListener();
    }

    private void registerGpsStatusListener() {
        LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        locationManager.addGpsStatusListener(this);
    }

    @Override
    public void onGpsStatusChanged(int event) {
        switch (event) {
            case GpsStatus.GPS_EVENT_STARTED:
                Log.e(TAG, "onGpsStatusChanged started");
                break;

            case GpsStatus.GPS_EVENT_STOPPED:
                Log.e(TAG, "onGpsStatusChanged stopped");
                break;

            case GpsStatus.GPS_EVENT_FIRST_FIX:
                Log.e(TAG, "onGpsStatusChanged first fix");
                break;

            case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
                Log.e(TAG, "onGpsStatusChanged status");
                break;
        }
    }

    @Override
    public void onLocationChanged(Location location) {
       //opertations
    }
}

我的问题如下:

1- 为什么改变GPS状态后,方法onGpsStatusChanged()没有调用。

2- 如何在onLocationChanged()方法中获取位置,以便我可以调用onLocationUpdate()方法。

注意:请不要建议使用BroadcastReceiver,因为它需要对我的当前代码进行大量修改。


我猜你可能不会喜欢这个答案。如果感兴趣,可以使用ReactiveLocation https://github.com/mcharmas/Android-ReactiveLocation - Ravi Gadipudi
GPS状态监听器是关于GPS服务在开启一段时间后发生的情况。要查看GPS是否已经打开,您需要使用LocationListener.isProviderEnabled()。请参考这里的答案:https://dev59.com/hHXYa4cB1Zd3GeqP9rtP - panonski
第二个问题我不是很理解。(Location location) 是你接收新位置的地方。然后你可以处理数据并执行像 location.getLatitude() 等操作... - panonski
4个回答

3

我想您正在尝试了解用户何时从设备上开启或关闭GPS。在这种情况下,您可以查看答案。这是检测GPS开/关开关的唯一正确且可靠的方法(至少对我来说是唯一有效的方法)。


我正在寻找除广播接收器之外的更好解决方案。 - droidev
更好的解决方案?在哪方面更好?我花了很多时间研究GPS,但是我找不到更好的解决方案。广播接收器方案是最可靠且完美运作的。如果你找到了更好的方案,请发帖分享。 - varunkr
但是当任何位置提供程序连接时,将触发 PROVIDERS_CHANGED 广播,不是吗? - droidev
@varunkr,“更好” == “更简单” ;) - angryITguy
@varunkr:当您打开虚假GPS应用程序时,您无法通过广播接收器听到GPS切换。 - Hai nguyen

3
我建议您使用谷歌位置服务而不是位置管理器。例如,使用这个LocationSimpleTracker,您可以轻松检测GPS状态和上次位置。
data class LocationSimpleTracker(val context: Context) {
    private val fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(context)
    private var locationCallback: LocationCallback? = null

    fun detectGPS(onGPSChanged: (Boolean) -> Unit) {
        locationCallback = object : LocationCallback() {

            override fun onLocationAvailability(var1: LocationAvailability?) {
                Timber.i("GPS enabled: ${var1?.isLocationAvailable}")
                onGPSChanged(var1?.isLocationAvailable ?: false)
            }

            override fun onLocationResult(result: LocationResult?) {
                Timber.i("New location: ${result?.lastLocation}")
            }
        }
        fusedLocationProviderClient.requestLocationUpdates(buildLocationRequest(), locationCallback, null)
    }

    private fun buildLocationRequest(): LocationRequest = LocationRequest.create().apply {
        priority = LocationRequest.PRIORITY_HIGH_ACCURACY
        interval = 5000 //5 seconds
        fastestInterval = 5000 //5 seconds
        maxWaitTime = 1000 //1 seconds
    }

    fun stop() {
        fusedLocationProviderClient.removeLocationUpdates(locationCallback)
    }
}

在你的活动中创建一个实例。祝你好运。

1

在设置完GpsStatus.Listener后,您需要将该侦听器添加到LocationManager中。

locationManager.addGpsStatusListener(yourGpsStatusListener);

1
对于 Android 24 API(N)及更高版本,它是 locationManager.registerGnssStatusCallback(listener) - user924

1
对于所有的Android版本(直至当前的30 API):
private val locationManager: LocationManager = context
    .getSystemService(Context.LOCATION_SERVICE) as LocationManager

private var gpsStatusListener: Any? = null

private fun registerGpsStatusCallback() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        val listener = object : GnssStatus.Callback() {
            override fun onStarted() {
                super.onStarted()
            }

            override fun onStopped() {
                super.onStopped()
            }

            override fun onFirstFix(ttffMillis: Int) {
                super.onFirstFix(ttffMillis)
            }

            override fun onSatelliteStatusChanged(status: GnssStatus) {
                super.onSatelliteStatusChanged(status)
                var inUse = 0
                for (i in 0 until status.satelliteCount) {
                    if (status.usedInFix(i)) {
                        inUse++
                    }
                }
            }
        }
        locationManager.registerGnssStatusCallback(listener, backgroundHandler)
        gpsStatusListener = listener
    } else {
        @Suppress("DEPRECATION")
        val listener = GpsStatus.Listener { event ->
            when (event) {
                GpsStatus.GPS_EVENT_STARTED -> {}
                GpsStatus.GPS_EVENT_STOPPED -> {}
                GpsStatus.GPS_EVENT_FIRST_FIX -> {}
                GpsStatus.GPS_EVENT_SATELLITE_STATUS -> {
                    val inUse = locationManager.getGpsStatus(null)?.satellites?.count { it.usedInFix() } ?: 0
                }
            }
        }
        @Suppress("DEPRECATION")
        locationManager.addGpsStatusListener(listener)
        gpsStatusListener = listener
    }
}

private fun unregisterGpsStatusCallback() {
    gpsStatusListener?.let { listener ->
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            locationManager.unregisterGnssStatusCallback(listener as GnssStatus.Callback)
        } else {
            @Suppress("DEPRECATION")
            locationManager.removeGpsStatusListener(listener as GpsStatus.Listener)
        }
        gpsStatusListener = null
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接