Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Android находит местоположение GPS один раз, показывает диалог загрузки

Автор вопроса: Daniel BowdenОтветов: 3

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

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

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

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

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

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

Подводя итог, я хочу:
* Найти текущие координаты
* Показать диалоговое окно прогресса при получении местоположения
* Может ли приложение ждать успешного определения местоположения или сдаться через определенное время?
* Если успешно : закрыть диалоговое окно "Ход выполнения" и использовать координаты для запуска других моих методов поиска предметов поблизости.
* Если не удалось получить местоположение: закрыть диалоговое окно "Ход выполнения" и показать сообщение об ошибке, а также предложить пользователю использовать меню для перехода к действиям поиска.
* Используйте эти координаты, если пользователь выбирает вид карты из меню, чтобы показать текущее местоположение на карте и булавки, установленные на всех близлежащих элементах, используя их координаты из базы данных.

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

ИЗМЕНИТЬ
Код согласно запросу

файл активности 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);
    }
}

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

  • stackoverflow.com/questions/3145089/ Rajal 07.07.2014

androidprogressdialoggpslocationlistener

Ответы

Ответ 1 · рейтинг 16 · Mathias Conradt

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

Хороший пример кода здесь: location-in-an/3145655#3145655">Какой самый простой и надежный способ узнать текущее местоположение пользователя на Android?

Для AsyncTask см. http://developer.android.com/reference/android/os/AsyncTask.html

Здесь на SO также есть много примеров кода, например здесь: Android Показать диалоговое окно, пока поток не будет завершен, а затем продолжить работу с программой

РЕДАКТИРОВАТЬ: концепция кода:

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

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);
};

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

Ответ 2 · рейтинг 12 · Daniel Bowden

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

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

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
            }
        }
    }

Затем местоположениеРезультат..

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 в классе Location Helper делает следующее:

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

Удачи с ним, он мне был нужен...

Ответ 3 · Carl

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

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы