13

Sto refactoring del codice in modo che la mia app recuperi i dati da un sito Web una volta al giorno in un dato momento. Dalla mia ricerca, sembra che AlarmManager sia l'approccio più appropriato.AlarmManager, BroadcastReceiver e servizio non funzionanti

Il tutorial ho seguito è: http://mobile.tutsplus.com/tutorials/android/android-fundamentals-downloading-data-with-services/

Finora, AlarmManager e il BroadcastReceiver sembra funzionare, tuttavia la Service non sembra iniziare (. Es onStartCommand non sembra di essere chiamato)

Ecco i frammenti importanti del codice che ho finora:

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> 

Quando ho tr igger il setRecurringAlarm nel MyActivity il log viene stampato come previsto, allo stesso modo, ogni 15 minuti viene visualizzato il registro da AlarmReceiver. Tuttavia, non vedo mai il registro da MyService :(

Esempio di quello che vedo nei log:

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 

Non riesco a capire cosa ho fatto di sbagliato - la mia comprensione dal Android Dev Docs è che in AlarmReceiver quando chiamo context.startService(dailyUpdater) che dovrebbe a sua volta chiamata onStartCommand in MyService, anche se questo non sembra essere il caso!

che cosa sto facendo di sbagliato che sta causando MyService di non iniziare affatto?

+0

+1 Grazie il codice aiuto me .. – Nirali

+0

Sei anche in esecuzione in un comportamento Wakelock non ovvio di avvio dei servizi in risposta agli allarmi. Ci sono alcuni dettagli e raccomandazioni nelle risposte su http://stackoverflow.com/questions/25852309/does-alarmmanager-require-the-pendingintent-to-be-of-type-broadcastreceiver – ctate

risposta

15

Capito!

MyService va estendendo IntentService invece di Servizio!

Con questa modifica, ma significa anche che invece di override onStartCommand dovrebbe essere prioritario onHandleIntent invece (vedi Documentazione su IntentService)

Così MyService appare come segue:

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 : Dai documenti, l'implementazione predefinita di onBind restituisce null quindi non è necessario sostituirlo.

ulteriori informazioni sull'estensione IntentService: http://developer.android.com/guide/topics/fundamentals/services.html#ExtendingIntentService

+1

+1 Grazie al tuo codice – Nirali

+1

+1 Grazie! La classe" Servizio "funziona bene su dispositivi Android 4.x ma non ho potuto allenarmi perché non funzionava su dispositivi Android 2.x. Quando si passa a "IntentService" ha funzionato come un incantesimo. –

0

Si potrebbe arrivare AlarmManager per eseguire il servizio subito piuttosto che passare attraverso un BroadcastReceiver, se si cambia il vostro intento in questo modo:

//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); 

Questo potrebbe risolvere il tuo problema!

+0

Grazie per il suggerimento - Ho provato questo prima (sebbene senza downloader.addFlags) e non ha funzionato - proverò con addFlags e vedrò se aiuta! Mi chiedo, perché esiste il "BroadcastReceiver" se puoi semplicemente eseguire direttamente il Servizio? – pyko

+0

Ho provato questo cambiamento - non ha funzionato :(ho anche provato a cambiare 'context' a' this' come suggerito da kumar ... senza fortuna neanche! – pyko

0

Invece di usare

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

uso

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

altro suggerimento è quello di avviare il servizio direttamente da allarme, piuttosto che l'invio di una trasmissione e l'avvio del servizio di ricevitore broadcast.

+0

hai provato il tuo codice ur senza downloader.addFlags (Intent.FLAG_ACTIVITY_NEW_TASK); –

+0

hi kumar, sì, credo di averlo provato senza 'addFlags', non ha funzionato neanche – pyko

Problemi correlati