tareas - programar tarea en android
Programar tareas recurrentes en Android (6)
Minutero
Como se mencionó en los Timer , es mejor utilizar un ScheduledThreadPoolExecutor.
ScheduledThreadPoolExecutor
Utilice esta clase cuando su caso de uso requiera múltiples hilos de trabajo y el intervalo de descanso sea pequeño. Cuán pequeño ? Bueno, yo diría unos 15 minutos. El AlarmManager
comienza a programar intervalos en este momento y parece sugerir que para intervalos de sueño más pequeños se puede usar esta clase. No tengo datos para respaldar la última declaración. Es una corazonada.
Servicio
Su servicio puede ser cerrado en cualquier momento por la máquina virtual. No use servicios para tareas recurrentes. Una tarea recurrente puede iniciar un servicio, que es otra cosa completamente distinta.
BroadcastReciever con AlarmManager
Para intervalos de sueño más largos (> 15 minutos), este es el camino a seguir. AlarmManager
ya tiene constantes ( AlarmManager.INTERVAL_DAY
) que sugieren que puede desencadenar tareas varios días después de que se haya programado inicialmente. También puede activar la CPU para ejecutar su código.
Debe usar una de esas soluciones según sus necesidades de sincronización y de trabajo.
Estoy diseñando una aplicación que tiene la tarea recurrente de enviar presencia a un servidor dedicado, siempre y cuando la aplicación esté en primer plano.
En mis búsquedas en la web vi algunos enfoques diferentes y quería saber cuál es la mejor manera de hacerlo.
¿Cuál es la mejor manera de programar una llamada al servidor?
Las opciones que vi fueron:
Service .
BroadcastReciever con AlarmManager .
¿Cual es tu opinion?
EDITAR:
La razón por la que necesito esto es para una aplicación basada en chat que envía todas las acciones del usuario a un servidor remoto.
es decir, el usuario está escribiendo un mensaje, el usuario está leyendo un mensaje, el usuario está en línea, el usuario está fuera de línea, etc.
Esto significa que una vez cada intervalo, necesito enviar al servidor lo que estoy haciendo, ya que abro una sala de chat con otras personas, ellos necesitan saber lo que estoy haciendo.
Similar al mecanismo de retroalimentación de mensajes de whatsapp:
EDIT # 2:
Las tareas recurrentes ahora deben programarse casi siempre a través de la API JobScheduler
(o FirebaseJobDispatcher
para las API inferiores) para evitar problemas de JobScheduler
la batería, como se puede leer en la sección de vitals de la capacitación de Android.
Cómo citar la programación de repetición de alarmas - Comprender los documentos Trade-offs :
Un escenario común para activar una operación fuera de la vida útil de su aplicación es sincronizar los datos con un servidor. Este es un caso en el que podría estar tentado de usar una alarma repetitiva. Pero si posee el servidor que aloja los datos de su aplicación, usar Google Cloud Messaging (GCM) junto con el adaptador de sincronización es una mejor solución que AlarmManager. Un adaptador de sincronización le ofrece todas las mismas opciones de programación que AlarmManager, pero le ofrece mucha más flexibilidad.
Entonces, en base a esto, la mejor forma de programar una llamada al servidor es usar Google Cloud Messaging (GCM) junto con el adaptador de sincronización .
He creado una tarea a tiempo en la que la tarea que el usuario desea repetir agrega en el método Custom TimeTask run (). está sucediendo con éxito.
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);
}});
}
}
}
Me doy cuenta de que esta es una vieja pregunta y ha sido respondida, pero esto podría ayudar a alguien. En tu activity
private ScheduledExecutorService scheduleTaskExecutor;
En 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.
No estoy seguro, pero según mi conocimiento, comparto mis puntos de vista. Siempre acepto la mejor respuesta si estoy equivocado.
Gerente de alarma
Alarm Manager tiene un bloqueo de activación de onReceive()
que se esté ejecutando el método onReceive()
del receptor de alarma. Esto garantiza que el teléfono no se apagará hasta que haya terminado de manejar la transmisión. Una vez que onReceive()
, el Alarm Manager libera este bloqueo de onReceive()
. Esto significa que, en algunos casos, el teléfono se onReceive()
tan pronto como se onReceive()
método onReceive()
. Si su receptor de alarmas llamó a Context.startService()
, es posible que el teléfono se apague antes de que se inicie el servicio solicitado. Para evitar esto, su BroadcastReceiver
and Service
deberá implementar una política de bloqueo de activación independiente para garantizar que el teléfono continúe ejecutándose hasta que el servicio esté disponible.
Nota: Alarm Manager está diseñado para casos en los que desee que su código de aplicación se ejecute en un momento específico, incluso si su aplicación no se está ejecutando actualmente. Para las operaciones de temporización normales (ticks, tiempos de espera, etc.) es más fácil y mucho más eficiente usar Handler.
Minutero
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
synchronized public void run() {
// here your todo;
}
}}, TimeUnit.MINUTES.toMillis(1), TimeUnit.MINUTES.toMillis(1));
Timer
tiene algunos inconvenientes que se solucionan con ScheduledThreadPoolExecutor
. Entonces no es la mejor opción
ScheduledThreadPoolExecutor .
Puede usar java.util.Timer
o ScheduledThreadPoolExecutor
(preferido) para programar una acción que ocurrirá a intervalos regulares en una cadena de fondo.
Aquí hay una muestra usando el último:
ScheduledExecutorService scheduler =
Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate
(new Runnable() {
public void run() {
// call service
}
}, 0, 10, TimeUnit.MINUTES);
Así que preferí ScheduledExecutorService
Pero también piense que si las actualizaciones ocurrirán mientras su aplicación se está ejecutando, puede usar un Timer
, como se sugiere en otras respuestas, o el más nuevo ScheduledThreadPoolExecutor
. Si su aplicación se actualizará incluso cuando no esté en ejecución, debe ir con AlarmManager
.
Alarm Manager está diseñado para casos en los que desee que su código de aplicación se ejecute en un momento específico, incluso si su aplicación no se está ejecutando actualmente.
Tenga en cuenta que si planea actualizar cuando su aplicación está apagada, una vez cada diez minutos es bastante frecuente y, por lo tanto, posiblemente consuma demasiada energía.
Tal vez no sea una respuesta para su pregunta, sino un consejo para la estructura de su aplicación. En cuanto a mí, es mucho más fácil usar el nodo JS con SOCKET.IO para aplicaciones como el chat. Y como es en tiempo real, no es necesario que preguntes al servidor cada cierto tiempo. Ahí puedes leer más sobre SOCET IO - http://socket.io/