Intereting Posts
Как играть в mms: // ссылку в Android-плеер Android GCM-GCMRegistrar checkManifest (this) – Ошибка файла манифеста Можно ли использовать метод BitmapFactory.decodeFile для декодирования изображения из местоположения http? Не удается удалить слушателя ViewPropertyAnimator Инструмент Patch для Android 9: Какова новая функция рамки? Android: настройка вкладок в состоянии: как сделать селектор доступным Оценка услуги радиомаяков в фоновом режиме Панель инструментов не отображается с помощью салфетки для обновления Невозможно сжать переработанное растровое изображение Невозможно вызвать REST API в android NotificationListenerService: NullPointerException в getActiveNotifications Как использовать два эмулятора одновременно в одном проекте в Android Studio? Получение строкового значения из объекта массива JSON в Java Высота вложенного ресайклера не ограничивает его содержимое Как удалить строку в первой позиции sqlite в android

Планирование повторяющейся задачи на Android

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

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

Каков наилучший способ запланировать вызов сервера?

Варианты, которые я видел, были:

  1. Таймер .

  2. ScheduledThreadPoolExecutor .

  3. Сервис .

  4. BroadcastReciever с AlarmManager .

Каково ваше мнение?

РЕДАКТИРОВАТЬ:
Причина, по которой мне это нужно, – это приложение для чата, которое отправляет все действия пользователя на удаленный сервер.
Т.е. пользователь вводит сообщение, пользователь читает сообщение, пользователь в сети, пользователь отключен и т. Д.

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

