我如何检查GPS接收机的当前状态?
我如何检查GPS接收机的当前状态? 我已经检查了LocationListener
onStatusChanged
方法,但不知何故,似乎不工作,或者只是错误的可能性。
基本上我只需要知道在屏幕顶部的GPS图标闪烁(没有实际的修复)或固体(修复是可用的)。
作为Android的SpeedView:GPS速度计的开发者,我必须尝试一切可能的解决scheme来解决这个问题,所有的结果都是一样的。 让我们重申什么是行不通的:
- onStatusChanged()不会在Eclair和Froyo上调用。
- 简单地计算所有可用的卫星当然是无用的。
- 检查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
- 使用
addGpsStatusListener
向LocationManager
注册侦听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 ..