Android - лучший способ реализовать LocationListener в нескольких видах деятельности - PullRequest
40 голосов
/ 26 апреля 2011

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

Мне интересно, каков наиболее эффективный способ отслеживать местоположение пользователя по нескольким действиям. Прямо сейчас я создал сервис, который реализует LocationListener и использует широковещательную рассылку для обновления статических полей lat и long в базовом классе Activity. Это означает, что сервис всегда работает, что не идеально. Но если я выключаю службу и перезапускаю ее только тогда, когда мне это нужно, требуется время, чтобы найти подходящее место. Мне нужны данные о местоположении в onCreate () деятельности. То же самое, если я попытаюсь реализовать это в базовом классе активности. Если я постоянно регистрирую слушателя в onResume / onCreate и отменяю его регистрацию в onPause (), это займет слишком много времени, чтобы начать получать обновления. Я также попытался создать службу, к которой мог бы привязаться, поэтому она запускается только тогда, когда мне нужно местоположение. Но у меня та же проблема: привязка к службе и получение обновлений занимает слишком много времени.

Служба, которую я использую сейчас, работает, но из всего, что я прочитал, я не должен использовать постоянно работающую службу для таких тривиальных вещей, как эта. Но весь смысл приложения заключается в предоставлении соответствующих данных на основе текущего местоположения пользователя. Так что у меня есть сервис, который просто работает в фоновом режиме и периодически предоставляет обновления. Одна из основных проблем, которая заставила меня пересмотреть дизайн на этом этапе, заключается в том, что я недавно обнаружил, что onProviderEnabled () не вызывается, если пользователь запускает приложение без включенного GPS, а затем включает его. В этом сценарии приложение не может распознать, что GPS был включен, поэтому оно может начать прослушивание обновлений.

Мне показалось, что я понял LocationManager и LocationListener, когда просматривал примеры, но я не могу применить их в такой ситуации, когда мне нужны данные о местоположении в нескольких видах деятельности. Буду признателен за любую помощь или совет.

Ответы [ 4 ]

43 голосов
/ 26 апреля 2011

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

Доступ к службе через привязки позволяет запускать и останавливать службу, поэтому она не работает, когда ваше приложениене на переднем плане (он умрет, как только больше не будут связаны Действия).IMO, чтобы сделать эту работу хорошо, это привязать службу в onStart() и UNBIND в onStop(), потому что эти два вызова перекрываются при переходе от одного действия к другому (второе действие начинается до остановки первого).Это предотвращает смерть Сервиса при перемещении внутри приложения и позволяет сервису умереть только тогда, когда все приложение (или, по крайней мере, любая часть, заинтересованная в местоположении) покидает передний план.

При использовании Привязок вы не сможетедолжны передавать данные местоположения в широковещательной рассылке, поскольку активность может вызывать методы непосредственно в службе для получения последнего местоположения.Тем не менее, широковещательная рассылка все равно будет полезна в качестве метода указания, КОГДА новое обновление доступно ... но оно просто станет уведомителем прослушивающей активности для вызова метода getLocation() в Сервисе.

Мои $ 0,02.Надеюсь, что поможет!

17 голосов
/ 20 апреля 2012

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

Я написал класс GPS.java:

public class GPS {

    private IGPSActivity main;

    // Helper for GPS-Position
    private LocationListener mlocListener;
    private LocationManager mlocManager;

    private boolean isRunning;

    public GPS(IGPSActivity main) {
        this.main = main;

        // GPS Position
        mlocManager = (LocationManager) ((Activity) this.main).getSystemService(Context.LOCATION_SERVICE);
        mlocListener = new MyLocationListener();
        mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
        // GPS Position END
        this.isRunning = true;
    }

    public void stopGPS() {
        if(isRunning) {
            mlocManager.removeUpdates(mlocListener);
            this.isRunning = false;
        }
    }

    public void resumeGPS() {
        mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
        this.isRunning = true;
    }

    public boolean isRunning() {
        return this.isRunning;
    }

    public class MyLocationListener implements LocationListener {

        private final String TAG = MyLocationListener.class.getSimpleName();

        @Override
        public void onLocationChanged(Location loc) {
            GPS.this.main.locationChanged(loc.getLongitude(), loc.getLatitude());
        }

        @Override
        public void onProviderDisabled(String provider) {
            GPS.this.main.displayGPSSettingsDialog();
        }

        @Override
        public void onProviderEnabled(String provider) {

        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {

        }

    }

}

Этот класс используется в каждом действии, для которого нужны координаты GPS.В каждом действии должен быть реализован следующий интерфейс (необходимый для общения):

public interface IGPSActivity {
    public void locationChanged(double longitude, double latitude);
    public void displayGPSSettingsDialog();
}

Теперь моя основная активность выглядит так:

public class MainActivity extends Activity implements IGPSActivity {

    private GPS gps;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        gps = new GPS(this);
    }


    @Override
    protected void onResume() { 
        if(!gps.isRunning()) gps.resumeGPS();   
        super.onResume();
    }

    @Override
    protected void onStop() {
        gps.stopGPS();
        super.onStop();
    }


    public void locationChanged(double longitude, double latitude) {
        Log.d(TAG, "Main-Longitude: " + longitude);
        Log.d(TAG, "Main-Latitude: " + latitude);
    }


    @Override
    public void displayGPSSettingsDialog() {
                Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                startActivity(intent);
    }
}

и вторая такая:

public class TEST4GPS extends Activity implements IGPSActivity{

    private GPS gps;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.gps = new GPS(this);
    }

    @Override
    public void locationChanged(double longitude, double latitude) {
        Log.d("TEST", "Test-Longitude: " + longitude);
        Log.d("TEST", "Test-Latitude: " + latitude);

    }

    @Override
    protected void onResume() { 
        if(!gps.isRunning()) gps.resumeGPS();   
        super. onResume();
    }

    @Override
    protected void onStop() {
        gps.stopGPS();
        super.onStop();
    }

    @Override
    public void displayGPSSettingsDialog() {
                Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                startActivity(intent);

    }
}

Это не так красиво, как решение Devunwired, но оно работает для меня.су

0 голосов
/ 19 января 2016

Вот очень простой и понятный способ сделать это:

В вашей основной деятельности:

private boolean mFinish;

@Override
public void onBackPressed() {
    mFinish = true;
}


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mFinish = false;
    ...
}

@Override
public void onPause(){
    super.onPause();
    if (mFinish) {
        // remove updates here
        mLocationManager.removeUpdates(mLocationListener);
    }
}

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

Это не лучший способ сделать это, но это простое решение для копирования и вставки.

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

0 голосов
/ 26 апреля 2011

Ваш сервис может записывать свои широковещательные и длинные координаты в sqlite db при изменении таким образом, что у вас не будет накладных расходов на привязку сервиса, и ваши координаты будут доступны во всех ваших действиях.

Возможно, в своей основной деятельности вы можете проверить статус GPS, а если он выключен, вы можете предложить пользователю включить его. Как только GPS включен, запустите ваш сервис.

...