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

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

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

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

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

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

4b9b3361

Ответ 1

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

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

С помощью Bindings вам не нужно передавать данные местоположения в широковещательном режиме, потому что Activity может вызывать методы непосредственно на службе, чтобы получить последнее местоположение. Тем не менее, широковещательная передача по-прежнему будет выгодна как способ указания WHEN, что новое обновление доступно... но это просто станет уведомляющим для прослушивающей активности вызовом метода getLocation() в службе.

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

Ответ 2

У меня такая же проблема, и я попытался решить ее с хорошим ответом 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, но оно работает для меня. суа

Ответ 3

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

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

Ответ 4

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

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

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

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

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

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