2010-08-15 5 views
26

Я пишу приложение, которое требует текущего местоположения пользователя (lastknownlocation не будет очень полезно) и отображает список всех ближайших «элементов» к ним, взятым из базы данных.Android найти местоположение GPS один раз, показать диалог загрузки

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

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

Как я могу запустить диспетчер местоположений один раз в фоновом режиме, а затем удалить обновления местоположения после его нахождения. Мне нужно, чтобы остальная часть приложения подождала, пока у него не появится местоположение GPS или тайм-аут после 20-30 секунд. Мне нужен ProgressDialog, чтобы пользователь знал, что что-то происходит, но он просто должен быть анимацией вращающейся загрузки, а не процентом или чем-то еще. Если возможно, я хотел бы, чтобы пользователь мог отменить диалог, если им надоело ждать, а затем они могут искать, набирая пригород и т. Д.

Я пытался сделать это с помощью нитей, но он становится намного сложнее, чем я чувствую, что он должен быть и до сих пор не работает. На iPhone это намного проще?

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

В заключение хочу:
* Найти текущие координаты
* Show Dialog Progress при получении расположение
* Есть приложение быть в состоянии ждать удачного расположения или отказаться по истечении определенного времени?
* If Successful: Dismiss Progress Dialog и используйте координаты для запуска моих других методов поиска объектов.
* Если не удалось найти местоположение: Отклоните диалог прогресса и покажите сообщение об ошибке, и попросите пользователя использовать меню для перехода к активности поиска.
* Используйте эти координаты, если пользователь выберет из меню вид карты, чтобы отобразить текущее местоположение на карте и штифты, сброшенные во всех соседних элементах, используя их координаты из базы данных.

Спасибо, ребята, я надеюсь, что я достаточно хорошо объяснил. Любые вопросы просто спрашивают, я буду регулярно проверять, поскольку я заинтересован в том, чтобы эта часть была завершена. Приветствия

EDIT
код с просьбой

файл locationList активность

protected void onStart() 
{ 
    super.onStart(); 

    // .... 

    new LocationControl().execute(this); 
} 


private class LocationControl extends AsyncTask<Context, Void, Void> 
{ 
    private final ProgressDialog dialog = new ProgressDialog(branchAtmList.this); 

    protected void onPreExecute() 
    { 
     this.dialog.setMessage("Determining your location..."); 
     this.dialog.show(); 
    } 

    protected Void doInBackground(Context... params) 
    { 
     LocationHelper location = new LocationHelper(); 

     location.getLocation(params[0], locationResult); 

     return null; 
    } 

    protected void onPostExecute(final Void unused) 
    { 
     if(this.dialog.isShowing()) 
     { 
      this.dialog.dismiss(); 
     } 

     useLocation(); //does the stuff that requires current location 
    } 

} 

public LocationResult locationResult = new LocationResult() 
{ 
    @Override 
    public void gotLocation(final Location location) 
    { 
     currentLocation = location; 
    } 
}; 

LocationHelper класс

package org.xxx.xxx.utils; 

import java.util.Timer; 
/* 
imports 
*/ 

public class LocationHelper 
{ 
    LocationManager locationManager; 
    private LocationResult locationResult; 
    boolean gpsEnabled = false; 
    boolean networkEnabled = false; 

    public boolean getLocation(Context context, LocationResult result) 
    {  
     locationResult = result; 

     if(locationManager == null) 
     { 
      locationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE); 
     } 
      //exceptions thrown if provider not enabled 
      try 
      { 
       gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); 
      } 
      catch (Exception ex) {} 
      try 
      { 
       networkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); 
      } 
      catch (Exception ex) {} 

      //dont start listeners if no provider is enabled 
      if(!gpsEnabled && !networkEnabled) 
      { 
       return false; 
      } 

      if(gpsEnabled) 
      { 
       locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListenerGps); 
      } 
      if(networkEnabled) 
      { 
       locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListenerNetwork); 
      } 


      GetLastLocation(); 
      return true; 
    } 

    LocationListener locationListenerGps = new LocationListener() { 
     public void onLocationChanged(Location location) 
     { 
      locationResult.gotLocation(location); 
      locationManager.removeUpdates(this); 
      locationManager.removeUpdates(locationListenerNetwork); 

     } 
     public void onProviderDisabled(String provider) {} 
     public void onProviderEnabled(String provider) {} 
     public void onStatusChanged(String provider, int status, Bundle extra) {} 
    }; 

    LocationListener locationListenerNetwork = new LocationListener() { 
     public void onLocationChanged(Location location) 
     { 
      locationResult.gotLocation(location); 
      locationManager.removeUpdates(this); 
      locationManager.removeUpdates(locationListenerGps); 

     } 
     public void onProviderDisabled(String provider) {} 
     public void onProviderEnabled(String provider) {} 
     public void onStatusChanged(String provider, int status, Bundle extra) {} 

    }; 

    private void GetLastLocation() 
    { 
      locationManager.removeUpdates(locationListenerGps); 
      locationManager.removeUpdates(locationListenerNetwork); 

      Location gpsLocation = null; 
      Location networkLocation = null; 

      if(gpsEnabled) 
      { 
       gpsLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); 
      } 
      if(networkEnabled) 
      { 
       networkLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); 
      } 

      //if there are both values use the latest one 
      if(gpsLocation != null && networkLocation != null) 
      { 
       if(gpsLocation.getTime() > networkLocation.getTime()) 
       { 
        locationResult.gotLocation(gpsLocation); 
       } 
       else 
       { 
        locationResult.gotLocation(networkLocation); 
       } 

       return; 
      } 

      if(gpsLocation != null) 
      { 
       locationResult.gotLocation(gpsLocation); 
       return; 
      } 

      if(networkLocation != null) 
      { 
       locationResult.gotLocation(networkLocation); 
       return; 
      } 

      locationResult.gotLocation(null); 
    } 

    public static abstract class LocationResult 
    { 
     public abstract void gotLocation(Location location); 
    } 
} 

