Android GPS тайм-аут
Edit: я переписываю этот вопрос, потому что я, по-видимому, не был ясен.
Иногда служба 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 не может получить исправление? Как бы я это сделал?
Edit: чтобы еще больше прояснить, я ищу лучший способ "отказаться" от получения местоположения после некоторой суммы о времени.
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() ...
}
5 ответов:
На самом деле это не так. В большинстве случаев это займет много времени, чтобы получить GPS-фиксацию. Но с этого момента каждое обновление (каждые 2 секунды в вашем коде) будет соответствовать текущей позиции человека. И первое исправление, которое вы получите, будет текущее положение человека, поэтому данные не будут "устаревшими".
Еще одна вещь. Если вы запускаете этот код в сервисе, вы не должны блокировать пользовательский интерфейс с помощью диалогового окна хода выполнения и определенно не из сервиса. Это утечка памяти. ожидание того, что произойдет. Вы должны показывать прогресс только в том случае, если это что-то, что может занять не более 5 секунд и выполняется в потоке в действии. Другой вариант-показать диалог хода выполнения в строке заголовка, и все еще позволить пользователю взаимодействовать с приложением (поэтому вы все равно используете сервис). Показывать прогресс в течение длительного периода времени действительно не очень удобно. Особенно, если они каким-то образом меняют ориентацию (возможно, случайно), а затем ваше приложение аварийно завершает работу из-за дескриптора службы, чтобы диалог, и они должны начать все сначала.
Взгляните на приложение Google I/O 2010 , чтобы увидеть отличный пример того, как действие должно работать с сервисом. Он использует службу для извлечения данных и показывает прогресс в заголовке, пока служба выполняет некоторую работу. И все еще позволяет вам делать другие вещи в приложении.
Скотт, есть много факторов, которые влияют на то, как долго может занять первое исправление - или даже может ли быть достигнуто исправление, наиболее распространенными являются физические препятствия между устройством и спутниками (такие как здания, стены каньона и т. д.).
Вы не можете контролировать, сколько времени требуется для 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 ():##, используется, 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, правда, 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, верно, 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
Обратите внимание, что в фиксированное время вы получите текущее местоположение, а не то, где вы когда-то могли быть. Я думаю, что вместе с тем, что у вас уже есть, вы можете получить и сейчас. Или проверьте, как это делают профессионалы здесь.
Есть пример получения местоположения GPS с таймаутом.
Http://sikazi.blogspot.com/2010/09/android-gps-timeout.html#more
Я боролся с подобной проблемой и недавно переключился с таймера на таймер.
AlarmManager, что, по-видимому, гораздо надежнее. Это может быть излишним для вашей ситуации (я использую это для повторной выборки местоположения), но вы можете по крайней мере использоватьHandlerвместо таймера. (ИспользуйтеHandler.postDelayed.)
Comments