如何查看GPS接收器的当前状态?我已经检查了LocationListener
onStatusChanged
方法,但是以某种方式似乎不起作用,或者只是错误的可能性。
基本上我只需要知道屏幕顶部的GPS图标是闪烁(没有实际修复)还是稳定(修复可用)即可。
如何查看GPS接收器的当前状态?我已经检查了LocationListener
onStatusChanged
方法,但是以某种方式似乎不起作用,或者只是错误的可能性。
基本上我只需要知道屏幕顶部的GPS图标是闪烁(没有实际修复)还是稳定(修复可用)即可。
Answers:
作为SpeedView:适用于Android的GPS车速表的开发人员,我必须尝试过所有可能解决此问题的方法,但结果都是相同的。让我们重申什么无效:
因此,这是我找到的唯一可行的解决方案,也是我在应用程序中实际使用的解决方案。假设我们有一个实现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;
您当然可以调整毫秒值,但我建议将其设置为3-5秒左右。
这实际上是可行的,尽管我没有看过绘制本机GPS图标的源代码,但这接近于复制其行为。希望这对某人有帮助。
mLastLocationMillis
不是由GPS以外的其他来源设置时,这不会中断吗?该系统将声称它isGPSFix
是正确的,但实际上这只是任何修复(可能是来自电话网络的修复)
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状态的变化。但是,只有状态更改时,您才会收到通知。因此,不可能使用这些意图确定当前状态。
不幸的是,新成员无法发表评论或投票,但是斯蒂芬·戴(Stephen Daye)的上述帖子是对我一直在寻求帮助的相同问题的完美解决方案。
对以下行进行了小的改动:
isGPSFix = (SystemClock.elapsedRealtime() - mLastLocationMillis) < 3000;
至:
isGPSFix = (SystemClock.elapsedRealtime() - mLastLocationMillis) < (GPS_UPDATE_INTERVAL * 2);
基本上是因为我正在制作一个慢节奏的游戏,并且我的更新间隔已经设置为5秒,一旦gps信号发出10+秒,那就是触发某些东西的正确时间。
干杯,在我找到您的帖子之前,花了大约10个小时尝试解决这个问题:)
好的,让我们尝试结合到目前为止的所有答案和更新,然后执行以下操作:
ACCESS_FINE_LOCATION
权限添加到清单LocationManager
GpsStatus.Listener
对GPS_EVENT_SATELLITE_STATUS
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和卫星信息,但我认为一个主意是看有多少颗卫星可用。如果低于3,则无法修复。如果更多,那么您应该有一个解决方法。
反复试验可能是确定Android报告卫星信息的频率以及每个GpsSatellite
对象包含的信息的方式。
GpsSatellite
对象中检索到这些信息。
LocationManager.requestLocationUpdates
将时间和距离设置设置为0?那应该立即向您发送GPS修复。如果您什么都没有收到,那么您很可能没有解决办法。如果愿意,可以将其与上面的状态侦听器结合使用。
在Windows Mobile上使用GPS几年后,我意识到“丢失” GPS修复的概念可能是主观的。为了简单地听GPS告诉您的内容,添加NMEAListener并解析该句子将告诉您该修复程序是否“有效”。参见http://www.gpsinformation.org/dale/nmea.htm#GGA。不幸的是,对于某些GPS,即使在“良好定位”区域的正常操作过程中,该值也会来回波动。
因此,另一种解决方案是将GPS位置的UTC时间与手机时间进行比较(转换为UTC)。如果它们相距一定的时差,则可以假设您丢失了GPS位置。
在我的MSc项目上工作时遇到类似的问题,当设备停留在静态位置时,Daye的回答似乎错误地报告了“无法修复”。我已经对解决方案进行了一些修改,这似乎对我在静态位置上正常工作。我不怎么会影响电池,因为这不是我主要关心的问题,但是这是我通过在修复程序超时后重新请求位置更新来实现的。
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;
}
}
}
好吧,将每种可行的方法放到一起都会导致这种情况(还处理不推荐使用的方法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) {
}
注意:此答案是上述答案的组合。
如果您只想知道是否有解决方法,请检查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();
...最后将其与当前日期时间进行比较(以UTC!)。如果足够新,则可以解决。
我在我的应用程序中做到了,到目前为止一切顺利。
您可以尝试使用LocationManager.addGpsStatusListener在GPS状态更改时进行更新。它看起来像GPS_EVENT_STARTED和GPS_EVENT_STOPPED可能是你在找什么。
GPS_EVENT_FIRST_FIX
听起来更贴合。
我可能是错的,但似乎人们似乎偏离了主题
我只需要知道屏幕顶部的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()进行超时
自2.1开始,至少在N1上可靠运行。
这么多帖子...
GpsStatus.Listener gpsListener = new GpsStatus.Listener() {
public void onGpsStatusChanged(int event) {
if( event == GpsStatus.GPS_EVENT_FIRST_FIX){
showMessageDialog("GPS fixed");
}
}
};
使用addGpsListener ... showMessageDialog ...添加此代码,仅显示带有字符串的标准对话框窗口
为我做了完美的工作:)非常感谢:=)(对此帖子表示抱歉,尚无法投票)
如果在丢失修补程序的那一刻不需要更新,则可以以这种方式修改Stephen Daye的解决方案,即可以使用一种方法来检查该修补程序是否仍然存在。
因此,只要您需要一些GPS数据并且不需要GpsStatus.Listener,就可以进行检查。
“全局”变量是:
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(),如果结果为true,则将变量“ lastKnownLocation”用作当前位置。
我知道这有点晚了。但是,如果您想知道是否有修复程序,为什么不使用NMEAListener。根据我的阅读,NMEAListener将为您提供NMEA句子,然后从中选择正确的句子。
RMC语句包含修复状态,该状态为A(表示正常)或V(表示警告)。GGA语句包含修复质量(0个无效,1个GPS或2个DGPS)
我无法为您提供任何Java代码,因为我只是从Android开始,但是我已经在C#中为Windows应用程序完成了GPS库,我希望将其与Xamarin一起使用。我只是碰到这个线程,因为我在寻找提供者信息。
到目前为止,我所读到的有关Location对象的内容对getAccuracy()和hasAccuracy()之类的方法并不满意。我习惯从NMEA语句中提取HDOP和VDOP值,以确定我的修正的准确性。进行修复很常见,但是HDOP不好,这意味着您的水平精度根本不是很好。例如,坐在办公桌前用外部蓝牙GPS设备紧贴窗户调试时,您很可能会得到修复,但HDOP和VDOP却很差。将您的GPS设备放在外面或类似地方的花盆中,或向GPS添加外部天线,立即获得良好的HDOP和VDOP值。
您说您已经尝试过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跟踪有关。不是您要找的东西。