Android регулярный GPS-опрос в сервисе, продлевая время автономной работы - PullRequest
4 голосов
/ 01 марта 2012

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

Итак,время создавать сервис.

Я создал сервис, настроил locationListener, получил менеджер местоположений и requestLocationUpdates ... все хорошо с миром .. рудиментарный скелет работает.

СейчасЯ не хочу, чтобы GPS работал постоянно, так как это может привести к потере заряда батареи. Я хотел бы, чтобы сервис работал, запускал GPS, запрашивал обновление, затем выключал (по крайней мере, его интерес к местоположению GPS).и затем через 5 или 10 минут сделайте это снова ..

Достаточно просто, на методе onLocationChanged () моего слушателя, я добавляю строку LocationManager (removeUpdates (locationListener)) .. .. поэтому, когда мой сервис запрашиваетобновление, он получает только одно и закрывается.

Я решил добавить небольшой цикл while, который эффективно регистрирует мой слушатель местоположения, и sпрыгает на Х минут.Логично, что он должен зарегистрировать, что ему нужна информация, затем спать .. приходит обновление, я получаю это обновление в onLocationChange, и он отменяет регистрацию своего интереса в событии, отключая GPS до следующего выполнения цикла.

Теперь у меня есть 2 вопроса 1) Логично ли это нормально?или есть более элегантный способ?Помните, я хочу, чтобы это записывало информацию о том, находится ли запущенное приложение в фокусе, и, честно говоря, даже если запускаемое приложение было убито, хотелось бы, чтобы служба продолжала работать потенциально, но это решение по проекту, которое я еще не полностью приняла.

Второй вопрос: мне нужно будет поместить этот LOOP в поток, так как наличие его в oncreate приводит к тому, что служба в конечном итоге будет уничтожена, потому что она занимает слишком много времени, чтобы вернуться из oncreate, так что будетлучший способ сделать это?AsyncTask является опцией, но это задача, которая теоретически никогда не будет завершена. Обработчик также кажется глупым, поскольку нет реальных обратных вызовов, он просто регистрируется для обновлений GPS, а неинтересный код находится в LocationListener.onLocationChange ().

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

Так я должен просто использовать базовый поток?Перейти с AsyncTask, хотя он никогда не вернется?или лучше использовать Handler?Или моя модель просто в дурной форме вышла из ворот?

1 Ответ

3 голосов
/ 02 марта 2012

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

Сначала я использовал Ibinder в сервисе и привязал его к действиям с

bindService (new Intent(....),   mServconn, Context.BIND_AUTO_CREATE);

в onStart ()

и unbindService(mServconn); в onStop () каждого действия

У меня было использование службы sendBroadcast() до BroadcastReceivers, зарегистрированное в действиях.Данные о местоположении передаются через статистические данные в статистических целях.

Я использовал конечный автомат в сервисе с 3 состояниями: IDLE, SEEKING и GOT_A_FIX_NOW_SLEEPING.Время ожидания передается через метод changeGPSParameters, представленный в общедоступном методе службы.Другим параметром является требуемая точность, т. Е. Не транслируйте сообщение, пока не получите исправление, превышающее требуемую точность, тогда вы можете спатьСпящий режим означает отключение GPS до истечения времени.

Время управляется с помощью Runnable, и обработчик отправляет на него сообщения с кодом, подобным

mHandler.postDelayed(this, mSleepTime );

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

UPDATE

Ниже приведен простой пример Runnable, который вы можете запускать / останавливатьс помощью двух кнопок в вашем main.xml, которые должны иметь одно текстовое представление для отображения состояния таймера:

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.TextView;

public class TimerLoopActivity extends Activity {

    private Handler mHandler = new Handler();
    private int mSleepTime  = 2; //seconds
    private int mLoopCount = 0;
    private Runnable mUpdateTimeTask = new Runnable() {
        public void run() {
            // Code here for when timer completes
            mLoopCount++;
            setTextBoxMsg("Running - count = " + mLoopCount);
            mHandler.removeCallbacks(this);
            mHandler.postDelayed(this, mSleepTime * 1000); // keep looping
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        setTextBoxMsg("Timer Idle");
    }

    private void setTextBoxMsg(String string) {
        TextView tv = (TextView) findViewById(R.id.textView1);
        tv.setText(string);
    }

    public void myClickHandler(View target) {
        switch (target.getId()) {
            case R.id.startbutton:
                setTextBoxMsg("Starting timer");
                startTimer();
                break;
            case R.id.stopbutton:
                setTextBoxMsg("Stopping timer");
                mLoopCount = 0;
                stopTimer();
                break;
        }
    }

    private void stopTimer() { mHandler.removeCallbacks(mUpdateTimeTask); }
    private void startTimer() { mHandler.postDelayed(mUpdateTimeTask, mSleepTime * 1000);}
}

Вы можете изменить это, чтобы использовать его в своем сервисе.

...