Подтвердить что ты не робот

Тайм-аут GPS для Android

Изменить: Я переписываю этот вопрос, потому что я, по-видимому, не был ясен.

Иногда служба GPS на телефонах Android занимает много времени, чтобы исправить ситуацию. Иногда это быстро, иногда это занимает несколько часов. Я знаю и принимаю это.

У меня есть приложение, которое делает много вещей. Одна из вещей, которую он должен сделать, это позволить пользователю нажать кнопку, чтобы отправить свои текущие координаты на сервер. Мне нужны координаты телефона , когда пользователь нажимает кнопку или в течение относительно короткого времени после этого.

Поскольку я знаю, что получение GPS-исправления не является мгновенным, и я знаю, что это может занять несколько минут или часов (в течение которых пользователь переместился на большое расстояние), мне нужно закодировать тайм-аут для этой функции. Для этой функции просто неприемлемо загружать GPS-местоположение пользователя три минуты (например) после нажатия кнопки. Это нормально, если требуется 45 секунд, не так, если требуется 75 секунд. Это прекрасно, чтобы дать пользователю уведомление об ошибке, если функция не смогла получить местоположение достаточно быстро.

Мне нужна функция, чтобы "получить местоположение GPS и отправить его на сервер, , если это занимает более одной минуты".

Мой исходный код приведен ниже. Я изменил некоторые вещи после публикации. Я добавил таймер в метод onStartCommand(). Я запускаю TimerTask, который через 60 секунд вызовет мой метод stop(). В начале метода onLocationChanged() я отменяю TimerTask.

Мой вопрос: Является ли схема таймера хорошим способом реализации этого таймаута? Есть ли лучший способ?

Оригинальный вопрос:

Я пишу приложение для Android, которое, помимо прочего, должно отправлять текущие координаты GPS на сервер, когда пользователь сообщает об этом. В контекстном меню я запускаю службу ниже. Служба - это LocationListener и запрашивает обновления из LocationManager. Когда он получает местоположение (onLocationChanged()), он удаляет себя в качестве слушателя и отправляет координаты на сервер. Все это работает.

Однако, если координаты GPS не будут быстро доступны, мой сервис просто продолжает работать, пока он не получит некоторые. Он поддерживает пользовательский интерфейс с диалоговым окном прогресса, который раздражает. Хуже того, если пользователь перешел с момента запуска службы, первые GPS-координаты могут быть неправильными, и приложение отправит плохие данные на сервер.

Мне нужен тайм-аут в сервисе. Есть ли хороший способ сделать это? Я не очень разбираюсь в потоках. Я думаю, что я могу запустить Runnable в методе onStartCommand(), который каким-то образом будет отсчитывать 30 секунд, а затем, если результат GPS еще нет, вызовите мой метод stop(). Это звучит как лучший способ сделать это?

В качестве альтернативы можно ли определить, не может ли GPS получить исправление? Как мне это сделать?

Изменить: Чтобы уточнить, я ищу лучший способ "отказаться" от получения местоположения через некоторое время.

public class AddCurrentLocation extends Service implements LocationListener {

    Application app;
    LocationManager mLocManager;
    ProgressDialog mDialog;

    @Override
    public int onStartCommand(Intent intent, int arg0, int arg1) {
        app = getApplication();

        // show progress dialog
        if (app.getScreen() != null) {
            mDialog = ProgressDialog.show(app.getScreen(), "", "Adding Location. Please wait...", true);
        }

        // find GPS service and start listening
        Criteria criteria = new Criteria();
        criteria.setAccuracy(Criteria.ACCURACY_FINE);
        mLocManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        String bestProvider = mLocManager.getBestProvider(criteria, true);
        mLocManager.requestLocationUpdates(bestProvider, 2000, 0, this);

        return START_NOT_STICKY;
    }

    private void stop() {
        mLocManager.removeUpdates(this);
        if (mDialog != null) {
            mDialog.dismiss();
        }
        stopSelf();
    }

    @Override
    public void onLocationChanged(Location location) {
        // done with GPS stop listening
        mLocManager.removeUpdates(this);

        sendLocation(location); // method to send info to server
        stop();
    }

    // other required methods and sendLocation() ...

}
4b9b3361

Ответ 1

Это не так, как это работает. В большинстве ситуаций это будет длиться долго, чтобы получить исправление GPS. Но с этого момента каждое обновление (каждые 2 секунды в вашем коде) будет текущим положением человека. И первое исправление, которое вы получите, будет текущим положением человека, поэтому данные не будут "устаревшими".

Другое дело. Если вы выполняете этот код в службе, вы не должны блокировать пользовательский интерфейс с помощью диалогового окна прогресса и, определенно, не из Сервиса. Это утечка памяти, ожидающая своего появления. Вы должны показывать только прогресс, если это то, что может занять не более 5 секунд и работает в потоке в Activity. Другой вариант - показать диалог выполнения в строке заголовка и по-прежнему позволить пользователю взаимодействовать с приложением (поэтому вы все равно пользуетесь сервисом). Показывать прогресс в течение длительного периода времени, действительно, не является Другим. Особенно, если они каким-то образом меняют ориентацию (возможно, на случай аварии), а затем ваше приложение выходит из строя из-за дескриптора службы в диалоговом окне, и они должны начать все сначала.