Это действительно похоже на большое усилие только для того, чтобы получить текущее местоположение один раз? Я не требую обновлений или чего-то еще? Нет ли более простого способа заставить приложение ждать результата? Я так долго застрял на этом.

+0

http://stackoverflow.com/questions/3145089/what-is-the-simplest-and-most-robust-way-to-get-the-users-current-location-in-a/9811633#9811633 – Rajal

ответ

17

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

Хороший пример кода здесь: What is the simplest and most robust way to get the user's current location on Android?

Для AsyncTask, посмотрите http://developer.android.com/reference/android/os/AsyncTask.html

Есть также много пример кода здесь на SO для него, например, здесь: Android Show a dialog until a thread is done and then continue with the program

EDIT: код концепции:

Добавить переменную класса

boolean hasLocation = false; 

вызова в OnCreate (не в AsyncTask):

locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener); 
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener); 

то в locationListener.onLocationChanged, изменить значение, как только местоположение найдено:

boolean hasLocation = false; 

AsyncTask: отпуск, как это , но не называть

LocationHelper location = new LocationHelper(); 
location.getLocation(params[0], locationResult); 

там, вместо того, чтобы сделать

Long t = Calendar.getInstance().getTimeInMillies(); 
while (!hasLocation && Calendar.getInstance().getTimeInMillies()-t<30000)) { 
    Thread.Sleep(1000); 
};  

вероятно, с задержкой между ними будет достаточно.

+0

Спасибо, это выглядит полезным. Я думал, что материал API GPS был асинхронным? Или мне все еще нужно реализовать это, чтобы приложение ожидало результата? На основании этих примеров: Так я бы назвал myLocation.getLocation (this, locationResult) из doInBackground (final String ... args)? Я просто не понимаю, когда onPostExecute (final Void unused) будет называться как конечный результат из материала MyLocation, это gotLocation (окончательное местоположение местоположения)? также, что произойдет, если таймер закончится вместо этого? –

+0

Да, материал gps асинхронный, но показ прогресса не является. поэтому вам нужно обернуть его в AsyncTask, так как диалог прогресса зависит от вашего состояния/результатов gps. onPostExecute и onPreExecute запускаются в основном потоке пользовательского интерфейса, поэтому вы обновляете свой интерфейс там, т. Е. После того, как вы получили gps-исправление, например, и также отпустите диалог прогресса там. –

+0

Хорошо спасибо, я отдам это. Как известно onPostExecute, когда у меня есть исправление gps или когда оно завершено? т.е. как он знает, когда вызывается либо getLocation(), либо таймер заканчивается? –

12

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

Если кто-то попадается это и предложить гораздо лучший результат очистки, чтобы просто получить текущие координаты местоположения пользователя только один раз, а затем перестать смотреть, что было бы очень полезно!

private LocationControl locationControlTask; 
private boolean hasLocation = false; 
LocationHelper locHelper; 

От OnCreate() я называю

locHelper = new LocationHelper(); 
locHelper.getLocation(context, locationResult); 
locationControlTask = new LocationControl(); 
locationControlTask.execute(this); 

Я тогда аа частный класс LocationControl

private class LocationControl extends AsyncTask<Context, Void, Void> 
    { 
     private final ProgressDialog dialog = new ProgressDialog(activityname.this); 

     protected void onPreExecute() 
     { 
      this.dialog.setMessage("Searching"); 
      this.dialog.show(); 
     } 

     protected Void doInBackground(Context... params) 
     { 
      //Wait 10 seconds to see if we can get a location from either network or GPS, otherwise stop 
      Long t = Calendar.getInstance().getTimeInMillis(); 
      while (!hasLocation && Calendar.getInstance().getTimeInMillis() - t < 15000) { 
       try { 
        Thread.sleep(1000); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      }; 
      return null; 
     } 

     protected void onPostExecute(final Void unused) 
     { 
      if(this.dialog.isShowing()) 
      { 
       this.dialog.dismiss(); 
      } 

      if (currentLocation != null) 
      { 
       useLocation(); 
      } 
      else 
      { 
       //Couldn't find location, do something like show an alert dialog 
      } 
     } 
    } 

Тогда locationResult ..

public LocationResult locationResult = new LocationResult() 
    { 
     @Override 
     public void gotLocation(final Location location) 
     { 
      currentLocation = new Location(location); 
      hasLocation = true; 
     } 
    }; 

Кроме того, чтобы избежать вы тянете ваши волосы, как я делал на протяжении веков, помнят, чтобы остановить работу по настройке местоположения, если кто-то рано уходит с работы, а также останавливает обновления местоположения, чтобы остановить работу GPS при выходе пользователя. В OnStop() сделать что-то вроде этого:

locHelper.stopLocationUpdates(); 
locationControlTask.cancel(true); 

Также stopLocationUpdates в классе Расположение Helper выполняет следующие действия:

public void stopLocationUpdates() 
{ 
locationManager.removeUpdates(locationListenerGps); 
locationManager.removeUpdates(locationListenerNetwork); 
} 

удачи с ней, мне нужно это ...

+6

опубликовать полный рабочий код (например, github) было бы замечательно для вас и для нас :) – ant

0

Вместо создания AsyncTask, почему вы не создали окно ProgressDialog и не отклонили его на public void gotLocation(final Location location){}? Вы также можете добавить onCancelListener в поле ProgressDialog и отменить любые текущие запросы местоположения.