2010-06-25 101 views
13

背景資料:AlarmManager和BroadcastReceiver而不是服務 - 是不是很糟糕? (超時)

我需要從網絡,大約每隔一小時左右,即使我的應用程序被關閉更新一些數據。數據更新本身大約需要40秒到1分鐘。然後將它作爲Serializable保存到文件中。當我的應用程序啓動時讀取此文件。

這個是我要做的時刻(不使用服務)

使用AlarmManager和廣播接收器像這樣的方法:

private void set_REFRESH_DATA_Alarm(){ 
    mContext = Main.this; 
    alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE); 
    broadcast_intent = new Intent(mContext, 
      RepeatingAlarmReceiver_REFRESH_DATA.class); 
    pendingIntent = PendingIntent.getBroadcast(mContext, 0, broadcast_intent, 0); 
    // do a REFRESH every hour, starting for the first time in 30 minutes from now ... 
    Calendar now = Calendar.getInstance(); 
    long triggerAtTime = now.getTimeInMillis()+ (1 * 30 * 60 * 1000); // starts in 30 minutes 
    long repeat_alarm_every = (1 * 60 * 60 * 1000); // repeat every 60 minutes 
    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, triggerAtTime, 
      repeat_alarm_every, pendingIntent); 
} 

RepeatingAlarmReceiver_REFRESH_DATA.class需要更新的護理來自網絡的數據:

public class RepeatingAlarmReceiver_REFRESH_DATA extends BroadcastReceiver { 

    public static Context mContext; 
    ConnectivityManager mConnectivity; 

    @Override 
    public void onReceive(Context context, Intent intent) { 
     mContext = context; 
     // if Network connection is OK (Wifi or Mobile) then Load data ... 
     mConnectivity = (ConnectivityManager) context 
       .getSystemService(Context.CONNECTIVITY_SERVICE); 
     Log.i("Hub", 
       "mConnectivity.getNetworkInfo(0)=" 
         + mConnectivity.getNetworkInfo(0)); 
     Log.i("Hub", 
       "mConnectivity.getNetworkInfo(1)=" 
         + mConnectivity.getNetworkInfo(1)); 
     if ((mConnectivity.getNetworkInfo(0).getState() == NetworkInfo.State.CONNECTED) 
       || (mConnectivity.getNetworkInfo(1).getState() == NetworkInfo.State.CONNECTED)) { 
      Log.i("Hub", "Connectivity OK ..."); 
      Refresh_HIST_DATA(); 
     } else { 
      // else Show Dialog "No network connection" ... 
      Log.i("Hub", 
        "No network connection for the moment... will try again later!"); 
     } 
    } 

    // ========================================================================= 
    private void Refresh_HIST_DATA() { 
     Log.i("Hub", "Refresh_HIST_DATA()... Starting ..."); 
     // etc... 
    } 
} 

在清單中,我有:

<receiver android:name="com.cousinHub.myapp.RepeatingAlarmReceiver_REFRESH_DATA" android:process=":remote" /> 

問題:

報警大幹快上的時間和更新開始發射,但隨後約10秒不動爲止(超時)後06-25 11:55:05.278: WARN/ActivityManager(76):超時 廣播BroadcastRecord {44bb4348 null} - [email protected]

11月6日至25日:55:05.278: WARN/ActivityManager(76):接收器 超時期間:ResolveInfo {44bb42c0 com.cousinHub.myapp.RepeatingAlarmReceiver_REFRESH_DATA p值= 0°= 0 M =爲0x0}

06-25 11:55:05.278:INFO/Process(76): 發送信號。 PID:819 SIG:9

11月6日至25日:55:05.298: INFO/ActivityManager(76):進程 com.cousinHub.myapp:遠程(PID 819) 已經死亡。

PS:奇怪的是,這個 「超時」 並不在我的HTC Hero(仍然在Android 1.5 - API等級4)約10秒後發生,但也對我的Nexus One(2.1 UPDATE1)

