Как проверить текущее состояние приемника GPS?

Как проверить текущее состояние приемника GPS? Я уже проверил метод LocationListener onStatusChanged, но почему-то кажется, что он не работает или просто неправильная возможность.

В принципе, мне просто нужно знать, мигает ли значок GPS в верхней части экрана (нет фактического исправления) или сплошной (исправление доступно).

Ответ 1

Как разработчик SpeedView: GPS-спидометр для Android, я должен был попробовать все возможные решения этой проблемы, все с тем же отрицательным результатом. Повторите то, что не работает:

  • onStatusChanged() не получает вызов в Eclair и Froyo.
  • Просто подсчет всех доступных спутников, конечно, бесполезен.
  • Проверка того, что какой-либо из спутников возвращает true для usedInFix(), также не очень помогает. Система явно теряет исправление, но продолжает сообщать, что в ней все еще используется несколько сатов.

Итак, вот единственное рабочее решение, которое я нашел, и тот, который я фактически использую в своем приложении. Скажем, у нас есть этот простой класс, который реализует 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, это приближается к репликации его поведения. Надеюсь, это поможет кому-то.

Ответ 2

Значок 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);

Пример кода для регистрации приемника: [/p >

// 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. Однако вы будете уведомлены только в случае изменения состояния. Таким образом, невозможно определить текущее состояние с использованием этих намерений.

Ответ 3

новый участник, к сожалению, я не смог прокомментировать или проголосовать, однако вышеприведенное сообщение Стивена Дейэ было идеальным решением для той же проблемы, с которой я искал помощь.

небольшое изменение к следующей строке:

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

в

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

в основном, поскольку я создаю медленную игру, и мой интервал обновления уже установлен на 5 секунд, как только сигнал gps отключается на 10+ секунд, это правильное время, чтобы что-то выпустить.

cheers mate, потратил около 10 часов, пытаясь решить это решение, прежде чем я нашел ваше сообщение:)

Ответ 4

Итак, давайте попробуем сочетание всех ответов и обновлений до сих пор и сделаем что-то вроде этого:

Приемник 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 и спутников предоставляется, но я думаю, что идея состоит в том, чтобы посмотреть, сколько спутников доступно. Если это ниже трех, то вы не можете исправить. Если это больше, тогда у вас должно быть исправление.

Вероятно, пробная версия и ошибка, чтобы определить, как часто Android сообщает информацию о спутниках, и какая информация содержит каждый объект GpsSatellite.

Ответ 5

После нескольких лет работы с GPS на мобильных устройствах Windows я понял, что концепция "потеря" GPS-решения может быть субъективной. Чтобы просто слушать, что говорит GPS, добавление NMEAListener и разбор предложения скажут вам, было ли исправление "действительным" или нет. См. http://www.gpsinformation.org/dale/nmea.htm#GGA. К сожалению, с некоторыми GPS-устройствами это значение будет колебаться взад и вперед даже во время обычного хода работы в области "хорошего исправления".

Таким образом, другим решением является сравнение времени UTC местоположения GPS по времени телефона (конвертируется в UTC). Если они отличаются от разницы во времени, вы можете предположить, что потеряли позицию GPS.

Ответ 6

сталкиваются с подобной проблемой во время работы над моим проектом 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;
        }
    }
}

Ответ 7

Если вам просто нужно знать, есть ли исправление, а затем проверить последнее известное местоположение, предоставленное 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!). Если это достаточно недавно, у вас есть исправление.

Я делаю это в своем приложении и пока так хорош.

Ответ 9

Возможно, я ошибаюсь, но кажется, что люди, похоже, идут не по теме для

Мне просто нужно знать, мигает ли значок 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()

Работает надежно, по крайней мере, на N1 с 2.1.

Ответ 10

С помощью LocationManager вы можете getLastKnownLocation() после getBestProvider(). Это дает вам объект Location, который имеет методы getAccuracy() в метрах и getTime() в миллисекундах UTC

Это дает вам достаточно информации?

Или, может быть, вы могли бы перебирать LocationProviders и выяснять, соответствует ли каждый критерийCriteria (ACCURACY_COARSE)

Ответ 11

столько сообщений...

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

добавление этого кода с помощью addGpsListener... showMessageDialog... просто показывает стандартное диалоговое окно со строкой

сделал работу отлично для меня:) Большое спасибо: =) (sry для этого поста, еще не в состоянии проголосовать)

Ответ 12

Если вам не нужно обновление в тот момент, когда исправление потеряно, вы можете изменить решение 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(), и если результат верен, я использую переменную "lastKnownLocation" в качестве моей текущей позиции.

Ответ 13

Я знаю, что это немного поздно. Однако почему бы не использовать NMEAListener, если вы хотите узнать, есть ли у вас исправление. Из того, что я прочитал, NMEAListener предоставит вам предложения NMEA, и оттуда вы выберете правильное предложение.

Предложение RMC содержит статус фиксации, который является A для OK или V для предупреждения. Предложение GGA содержит качество исправления (0 недействительных, 1 GPS или 2 DGPS)

Я не могу предложить вам какой-либо java-код, поскольку я только начинаю работать с Android, но я сделал библиотеку GPS в С# для приложений Windows, которую я собираюсь использовать с Xamarin. Я только наткнулся на эту тему, потому что искал информацию о провайдере.

Из того, что я до сих пор читал о объекте Location, мне не все так нравится в таких методах, как getAccuracy() и hasAccuracy(). Я привык извлекать из предложений NMEA предложения HDOP и VDOP, чтобы определить, насколько точны мои исправления. Его довольно часто встречаются, чтобы иметь исправить, но иметь паршивый HDOP, который означает, что ваша горизонтальная точность не очень хороша. Например, сидя на своем столе, отлаживая внешнее Bluetooth-устройство GPS, сильно противостоящее окну, вы, скорее всего, получите исправление, но очень плохое HDOP и VDOP. Поместите устройство GPS в цветочный горшок снаружи или что-то подобное или добавьте внешнюю антенну в GPS и сразу получите хорошие значения HDOP и VDOP.

Ответ 14

Ну, в результате каждый рабочий подход приведет к этому (также относится к устаревшим 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) {

}

Примечание: этот ответ представляет собой комбинацию ответов выше.

Ответ 15

Возможно, это самая лучшая возможность создать TimerTask, которая регулярно устанавливает принятое местоположение на определенное значение (null?). Если новое значение получено GPSListener, оно обновит местоположение с текущими данными.

Я думаю, это было бы рабочим решением.

Ответ 16

Вы говорите, что вы уже пробовали 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-отслеживания пользователем; не то, что вы ищете.

Ответ 17

Установка интервала времени для проверки исправления не является хорошим выбором. Я заметил, что onLocationChanged не вызывается, если вы не двигаетесь.. что понятно, поскольку местоположение не меняется:)

Лучше всего было бы:

  • проверить интервал до последнего найденного местоположения (в gpsStatusChanged)
  • если этот интервал составляет более 15 с заданной переменной: long_interval = true
  • удалите прослушиватель местоположения и добавьте его снова, обычно после этого вы получаете обновленную позицию если местоположение действительно доступно, если нет - вы, вероятно, потеряли местоположение.
  • В onLocationChanged вы просто установите long_interval на false.