如何查看GPS接收器的当前状态?

时间:2010-01-07 15:06:32

标签: android gps

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

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

17 个答案:

答案 0 :(得分:145)

作为SpeedView的开发者:Android的GPS速度计,我必须尝试解决这个问题的所有方法,所有这些都有相同的负面结果。让我们重申一下不起作用:

  1. onStatusChanged()没有被Eclair和Froyo调用。
  2. 简单地计算所有可用的卫星当然是没用的。
  3. 检查usedInFix()中是否有任何卫星返回true也不是很有帮助。该系统明显失去了修复程序,但仍然报告仍然有几个sats用于其中。
  4. 所以这是我找到的唯一可行的解​​决方案,也是我在我的应用中实际使用的解决方案。假设我们有这个实现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图标的源代码,但这接近于复制其行为。希望这有助于某人。

答案 1 :(得分:26)

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状态的变化。但是,只有在状态发生变化时才会通知您。因此,不可能使用这些意图来确定当前状态。

答案 2 :(得分:18)

新成员很遗憾我无法发表评论或投票,但上面的Stephen Daye的帖子是我一直在寻求帮助的完全相同问题的完美解决方案。

对以下行的一个小改动:

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

为:

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

基本上我正在构建一个节奏缓慢的游戏并且我的更新间隔已经设置为5秒,一旦gps信号超出10秒,这就是触发某些事情的正确时间。

欢呼伙伴,在找到你的帖子之前花了大约10个小时试图解决这个问题:)

答案 3 :(得分:14)

好的,让我们到目前为止尝试所有答案和更新的组合并执行以下操作:

  • ACCESS_FINE_LOCATION权限添加到您的清单
  • 获取系统LocationManager
  • 的实例
  • 创建一个对GpsStatus.Listener
  • 作出反应的GPS_EVENT_SATELLITE_STATUS
  • 使用LocationManager
  • 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 } } } 注册听众

GPS聆听者可能是这样的:

GpsSatellite

关于GPS和卫星信息何时以及提供什么信息,API有点不清楚,但我认为可以看看有多少卫星可用。如果它低于三,那么你就无法修复。如果它更多,那么你应该有一个修复。

尝试和错误可能是确定Android报告卫星信息的频率以及每个{{1}}对象包含的信息的方式。

答案 4 :(得分:8)

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

因此,另一种解决方案是将GPS位置的UTC时间与手机的时间(转换为UTC)进行比较。如果它们相隔一定的时差,则可以假设您丢失了GPS位置。

答案 5 :(得分:7)

在处理我的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;
        }
    }
}

答案 6 :(得分:4)

好吧,将每个工作方法放在一起会产生这种情况(也处理弃用的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) {

}

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

答案 7 :(得分:3)

如果您只是需要知道是否有修复,请检查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格式!)。如果它已经足够了你就得到了修复。

我在我的应用程序中这样做,到目前为止一切顺利。

答案 8 :(得分:2)

当GPS状态发生变化时,您可以尝试使用LocationManager.addGpsStatusListener进行更新。看起来GPS_EVENT_STARTEDGPS_EVENT_STOPPED可能就是您要找的内容。

答案 9 :(得分:2)

我可能错了,但似乎人们似乎偏离主题

  

我只需要知道屏幕顶部的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上。

答案 10 :(得分:1)

这么多帖子......

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

使用addGpsListener添加此代码... showMessageDialog ...只显示一个带有字符串

的标准对话框窗口

完美地完成了我的工作:) 非常感谢:=)(sry这篇文章,尚未投票)

答案 11 :(得分:1)

使用LocationManager,您可以在getBestProvider()之后获取LastKnownLocation()。 这将为您提供一个Location对象,其中包含以米为单位的getAccuracy()方法和以UTC毫秒为单位的getTime()

这会给你足够的信息吗?

或许您可以遍历LocationProviders并查明每个人是否符合标准(ACCURACY_COARSE)

答案 12 :(得分:1)

如果您在修复丢失的瞬间不需要更新,则可以通过这种方式修改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”作为我当前的位置。

答案 13 :(得分:1)

我知道这有点晚了。但是,如果您想知道是否有修复,为什么不使用NMEAListener。根据我的阅读,NMEAListener将为您提供NMEA句子,并从那里选择正确的句子。

RMC句子包含修复状态,可以是A表示OK,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值。

答案 14 :(得分:0)

你说你已经尝试过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跟踪;不是你想要的。

答案 15 :(得分:0)

创建一个定期将接收的位置设置为某个值(null?)的TimerTask可能是最好的可能性。 如果GPSListener收到新值,它将使用当前数据更新位置。

我认为这将是一个有效的解决方案。

答案 16 :(得分:0)

设置检查修复的时间间隔不是一个好选择..我注意到,如果你没有移动 onLocationChanged ,那么可以理解,因为位置没有改变:)

更好的方法是例如:

  • 检查间隔到收到的最后一个位置(在gpsStatusChanged中)
  • 如果该间隔大于15s,则设置变量:long_interval = true
  • 删除位置监听器并再次添加,通常会获得更新位置 如果位置真的可用,如果没有 - 你可能丢失了位置
  • 在onLocationChanged中你只需将long_interval设置为false ..