AlarmManager, BroadcastReceiver y el servicio no funciona

Estoy refactorizando algún código para que mi aplicación extraiga datos de un sitio web una vez al día en un momento dado. De mi investigación, parece que AlarmManager es el enfoque más apropiado.

El tutorial que he estado siguiendo es: http://mobile.tutsplus.com/tutorials/android/android-fundamentals-downloading-data-with-services/

Hasta ahora, AlarmManager y el BroadcastReceiver parecen estar funcionando, sin embargo, el Service nunca parece comenzar (por ejemplo, onStartCommand no parece ser llamado)

Aquí están los fragmentos importantes del código que tengo hasta ahora:

MyActivity.java

 private void setRecurringAlarm(Context context) { Calendar updateTime = Calendar.getInstance(); updateTime.setTimeZone(TimeZone.getDefault()); updateTime.set(Calendar.HOUR_OF_DAY, 20); updateTime.set(Calendar.MINUTE, 30); Intent downloader = new Intent(context, AlarmReceiver.class); downloader.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, downloader, PendingIntent.FLAG_CANCEL_CURRENT); AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); // should be AlarmManager.INTERVAL_DAY (but changed to 15min for testing) alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis(), AlarmManager.INTERVAL_FIFTEEN_MINUTES, pendingIntent); Log.d("MyActivity", "Set alarmManager.setRepeating to: " + updateTime.getTime().toLocaleString()); } 

AlarmReceiver.java

 public class AlarmReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Intent dailyUpdater = new Intent(context, MyService.class); context.startService(dailyUpdater); Log.d("AlarmReceiver", "Called context.startService from AlarmReceiver.onReceive"); } } 

MyService.java

 public class MyService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d("MyService", "About to execute MyTask"); new MyTask().execute(); return Service.START_FLAG_REDELIVERY; } @Override public IBinder onBind(Intent intent) { return null; } private class MyTask extends AsyncTask<String, Void, boolean> { @Override protected boolean doInBackground(String... strings) { Log.d("MyService - MyTask", "Calling doInBackground within MyTask"); return false; } } } 

AndroidManifest.xml

 <application ...> ... <service android:name="MyService"></service> <receiver android:name="AlarmReceiver"></receiver> </application> 

Cuando disparo el setRecurringAlarm en MyActivity el registro se imprime como se esperaba, de manera similar, cada 15min aparece el registro de AlarmReceiver . Sin embargo, nunca veo el registro de MyService 🙁

Ejemplo de lo que veo en los registros:

 DEBUG/MyActivity(688): Set alarmManager.setRepeating to: Jan 29, 2012 8:30:06 PM DEBUG/AlarmReceiver(688): Called context.startService from AlarmReceiver.onReceive DEBUG/AlarmReceiver(688): Called context.startService from AlarmReceiver.onReceive 

No puedo imaginar lo que he hecho mal – mi entendimiento de los documentos de Android Dev es que en AlarmReceiver cuando llamo context.startService(dailyUpdater) que a su vez debe llamar onStartCommand en MyService , aunque eso no parece ¡sea el caso!

¿Qué estoy haciendo mal que está causando MyService para no empezar en absoluto?

¡Lo averigué!

MyService debe extender IntentService en lugar de Service !

Con este cambio, también significa que en lugar de reemplazar onStartCommand debería sobrescribir onHandleIntent (vea docs en IntentService )

Así que MyService ahora se parece a esto:

 public class MyService extends IntentService { public MyService() { super("MyServiceName"); } @Override protected void onHandleIntent(Intent intent) { Log.d("MyService", "About to execute MyTask"); new MyTask().execute(); } private class MyTask extends AsyncTask<String, Void, boolean> { @Override protected boolean doInBackground(String... strings) { Log.d("MyService - MyTask", "Calling doInBackground within MyTask"); return false; } } } 

Nota: Desde los documentos, la implementación predeterminada de onBind devuelve null por lo que no es necesario onBind .

Más información sobre la extensión de IntentService : http://developer.android.com/guide/topics/fundamentals/services.html#ExtendingIntentService

Usted podría obtener AlarmManager para ejecutar el Servicio de inmediato en lugar de pasar por un BroadcastReceiver, si cambia su intención de esta manera:

 //Change the intent Intent downloader = new Intent(context, MyService.class); downloader.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //Change to getService() PendingIntent pendingIntent = PendingIntent.getService(context, 0, downloader, PendingIntent.FLAG_CANCEL_CURRENT); 

Esto puede resolver su problema!

En lugar de usar

Intent dailyUpdater = new Intent(context, MyService.class);

utilizar

Intent dailyUpdater = new Intent(this, MyService.class);

Otra sugerencia es iniciar el servicio directamente desde la alarma en lugar de enviar una emisión e iniciar el servicio en el receptor de emisión.

  • Android BroadcastReceiver o método simple de devolución de llamada?
  • ¿Cómo notificar la actividad sobre los cambios en la variable global en la aplicación?
  • Repetir alarmas cada lunes en Android usig AlarmManager / BroadcastReceiver
  • ¿Hay alguna razón para continuar usando IntentService para manejar mensajes de GCM?
  • BroadcastReceiver no funciona después de BOOT_COMPLETED
  • Cómo repetir la notificación diaria en el tiempo específico en androide a través del servicio de fondo
  • Uso de BroadcastReceiver con funcionalidad de PhoneStateListener
  • Cómo detectar el estado contestado o rechazado en la llamada saliente
  • ¿Cómo detectar cuando un usuario se conecta auriculares en el dispositivo Android? (Opuesto de ACTION_AUDIO_BECOMING_NOISY)
  • ¿Cómo puedo pasar los datos de un BroadcastReceiver a una actividad iniciada?
  • Android: ¿Debo usar BroadcastReceiver vs Messenger vs BindService vs Handler
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.