我如何检查GPS接收机的当前状态?

我如何检查GPS接收机的当前状态? 我已经检查了LocationListener onStatusChanged方法,但不知何故,似乎不工作,或者只是错误的可能性。

基本上我只需要知道在屏幕顶部的GPS图标闪烁(没有实际的修复)或固体(修复是可用的)。

作为Android的SpeedView:GPS速度计的开发者,我必须尝试一切可能的解决scheme来解决这个问题,所有的结果都是一样的。 让我们重申什么是行不通的:

  1. onStatusChanged()不会在Eclair和Froyo上调用。
  2. 简单地计算所有可用的卫星当然是无用的。
  3. 检查usedInFix()是否有任何卫星返回true也没有什么帮助。 该系统显然失去了修复,但不断报告,仍然有几个sats在使用。

所以这里是我find的唯一工作解决scheme,以及我在我的应用程序中实际使用的解决scheme。 比方说,我们有这个简单的类来实现GpsStatus.Listener:

 private class MyGPSListener implements GpsStatus.Listener { public void onGpsStatusChanged(int event) { switch (event) { case GpsStatus.GPS_EVENT_SATELLITE_STATUS: if (mLastLocation != null) isGPSFix = (SystemClock.elapsedRealtime() - mLastLocationMillis) < 3000; if (isGPSFix) { // A fix has been acquired. // Do something. } else { // The fix has been lost. // Do something. } break; case GpsStatus.GPS_EVENT_FIRST_FIX: // Do something. isGPSFix = true; break; } } } 

好的,现在在onLocationChanged()中添加下面的代码:

 @Override public void onLocationChanged(Location location) { if (location == null) return; mLastLocationMillis = SystemClock.elapsedRealtime(); // Do something. mLastLocation = location; } 

就是这样。 基本上,这就是一切:

 isGPSFix = (SystemClock.elapsedRealtime() - mLastLocationMillis) < 3000; 

你当然可以调整millis的值,但是我build议把它设置在3-5秒左右。

这实际上工作,虽然我没有看过绘制原生GPS图标的源代码,这接近复制其行为。 希望这有助于某人。

GPS图标似乎根据收到的广播意图改变其状态。 您可以使用以下代码示例自行更改其状态:

通知GPS已启用:

 Intent intent = new Intent("android.location.GPS_ENABLED_CHANGE"); intent.putExtra("enabled", true); sendBroadcast(intent); 

通知GPS正在接受修复:

 Intent intent = new Intent("android.location.GPS_FIX_CHANGE"); intent.putExtra("enabled", true); sendBroadcast(intent); 

通知GPS不再接收修复:

 Intent intent = new Intent("android.location.GPS_FIX_CHANGE"); intent.putExtra("enabled", false); sendBroadcast(intent); 

通知GPS已被禁用:

 Intent intent = new Intent("android.location.GPS_ENABLED_CHANGE"); intent.putExtra("enabled", false); sendBroadcast(intent); 

将接收机注册到意图的示例代码:

 // MyReceiver must extend BroadcastReceiver MyReceiver receiver = new MyReceiver(); IntentFilter filter = new IntentFilter("android.location.GPS_ENABLED_CHANGE"); filter.addAction("android.location.GPS_FIX_CHANGE"); registerReceiver(receiver, filter); 

通过接收这些广播意图,您可以注意到GPS状态的变化。 但是,只有在状态发生变化时才会通知您。 因此,使用这些意图来确定当前状态是不可能的。

新成员,所以不幸的是我无法评论或投票,但斯蒂芬·戴耶的上面的post是完全相同的问题,我一直在寻求帮助的解决scheme。

对以下行进行小改动:

 isGPSFix = (SystemClock.elapsedRealtime() - mLastLocationMillis) < 3000; 

至:

 isGPSFix = (SystemClock.elapsedRealtime() - mLastLocationMillis) < (GPS_UPDATE_INTERVAL * 2); 

基本上就像我build立一个慢节奏的比赛,我的更新时间间隔已经设置为5秒,一旦GPS信号超过10秒以上,这是正确的时间触发的东西。

欢呼队友,花了大约10个小时,试图解决这个问题之前,我发现你的post:)

好的,让我们尝试所有答案和更新到目前为止的组合,并做这样的事情:

  • ACCESS_FINE_LOCATION权限添加到您的清单
  • 获取系统LocationManager一个实例
  • 创build一个对GpsStatus.Listener有反应的GPS_EVENT_SATELLITE_STATUS
  • 使用addGpsStatusListenerLocationManager注册侦听addGpsStatusListener

GPS监听器可能是这样的:

 GpsStatus.Listener listener = new GpsStatus.Listener() { void onGpsStatusChanged(int event) { if (event == GPS_EVENT_SATELLITE_STATUS) { GpsStatus status = mLocManager.getGpsStatus(null); Iterable<GpsSatellite> sats = status.getSatellites(); // Check number of satellites in list to determine fix state } } } 

这些API对于何时以及给出什么GPS和卫星信息有点不清楚,但是我想一个想法是查看有多less卫星可用。 如果它低于三,那么你不能有一个修复。 如果更多,那么你应该有一个修复。

试验和错误可能是确定Android报告卫星信息的频率以及每个GpsSatellite对象包含哪些信息的方法。

在Windows Mobile上使用GPS几年后,我意识到“丢失”GPS定位的概念可能是主观的。 为了简单地听取GPS告诉你什么,添加一个NMEAListener并parsing句子会告诉你这个修正是否“有效”。 请参阅http://www.gpsinformation.org/dale/nmea.htm#GGA 。 不幸的是,对于一些GPS,即使在正常的操作过程中,这个值也会在“良好修复”区域中来回波动。

因此,另一种解决scheme是比较GPS位置的UTC时间和电话时间(转换为UTC)。 如果他们有一定的时差,你可以假设你失去了GPS的位置。

在我的MSc项目上工作时遇到类似的问题,似乎Daye的回答错误地报告“没有修复”,而设备停留在静态位置。 我已经修改了解决scheme只是一点点,这似乎在静态位置正常工作。 我不会如何影响电池,因为它不是我主要关心的问题,但这是我通过在修复超时后重新请求位置更新来做到的。

 private class MyGPSListener implements GpsStatus.Listener { public void onGpsStatusChanged(int event) { switch (event) { case GpsStatus.GPS_EVENT_SATELLITE_STATUS: if (Global.getInstance().currentGPSLocation != null) { if((SystemClock.elapsedRealtime() - mLastLocationMillis) < 20000) { if (!hasGPSFix) Log.i("GPS","Fix Acquired"); hasGPSFix = true; } else { if (hasGPSFix) { Log.i("GPS","Fix Lost (expired)"); lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 10, locationListener); } hasGPSFix = false; } } break; case GpsStatus.GPS_EVENT_FIRST_FIX: Log.i("GPS", "First Fix/ Refix"); hasGPSFix = true; break; case GpsStatus.GPS_EVENT_STARTED: Log.i("GPS", "Started!"); break; case GpsStatus.GPS_EVENT_STOPPED: Log.i("GPS", "Stopped"); break; } } } 

如果你只是需要知道是否有修复,然后检查GPS接收器提供的最后一个已知的位置,并检查.getTime()值知道多大年纪。 如果它是近期(如…几秒钟),你有一个修复。

  LocationManager lm = (LocationManager)context.getSystemService(LOCATION_SERVICE); Location loc = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER); // Get the time of the last fix long lastFixTimeMillis = loc.getTime(); 

…最后将其与当前date时间(在UTC!)进行比较。 如果它是最近足够你有一个修复。

我在我的应用程序中这样做,迄今为止这么好。

您可以尝试使用LocationManager.addGpsStatusListener在GPS状态更改时更新。 它看起来像GPS_EVENT_STARTED和GPS_EVENT_STOPPED可能是你在找什么。

我可能是错的,但似乎人们似乎要走的路

我只需要知道屏幕顶部的GPS图标是否闪烁(没有实际的修复)

这很容易完成

 LocationManager lm = (LocationManager) getSystemService(LOCATION_SERVICE); boolean gps_on = lm.isProviderEnabled(LocationManager.GPS_PROVIDER); 

要看看你是否有一个坚实的修复,事情会变得有点棘手:

 public class whatever extends Activity { LocationManager lm; Location loc; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); lm = (LocationManager) getSystemService(LOCATION_SERVICE); loc = null; request_updates(); } private void request_updates() { if (lm.isProviderEnabled(LocationManager.GPS_PROVIDER)) { // GPS is enabled on device so lets add a loopback for this locationmanager lm.requestLocationUpdates(LocationManager.GPS_PROVIDER,0, 0, locationListener); } } LocationListener locationListener = new LocationListener() { public void onLocationChanged(Location location) { // Each time the location is changed we assign loc loc = location; } // Need these even if they do nothing. Can't remember why. public void onProviderDisabled(String arg0) {} public void onProviderEnabled(String provider) {} public void onStatusChanged(String provider, int status, Bundle extras) {} }; 

现在每当你想看看你是否有修复?

 if (loc != null){ // Our location has changed at least once blah..... } 

如果你想要看起来你可以使用System.currentTimeMillis()和loc.getTime()

可靠地工作,至less从2.1开始就是N1。

使用LocationManager,您可以在getBestProvider()后获取最后的位置()。 这为您提供了一个Location对象,它具有以毫秒为单位的getAccuracy()方法和以毫秒为单位的getTime()

这是否给你足够的信息?

或者,也许你可以迭代LocationProviders并找出每个是否符合标准(ACCURACY_COARSE)

那么多post…

 GpsStatus.Listener gpsListener = new GpsStatus.Listener() { public void onGpsStatusChanged(int event) { if( event == GpsStatus.GPS_EVENT_FIRST_FIX){ showMessageDialog("GPS fixed"); } } }; 

添加此代码,与addGpsListener … showMessageDialog …只是显示一个标准的对话框窗口的string

完成了我的工作:)非常感谢:=)(这个post,还没有能够投票)

如果您在修复程序丢失的瞬间不需要更新,则可以通过这种方式修改Stephen Daye的解决scheme,即可以检查修复程序是否仍然存在。

所以,只要你需要一些GPS数据,你就可以检查它,而且你不需要那个GpsStatus.Listener。

“全局”variables是:

 private Location lastKnownLocation; private long lastKnownLocationTimeMillis = 0; private boolean isGpsFix = false; 

这是在“onLocationChanged()”中调用以记住更新时间和当前位置的方法。 除此之外,它更新“isGpsFix”:

 private void handlePositionResults(Location location) { if(location == null) return; lastKnownLocation = location; lastKnownLocationTimeMillis = SystemClock.elapsedRealtime(); checkGpsFix(); // optional } 

只要我需要知道是否有GPS定位,就会调用该方法:

 private boolean checkGpsFix(){ if (SystemClock.elapsedRealtime() - lastKnownLocationTimeMillis < 3000) { isGpsFix = true; } else { isGpsFix = false; lastKnownLocation = null; } return isGpsFix; } 

在我的实现中,我首先运行checkGpsFix(),如果结果为真,我使用variables“lastKnownLocation”作为我的当前位置。

我知道这有点晚了。 但是,如果你想知道你是否有修复,为什么不使用NMEAListener? 从我读过的内容来看,NMEAListener会给你NMEA句子,然后从那里select正确的句子。

RMC语句包含修正状态,即A为OK或V为警告。 GGA语句包含固定质量(0无效,1 GPS或2 DGPS)

我不能为您提供任何Java代码,因为我只是刚刚开始使用Android,但是我已经在C#中为Windows应用程序完成了一个GPS库,我正在使用Xamarin。 我只是遇到这个线程,因为我正在寻找提供商的信息。

从迄今为止关于Location对象所读到的内容来看,对于像getAccuracy()和hasAccuracy()这样的方法,我并不是那么舒服。 我习惯从NMEA语句中提取HDOP和VDOP值,以确定我的修复程序有多准确。 它有一个固定的相当普遍,但有一个糟糕的HDOP,这意味着你的水平精度不是很好。 例如坐在办公桌前用外部蓝牙GPS设备进行debugging时,你很可能会得到一个修复,但非常糟糕的HDOP和VDOP。 把你的GPS设备放在外面的花盆里或类似的东西上,或者在GPS上增加一个外部天线,并立即获得良好的HDOP和VDOP值。

那么,把每个工作方法放在一起将导致这个(也处理不推荐的GpsStatus.Listener ):

 private GnssStatus.Callback mGnssStatusCallback; @Deprecated private GpsStatus.Listener mStatusListener; private LocationManager mLocationManager; @Override public void onCreate() { mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE); mLocationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); if (checkPermission()) { mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, GPS_UPDATE_INTERVAL, MIN_DISTANCE, this); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { mGnssStatusCallback = new GnssStatus.Callback() { @Override public void onSatelliteStatusChanged(GnssStatus status) { satelliteStatusChanged(); } @Override public void onFirstFix(int ttffMillis) { gpsFixAcquired(); } }; mLocationManager.registerGnssStatusCallback(mGnssStatusCallback); } else { mStatusListener = new GpsStatus.Listener() { @Override public void onGpsStatusChanged(int event) { switch (event) { case GpsStatus.GPS_EVENT_SATELLITE_STATUS: satelliteStatusChanged(); break; case GpsStatus.GPS_EVENT_FIRST_FIX: // Do something. gpsFixAcquired(); break; } } }; mLocationManager.addGpsStatusListener(mStatusListener); } } private void gpsFixAcquired() { // Do something. isGPSFix = true; } private void satelliteStatusChanged() { if (mLastLocation != null) isGPSFix = (SystemClock.elapsedRealtime() - mLastLocationMillis) < (GPS_UPDATE_INTERVAL * 2); if (isGPSFix) { // A fix has been acquired. // Do something. } else { // The fix has been lost. // Do something. } } @Override public void onLocationChanged(Location location) { if (location == null) return; mLastLocationMillis = SystemClock.elapsedRealtime(); mLastLocation = location; } @Override public void onStatusChanged(String s, int i, Bundle bundle) { } @Override public void onProviderEnabled(String s) { } @Override public void onProviderDisabled(String s) { } 

注意:这个答案是上述答案的组合。

也许最好的办法是创build一个TimerTask,定期将收到的位置设置为一个特定的值(null?)。 如果GPSListener接收到新的值,它将用当前数据更新位置。

我认为这将是一个工作的解决scheme。

你说你已经试过onStatusChanged(),但是这对我有用。

这里是我使用的方法(我让类本身处理onStatusChanged):

 private void startLocationTracking() { final int updateTime = 2000; // ms final int updateDistance = 10; // meter final Criteria criteria = new Criteria(); criteria.setCostAllowed(false); criteria.setAccuracy(Criteria.ACCURACY_FINE); final String p = locationManager.getBestProvider(criteria, true); locationManager.requestLocationUpdates(p, updateTime, updateDistance, this); } 

我处理onStatusChanged如下:

 void onStatusChanged(final String provider, final int status, final Bundle extras) { switch (status) { case LocationProvider.OUT_OF_SERVICE: if (location == null || location.getProvider().equals(provider)) { statusString = "No Service"; location = null; } break; case LocationProvider.TEMPORARILY_UNAVAILABLE: if (location == null || location.getProvider().equals(provider)) { statusString = "no fix"; } break; case LocationProvider.AVAILABLE: statusString = "fix"; break; } } 

请注意,onProvider {Dis,En} abled()方法是关于启用和禁用用户的GPS跟踪; 不是你要找的东西。

设置时间间隔来检查修复是不是一个好的select..我注意到, onLocationChanged不会被调用,如果你不移动 ..什么是可以理解的,因为位置不变:)

更好的方法是例如:

  • 检查最后接收位置的时间间隔(在gpsStatusChanged中)
  • 如果该间隔超过15秒,设置variables:long_interval = true
  • 删除位置侦听器并重新添加,通常会得到更新的位置,如果位置确实可用,如果没有 – 您可能丢失了位置
  • 在onLocationChanged你只需将long_interval设置为false ..