Вопрос по gps, android – Как я могу проверить текущее состояние GPS-приемника?

87

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

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

Ваш Ответ

17   ответов
0

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

Лучше всего было бы, например:

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

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

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

3

объединение каждого рабочего подхода приведет к этому (также имеет дело с устаревшим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) {

}

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

Пока вы доверяете другим авторам, нет проблем с получением ваших собственных голосов за новую или производную работу. Правила здесь больше заботятся о людях, которые плагиат других людей ответы и использование их в других местах на переполнение стека, чтобы нечестно привлекать представителей. Так как тыЯ упомянул тебяЯ построил на других ответах, я думаю, что это хорошо. halfer
145

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

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

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

Привет Стивен, не могли бы вы объяснитьЗачем isGPSFix работает. Спасибо ник nickfox
Привет, мне интересно, почему подсчет доступных спутников бесполезен, как в этом примере? Если количество найденных спутников равно 0, значит, нет соединения, или я ошибаюсь?groups.google.com/group/android-developers/browse_thread/thread/... per_jansson
Но нет этот перерыв, когдаmLastLocationMillis был установлен источник, отличный от GPS? Система будет утверждать, чтоisGPSFix это правда, но на самом деле это простолюбой исправить (возможно, один из телефонной сети) avalancha
GpsStatus.Listener кажется устаревшим; Есть ли обновление? mbacvanski
2

LocationManager.addGpsStatusListener чтобы получать обновления при изменении статуса GPS. Это выглядит какGPS_EVENT_STARTED а такжеGPS_EVENT_STOPPED может быть то, что тыищу.

Статус слушателя в сочетании сGPS_EVENT_FIRST_FIX звучит как более тесная посадка. Christopher Orr
26

похоже, меняет свое состояние в соответствии с полученными намерениями вещания. Вы можете изменить его состояние самостоятельно с помощью следующих примеров кода:

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

Да я'мы получили этот сбой: 05-14 10: 25: 24.113 17344-17344 / xxx.yyy.zzz.debug E / AndroidRuntime: FATAL EXCEPTION: main Процесс: xxx.yyy.zzz.debug, PID: 17344 java.lang.SecurityException : Отказ в разрешении: запрещено отправлять трансляцию android.location.GPS_FIX_CHANGE с pid = 17344, uid = 10416 unlimited101
Я нене знаю как тыВы можете отправить эту трансляцию из своего приложения, потому что кажется, что трансляция защищена системой, то есть только система может отправить ее. Любое приложение, отправляющее это намерение, должно аварийно завершить работу. JoxTraex
Его можно было отправить шесть лет назад, когда я написал ответ. Очевидно, с тех пор они добавили некоторую защиту в систему. sast
Я использовал эти намерения, чтобы сказать, когда другие приложения использовали GPS. Я считаю, что начиная с нуги, вы можетедаже больше не слушайте эти намерения, они или они изменились! Я нене хочу слушать местоположение с моим собственным приложением. У кого-нибудь есть другие идеи? Flyview
14
, Р>Хорошо, так давайтеs попробуйте комбинацию всех ответов и обновлений и сделайте что-то вроде этого:

Добавить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
        }
    }
}
</gpssatellite>

API-интерфейсы немного неясно, когда и что предоставляется информация о GPS и спутниках, но я думаю, что идея будет состоять в том, чтобы посмотреть, сколько спутников доступно. Если оно'ниже трех, то вы можетене могу исправить. Если оно'Чем больше, тем лучше.

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

В самом деле. Хотя я небольше не знаю, какая информация требуется для исправления или как / можно ли ее получить изGpsSatellite объект. Christopher Orr
Еще одна мысль .. ты нене упомянуть об этом в своем вопросе, но вы пытались просто использоватьLocationManager.requestLocationUpdates с настройками времени и расстояния, установленными на 0? Это должно отправить вам GPS-исправления, как только они произойдут. Если ты'если вы ничего не получаете, то скорее всегоне могу исправить. Вы можете объединить это со статусом слушателя выше, если хотите. Christopher Orr
ИтерированиеСац» и проверка usedInFix () в GpsSatell может быть? DeliriumTremens
проблема с подсчетом доступных спутников заключается в том, что даже если у вас есть 5 спутников, это неЭто означает, что исправить это всегда возможно. (Вы упомянули это правильно, написав "Если оно'больше, чем тыдолжен исправить ") nr1
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!). Если оно'Достаточно недавно у вас есть решение.

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

+1 стоит попробовать, если вы сразу захотите узнать, есть ли исправление. AgentKnopf
18

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

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

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

чтобы:

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

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

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

1

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

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

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

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

0

что уже пробовали onStatusChanged (), но это работает для меня.

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

К сожалению, это часто не работает. onLocationChanged () вызывается раз в секунду, но onStatusChanged не вызываетТебя вообще не зовут. Иногда я хотел бы просто запросить текущее состояние вместо ожидания уведомления, которое может не появиться в течение долгого времени или никогда. Edward Falk
Правильно. Я'После этого предыдущего ответа я узнал несколько вещей, и одна из них состоит в том, что не все платформы Android сделаны одинаково. Я определенно вижу вызовы onStatusChanged как на моем HTC Hero, так и на Archos 5, но яЯ не удивлен, что неработать не везде. Как насчет плана B: вы используете GPSStatusListener, который показан в другом ответе, и просто смотрите, возвращает ли какой-либо из спутников значение true для usedInFix (). По моему опыту это ближе всего подходит к поведению стандартной иконки GPS. (Вы пытались найти источник, который реализует этот стандартный значок, кстати?) CvR
1

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

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

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;
        }
    }
}
+1 Спасибо - это было очень интересно. AgentKnopf
1

о, как получите getBestProvider (). Это дает вам объект Location, который имеет методы getAccuracy () в метрах и getTime () в миллисекундах UTC

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

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

1

так много постов ...

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

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

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

Это только первое исправление. Что если вы войдете в туннель? Leos Literak
8

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

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

классно! это объясняет Стивена Деякод с Someone Somewhere
Не могли бы вы объяснить метод сравнения времени? Стивен ДэйВ ответ он сравнил разницу во времени между последним исправлением и последним событием GPS_EVENT_SATELLITE_STATUS ... Не уверен, что именно он измеряет. Rokey Ge
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 ()

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

Ваше решение слишком сложное для того, что оно делает. Однако это очень мало. Что, если после того, как gps определит мое местоположение, я пойду на станцию метро, и, таким образом, gps потеряет исправление? meandre

Похожие вопросы