Запуск повторяющейся задачи в фоновом режиме в приложении реального времени - PullRequest
1 голос
/ 25 апреля 2011

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

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

Каков наилучший подход к задаче, которая должна производить вычисления и генерировать событие? Таймер? Потоки? AsynkTask? AlarmManager? Другой подход?

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

Я бы хотел услышать разные мнения. Заранее спасибо! Гильермо.

Ответы [ 2 ]

3 голосов
/ 25 апреля 2011

Вы можете использовать AlarmManager для настройки повторяющихся задач (это предпочитаемый Android способ установки будущих / повторяющихся задач).Чтобы сделать вычисления, используйте Service (если вы считаете, что вычисления будут дорогостоящими, подумайте о перемещении их в отдельный рабочий поток или используйте IntentService).

Относительно блокировки пробуждения (изСправочник по AlarmManager):

Диспетчер тревог удерживает активную блокировку ЦП, пока выполняется метод onReceive () получателя тревоги.Это гарантирует, что телефон не будет спать, пока вы не закончили обработку трансляции.Как только onReceive () возвращается, диспетчер тревог снимает эту пробужденную блокировку.Это означает, что телефон в некоторых случаях будет спать, как только ваш метод onReceive () завершится.Если ваш приемник тревоги называется Context.startService (), возможно, что телефон будет находиться в спящем режиме до запуска запрошенной службы.Чтобы предотвратить это, вашему BroadcastReceiver и Сервису потребуется реализовать отдельную политику блокировки пробуждения, чтобы телефон продолжал работать до тех пор, пока сервис не станет доступным.

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

Это модифицированный фрагмент сервиса, который я написал для регистрации частоты процессора некоторое время назад.В нем отсутствуют элементы Application и Activity, но показано, как я написал Service для ведения журнала каждые десять секунд.Он не регистрирует, когда телефон переходит в глубокий сон, поэтому, если вы хотите войти в систему без перерывов, вам нужно будет набрать PARTIAL_WAKE_LOCK с, но учтите, что это сильно сократит срок службы батареи.

public class YOURCLASS_Service extends Service {
    private long mStartTime = 0L;
    private final Handler mHandler = new Handler();
    private Runnable mUpdateTimeTask;
    private YOURAPP app;

    @Override
    public void onCreate() {
        super.onCreate();
        app = (YOURAPP) getApplicationContext();
    }

    @Override
    public void onDestroy() {
        Toast.makeText(this, "Service finished.", Toast.LENGTH_SHORT).show();
        stopLog ();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (app.isRunning())
            return START_STICKY;
        try {
            File file = new File(Environment.getExternalStorageDirectory(), "yourlog.csv");
            OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(file, false));
            out.write("Log title");
            out.close();
        } catch (java.io.IOException e) {
              stopLog ();
              Toast.makeText(this, "Error creating log file. Aborting.", Toast.LENGTH_SHORT).show();
        }

        mUpdateTimeTask = new Runnable() {
            public void run() {
                long millis = SystemClock.uptimeMillis() - mStartTime;
                int seconds = (int) (millis / 1000);
                int minutes = seconds / 60;
                seconds     = seconds % 60;

                readYourSensors ();
                   if (!writeLog (str)) stopLog();
                   mHandler.postAtTime(this, mStartTime + (((minutes * 60) + seconds + 10) * 1000));
                   mHandler.postDelayed (mUpdateTimeTask, 10000);
        }};
        mStartTime = SystemClock.uptimeMillis();
        mHandler.removeCallbacks(mUpdateTimeTask);
        mHandler.postDelayed(mUpdateTimeTask, 100);

        Notification notification = new Notification(R.drawable.notification_icon, "App title", System.currentTimeMillis());
        Intent notificationIntent = new Intent(this, YOURCLASS.class);
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
        notification.setLatestEventInfo(getApplicationContext(), "App title", "Please see /sdcard/yourlog.csv", contentIntent);
        startForeground(startId, notification);

        app.isRunning(true);
        return START_STICKY;
    }

    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    public void stopLog () {
            mHandler.removeCallbacks(mUpdateTimeTask);
    }
}    
...