問題:

  1. 爲什麼超時?任何簡單的方法來避免這一點?
  2. 我在清單中正確設置了我的BroadcastReceiver嗎?我是否需要添加一些內容(以避免此超時)?
  3. 我是否應該絕對爲這種「從網絡刷新」功能提供服務? (考慮這篇文章:http://www.androidguys.com/2009/09/09/diamonds-are-forever-services-are-not/) 如果是(我應該切換到服務):任何好的代碼片段/教程這個...

作爲總之,感謝您的幫助。

H.

回答

18

爲什麼超時?

您正在主應用程序線程上運行。您不能在主應用程序線程上運行超過幾秒鐘。另外,在做這件事情時,你會損害設備的性能(因爲你是running with foreground priority),例如在遊戲或視頻中造成幀率下降。

任何簡單的方法來避免這種情況?

不要在主應用程序線程上做大量的工作(> 100ms)。請您的BroadcastReceiver代表IntentService,或許是WakefulIntentService

我在清單中正確設置了我的BroadcastReceiver 嗎?

請請請請請擺脫android:process=:remote。您不需要它,它不會幫助您,並且會進一步降低設備的性能。

我應該絕對去服務 對於這種「從網頁刷新」 功能? (考慮到這 文章: http://www.androidguys.com/2009/09/09/diamonds-are-forever-services-are-not/) 如果是(我應該切換到服務): 碼/教程 此的任何一個好的片斷...

恕我直言,是的。然後,我又寫了那篇博文。有關示例,請參閱WakefulIntentService項目。

+0

和WakefulIntentService將能夠「活」超過30秒並更新我的所有數據?它是否可以訪問我的應用程序將讀取的文件? – Hubert 2010-06-25 12:20:08

+0

「,WakefulIntentService將能夠」活「超過30秒並更新我的所有數據?」 ['IntentService'](http://developer.android.com/reference/android/app/IntentService.html)只要在'WakefulIntentService'中的'onHandleIntent()'(或'doWakefulWork()')正在開展工作。 「它會訪問我的應用程序將讀取的文件嗎?」就像你今天的'BroadcastReceiver'一樣,大概是這樣。請注意,我不是你,因此沒有寫你的代碼,所以我不知道這個「我的應用程序將讀取的文件」是什麼。 – CommonsWare 2010-06-25 12:28:34

+0

最後一個問題,如果我可以:如何在AppService.doWakefulWork內最好地訪問應用上下文(mContext =>也許「Context mContext =(Context)getApplicationContext();」)?目標是通過「pref = PreferenceManager.getDefaultSharedPreferences(mContext)」訪問我的應用程序首選項;「和我的文件「FileOutputStream fOut = mContext.openFileOutput(Globals.mFileName,Context.MODE_WORLD_READABLE);」 – Hubert 2010-06-26 06:02:35

1

有關信息,我試圖用一個新的線程,它工作時,在WiFi(約需時1'30" ,當手機處於睡眠狀態更新數據,它不會‘殺死’!

//let's try with a new separate thread ? 
     new Thread(new Runnable() { 
      public void run() { 
       Refresh_HIST_DATA(); 
      } 
      }).start(); 

但手機(GPRS)不是時候,因爲它得到後約10秒殺死!

這是一時半一的解決方案,我將盡力CommonsWare的更清潔/更可持續的辦法解決方案...讓我們來看看新的線程解決方案是否可以正常工作或者只是運氣(I'已經測試只在幾個小時)...

如果其他人有另一個建議,請張貼它。

+0

新的線程解決方案不總是工作,所以避免!那麼我們來看看CommonsWare的解決方案。 – Hubert 2010-06-26 03:02:37

0

而不是線程。您可以從廣播接收器onRecive()方法啓動AsyncTask。這不會阻塞UI線程。我自己也在我的項目中做過同樣的事情,即它必須每隔1小時發佈一次數據。

public void onReceive(Context context, Intent intent) { 
     // start your Asynctask from here. which will post data in doInBackground() method 
} 
相關問題