Подобно механизму обратной связи сообщения Whatsash: Сообщение выглядит доставленным

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

    Менеджер аварийных сообщений

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

    Примечание. Диспетчер аварийных сигналов предназначен для случаев, когда вы хотите, чтобы ваш код приложения запускался в определенное время, даже если ваше приложение в настоящее время не работает. Для обычных операций синхронизации (тиков, тайм-аутов и т. Д.) Проще использовать Handler.

    таймер

     timer = new Timer(); timer.scheduleAtFixedRate(new TimerTask() { synchronized public void run() { \\ here your todo; } }}, TimeUnit.MINUTES.toMillis(1), TimeUnit.MINUTES.toMillis(1)); 

    Timer есть некоторые недостатки, которые решаются ScheduledThreadPoolExecutor . Так что это не лучший выбор

    ScheduledThreadPoolExecutor .

    Вы можете использовать java.util.Timer или ScheduledThreadPoolExecutor (предпочтительно), чтобы запланировать, чтобы действие происходило через равные промежутки времени в фоновом потоке.

    Вот пример с использованием последнего:

     ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); scheduler.scheduleAtFixedRate (new Runnable() { public void run() { // call service } }, 0, 10, TimeUnit.MINUTES); 

    Поэтому я предпочел ScheduledExecutorService

    Но подумайте об этом, если обновления будут выполняться во время работы вашего приложения, вы можете использовать Timer , как это предлагается в других ответах, или новый ScheduledThreadPoolExecutor . Если ваше приложение будет обновляться, даже если оно не запущено, вы должны пойти с AlarmManager .

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

    Обратите внимание, что если вы планируете обновлять, когда приложение отключено, то каждые 10 минут достаточно часты и, следовательно, могут быть слишком энергоемкими.

    таймер

    Как упоминалось в javadocs, вам лучше использовать ScheduledThreadPoolExecutor.

    ScheduledThreadPoolExecutor

    Используйте этот класс, если для вашего случая использования требуется несколько рабочих потоков, а интервал ожидания невелик. Насколько малы? Ну, я бы сказал, около 15 минут. В это время AlarmManager запускает интервалы времени и, как представляется, для меньших интервалов сна этот класс может использоваться. У меня нет данных для возврата последнего утверждения. Это догадка.

    обслуживание

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

    BroadcastReciever с AlarmManager

    Для более длительных спящих интервалов (> 15 минут) это путь. AlarmManager уже имеет константы ( AlarmManager.INTERVAL_DAY ), предполагая, что он может запускать задачи через несколько дней после того, как он был запланирован. Он также может разбудить CPU для запуска вашего кода.

    Вы должны использовать одно из этих решений на основе ваших потребностей времени и рабочего потока.

    Я понимаю, что это старый вопрос, на который был дан ответ, но это может помочь кому-то. В вашей activity

     private ScheduledExecutorService scheduleTaskExecutor; 

    В onCreate

      scheduleTaskExecutor = Executors.newScheduledThreadPool(5); //Schedule a task to run every 5 seconds (or however long you want) scheduleTaskExecutor.scheduleAtFixedRate(new Runnable() { @Override public void run() { // Do stuff here! runOnUiThread(new Runnable() { @Override public void run() { // Do stuff to update UI here! Toast.makeText(MainActivity.this, "Its been 5 seconds", Toast.LENGTH_SHORT).show(); } }); } }, 0, 5, TimeUnit.SECONDS); // or .MINUTES, .HOURS etc. 

    Цитирование предупреждений о повторном расписании – ознакомьтесь с документами о компромиссах :

    Общим сценарием для запуска операции за пределами срока службы вашего приложения является синхронизация данных с сервером. Это случай, когда у вас может возникнуть соблазн использовать повторяющийся сигнал. Но если у вас есть сервер, на котором размещаются данные вашего приложения, использование Google Cloud Messaging (GCM) в сочетании с адаптером синхронизации является лучшим решением, чем AlarmManager. Адаптер синхронизации предоставляет вам все те же параметры планирования, что и AlarmManager, но он предлагает вам значительно большую гибкость.

    Поэтому, исходя из этого, лучший способ запланировать вызов сервера – использовать Google Cloud Messaging (GCM) в сочетании с адаптером синхронизации .

    Я создал по времени задачу, в которой задача, которую пользователь хочет повторить, добавить в метод Custom TimeTask run (). Он успешно повторяется.

      import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Timer; import java.util.TimerTask; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.CheckBox; import android.widget.TextView; import android.app.Activity; import android.content.Intent; public class MainActivity extends Activity { CheckBox optSingleShot; Button btnStart, btnCancel; TextView textCounter; Timer timer; MyTimerTask myTimerTask; int tobeShown = 0 ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); optSingleShot = (CheckBox)findViewById(R.id.singleshot); btnStart = (Button)findViewById(R.id.start); btnCancel = (Button)findViewById(R.id.cancel); textCounter = (TextView)findViewById(R.id.counter); tobeShown = 1; if(timer != null){ timer.cancel(); } //re-schedule timer here //otherwise, IllegalStateException of //"TimerTask is scheduled already" //will be thrown timer = new Timer(); myTimerTask = new MyTimerTask(); if(optSingleShot.isChecked()){ //singleshot delay 1000 ms timer.schedule(myTimerTask, 1000); }else{ //delay 1000ms, repeat in 5000ms timer.schedule(myTimerTask, 1000, 1000); } btnStart.setOnClickListener(new OnClickListener(){ @Override public void onClick(View arg0) { Intent i = new Intent(MainActivity.this, ActivityB.class); startActivity(i); /*if(timer != null){ timer.cancel(); } //re-schedule timer here //otherwise, IllegalStateException of //"TimerTask is scheduled already" //will be thrown timer = new Timer(); myTimerTask = new MyTimerTask(); if(optSingleShot.isChecked()){ //singleshot delay 1000 ms timer.schedule(myTimerTask, 1000); }else{ //delay 1000ms, repeat in 5000ms timer.schedule(myTimerTask, 1000, 1000); }*/ }}); btnCancel.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { if (timer!=null){ timer.cancel(); timer = null; } } }); } @Override protected void onResume() { super.onResume(); if(timer != null){ timer.cancel(); } //re-schedule timer here //otherwise, IllegalStateException of //"TimerTask is scheduled already" //will be thrown timer = new Timer(); myTimerTask = new MyTimerTask(); if(optSingleShot.isChecked()){ //singleshot delay 1000 ms timer.schedule(myTimerTask, 1000); }else{ //delay 1000ms, repeat in 5000ms timer.schedule(myTimerTask, 1000, 1000); } } @Override protected void onPause() { super.onPause(); if (timer!=null){ timer.cancel(); timer = null; } } @Override protected void onStop() { super.onStop(); if (timer!=null){ timer.cancel(); timer = null; } } class MyTimerTask extends TimerTask { @Override public void run() { Calendar calendar = Calendar.getInstance(); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd:MMMM:yyyy HH:mm:ss a"); final String strDate = simpleDateFormat.format(calendar.getTime()); runOnUiThread(new Runnable(){ @Override public void run() { textCounter.setText(strDate); }}); } } 

    }

    BroadcastReciever с AlarmManager лучший способ запланировать серверный вызов для андроидной защиты.

    Может быть, это не ответ на ваш вопрос, а совет для структуры вашего заявления. Что касается меня, гораздо проще использовать узел JS с SOCKET.IO для таких приложений, как chat. И поскольку это в режиме реального времени, вам не нужно спрашивать сервер каждый раз. Там вы можете узнать больше о SOCET IO – http://socket.io/