13

我正在重構一些代碼,以便我的應用程序每天在給定時間從一個網站提取數據。從我的研究看來,AlarmManager似乎是最合適的方法。AlarmManager,BroadcastReceiver和服務不工作

我一直在下面的教程:http://mobile.tutsplus.com/tutorials/android/android-fundamentals-downloading-data-with-services/

到目前爲止,AlarmManagerBroadcastReceiver似乎工作,但是Service似乎永遠不會啓動(即onStartCommand似乎不叫)

這裏是代碼的重要片斷我到目前爲止:

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> 

當我TR igger 中的setRecurringAlarm日誌打印如下,同樣,每15分鐘從AlarmReceiver出現日誌。但是,我從來沒有看到日誌從我在日誌中看到MyService :(

例子:

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 

似乎無法找出我錯了做 - 從Android Dev Docs我的理解在AlarmReceiver當我打電話context.startService(dailyUpdater),在依次調用onStartCommandMyService,雖然這似乎是應該不會是這樣!

我在做什麼錯,是造成MyService無法啓動呢?

+0

+1感謝您的代碼,幫助我.. – Nirali 2012-06-15 12:09:42

+0

你也運行到響應警報啓動服務的非顯而易見激活鎖定行爲。有一些細節和建議的答案在http://stackoverflow.com/questions/25852309/does-alarmmanager-require-the-pendingintent-to-be-of-type-broadcastreceiver – ctate 2014-09-15 23:24:50

回答

15

想通了!

爲MyService應延長IntentService,而不是服務

隨着這一變化,這也意味着,而不是覆蓋onStartCommand,應該是壓倒一切的onHandleIntent代替(見IntentService文檔)

所以爲MyService現在看起來是這樣的:

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; 
     } 
    } 
} 

注:從文檔中,默認實現onBind返回null因此不需要重寫它。有關擴展IntentService

的更多信息:http://developer.android.com/guide/topics/fundamentals/services.html#ExtendingIntentService

+1

+1 Thanks your code help me。 – Nirali 2012-06-15 12:10:17

+1

+1 Thanks!「Service」類在Android 4.x設備上工作得很好但我無法理解它爲什麼不能在Android 2.x設備上工作,當改變爲「IntentService」時,它就像一個魅力一樣。 – 2013-05-11 09:35:09

0

你可以得到AlarmManager運行Service直線距離,而不是通過一個BroadcastReceiver去,如果你改變你的意圖是這樣的:

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

這可以解決您的問題!

+0

感謝您的建議 - 我試過這個之前(儘管沒有downloader.addFlags),它不起作用 - 會嘗試使用addFlags,看看它是否有幫助!想知道,爲什麼'BroadcastReceiver'存在,如果你可以直接運行服務? – pyko 2012-01-29 22:39:10

+0

試過這種改變 - 沒有工作:(也試圖改變'上下文'作爲由庫馬爾建議''這個'...也沒有運氣! – pyko 2012-01-30 12:33:17

0

而不是使用

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

使用

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

其他的建議是直接從報警,而不是發送廣播和廣播接收器啓動該服務啓動服務。

+0

你試過烏爾代碼沒有downloader.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); – 2012-01-30 18:43:33

+0

嗨kumar,是的,我相信我沒有'addFlags'也嘗試過,也沒有工作。 – pyko 2012-01-31 00:22:58