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/
- Eliminar Apk después de la instalación de la aplicación
- Error de excepción del receptor no registrado?
- Android - Receptor de emisión de estado de red no recibe intención
- Utilizar un receptor de broadcast / broadcast para enviar mensajes de un servicio a una actividad
- ¿Es BroadcastReceiver.onReceive llamado exactamente una vez por sms?
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?
- Incorrecto timestamp en las notificaciones futuras
- Escuchar el acceso a la ubicación desactivar / activar en la configuración
- ¿Cómo pasar datos a BroadcastReceiver?
- TabActivity Actividad infantil con BroadcastReceiver permanece viva en segundo plano
- ¿Hay alguna manera de saber si se recibieron las transmisiones de LocalBroadcastManager?
- Receptor de difusión Dual Sim
- Actividad de Broadcastreceiver y Paused
- Enviando la intención de BroadcastReceiver desde adb
¡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.