Взгляните на приложение Google I/O 2010, чтобы увидеть отличный пример того, как деятельность должна работать с сервисом. Он использует службу для извлечения данных и показывает прогресс в заголовке, пока служба выполняет определенную работу. И все же позволяет вам делать другие вещи в приложении.

Ответ 2

Скорее всего, есть много факторов, влияющих на то, как долго может произойти первое исцеление - или даже можно ли исправить, причем наиболее распространенными являются физические препятствия между устройством и спутниками (такие здания, стены каньона и т.д.).

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

locationManager.addGpsStatusListener(gpsListener);

    // this reports on the status of the GPS engine, but does not enable additional controls 
    private static final GpsStatus.Listener gpsListener = new GpsStatus.Listener() {
        public void onGpsStatusChanged(int event) {
            GpsStatus gpsStatus = locationManager.getGpsStatus(null);
            switch (event) {
                case GpsStatus.GPS_EVENT_STARTED: 
                    Log.i(TAG, "onGpsStatusChanged(): GPS started");
                    break;
                case GpsStatus.GPS_EVENT_FIRST_FIX: 
                    Log.i(TAG, "onGpsStatusChanged(): time to first fix in ms = " + gpsStatus.getTimeToFirstFix());
                    break;
                case GpsStatus.GPS_EVENT_SATELLITE_STATUS: 
                    // int maxSatellites = gpsStatus.getMaxSatellites();    // appears fixed at 255
                    // if (H.DEBUG) Log.d(TAG, "onGpsStatusChanged(): max sats = " + maxSatellites);
                    if (H.VERBOSE) Log.d(TAG, "onGpsStatusChanged(): ##,used,s/n,az,el");
                    Iterable<GpsSatellite>satellites = gpsStatus.getSatellites();
                    Iterator<GpsSatellite>satI = satellites.iterator();
                    while (satI.hasNext()) {
                        GpsSatellite satellite = satI.next();
                        if (H.VERBOSE) Log.d(TAG, "onGpsStatusChanged(): " + satellite.getPrn() + "," + satellite.usedInFix() + "," + satellite.getSnr() + "," + satellite.getAzimuth() + "," + satellite.getElevation()); 
                        // http://en.wikipedia.org/wiki/Global_Positioning_System: the almanac consists of coarse orbit and status information for each satellite
                        // http://en.wikipedia.org/wiki/Ephemeris: the positions of astronomical objects in the sky at a given time
                        // + "," + satellite.hasAlmanac() + "," + satellite.hasEphemeris());
                    }
                    break;
                case GpsStatus.GPS_EVENT_STOPPED: 
                    Log.i(TAG, "onGpsStatusChanged(): GPS stopped");
                    break;
            }       
        }
    };

События будут генерироваться, когда движок пытается прослушивать доступные спутники. На недавнем испытании этого с легкими препятствиями я обнаружил, что для первоначального исправления потребовалось 22,4 секунды, в течение которого 24 события SATELLITE_STATUS сообщали о постепенном доступе 8 спутников до получения достаточно чистых сигналов для достижения исправления. Вот последнее событие:

06-08 23: 23: 25.147, D, GPS, 22427, "onGpsStatusChanged(): ##, used, s/n, az, el" 06-08 23: 23: 25.147, D, GPS, 22427, "onGpsStatusChanged(): 2, true, 26.0,57.0,73.0" 06-08 23: 23: 25.147, D, GPS, 22427, "onGpsStatusChanged(): 4, true, 30,0,46.0,27.0" 06-08 23: 23: 25.147, D, GPS, 22427, "onGpsStatusChanged(): 5, true, 19.0,144.0,25.0" 06-08 23: 23: 25.155, D, GPS, 22427, "onGpsStatusChanged(): 9, true, 22.0,202.0,22.0" 06-08 23: 23: 25.155, D, GPS, 22427, "onGpsStatusChanged(): 10, true, 17.0,109.0,32.0" 06-08 23: 23: 25.155, D, GPS, 22427, "onGpsStatusChanged(): 12, true, 32.0.320.0,80.0" 06-08 23: 23: 25.155, D, GPS, 22427, "onGpsStatusChanged(): 29, true, 21.0,278.0,21.0" 06-08 23: 23: 25.155, D, GPS, 22427, "onGpsStatusChanged(): 30, true, 31.0.312.0, 43.0" 06-08 23: 23: 25.163, D, GpsLocationProvider, 1039, TTFF: 22457 06-08 23: 23: 25.194, I, GPS, 22427, onGpsStatusChanged(): время для первого исправления в ms = 22457

Обратите внимание, что во время фиксации вы будете получать текущее местоположение, а не там, где вы когда-то были. Я думаю, вместе с тем, что вы уже можете получить там сейчас. Или, посмотрите, как это делают профессионалы здесь.

Ответ 4

Я боролся с подобной проблемой и недавно переключился с таймера на AlarmManager, который выглядит намного более надежным. Это может быть излишним для вашей ситуации (я использую это для повторной выборки местоположения), но вы можете хотя бы использовать Handler вместо таймера. (Используйте Handler.postDelayed.)

Ответ 5

Основываясь на ответе Shawn, упакуйте параметры в JSON и отправьте объекты JSON на сервер