2012-01-22 43 views
2

我正在嘗試保持活動狀態以響應屏幕開/關更改。該服務將會完美工作一段時間,但最終會被殺死。我現在試圖使用startForeground()來保持這個進程的活躍,但它似乎仍然在死亡。我明白沒有辦法讓流程永遠活着,沒有錯誤,但是我覺得我必須做錯了什麼,因爲添加startForeground()並沒有爲流程添加額外的生命。此外,作爲一個便箋,Logcat抱怨泄漏,因爲未調用unregisterReceiver()(除了手動按下用戶按鈕)..但是,由於我試圖完成的性質,接收器需要直到明確告訴停止。將startForeground()與意圖服務結合使用

有什麼建議嗎?

相關代碼:

public class UpdateService extends IntentService { 

     public UpdateService() { 
     super(null); 

    } 

     @Override 
     protected void onHandleIntent(Intent intent) { 

      final int myID = 1234; 


      Intent notificationintent = new Intent(this, Main.class); 
      notificationintent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); 
      PendingIntent pendIntent = PendingIntent.getActivity(this, 0, notificationintent, 0); 


      Notification notice = new Notification(R.drawable.icon_image, "***********", System.currentTimeMillis()); 


      notice.setLatestEventInfo(this, "*************", "***********", pendIntent); 

      notice.flags |= Notification.FLAG_NO_CLEAR; 
      startForeground(myID, notice); 

      boolean screenOn = intent.getBooleanExtra("screen_state", false); 


// Blah Blah Blah...... 


     } 

     @Override 
     public IBinder onBind(Intent arg0) { 
      // TODO Auto-generated method stub 
      return null; 
     } 

} 
+0

我有類似的問題,在我的情況,我有以保持閃光燈,但它在幾秒鐘內停止,只有可行的選項,我發現是使用意圖服務內的另一個服務,並運行該服務作爲前臺服務,這解決了問題。讓我知道如果你想讓我在此發佈更多詳細信息 – user2548816

回答

0

如果記憶是低,你消耗太多的內存和你坐在後臺太長時間,那麼你將被ActivityManager殺死。

6

IntentService自動關閉onHandleIntent()完成時。發生事情時要做一些簡單的工作。通常情況下,它不應該生活超過幾秒鐘。

我會以爲這是依賴於我寫in your last question in this area


的東西在你的應用程序的其餘部分將被註冊和註銷的BroadcastReceiver的屏幕開/關事件 - 顯然,從您的意見,這是一個活動。如果在發生這些事情時你想要做的事情非常快(大約幾毫秒),那麼只需在onReceive()中完成工作,並完成它。

如果,另一方面,你有超過幾毫秒的價值更多的工作,你需要有一個工作由別的東西,可以做一個後臺線程的工作要做。例如,如果登錄BroadcastReceiver的「其他應用程序中的某些內容」確實是一項活動,則該活動可能會產生一個AsyncTask來完成此項工作。

另一種可能性是使用IntentService。在最後一個問題之前,你選擇在你的工作中走這條路。我不知道爲什麼。無論如何,一個IntentService,就像一個AsyncTask,應該是一個短命的組件 - 你通過startService()發送一個命令,它在onHandleIntent()中完成它的工作,並且它消失了。

與所有考慮到這一點,讓我們來談談你的具體問題。


服務將很好地工作一段時間,但然後最終它會被殺死。

目前還不清楚你在想什麼「封殺」的手段。一旦onHandleIntent()返回,IntentService自動消失,理想情況下應在幾秒鐘內發生。

我現在試圖使用startForeground()來保持進程活着,但它似乎仍然在死亡。

同樣,你不清楚你認爲「垂死」的含義。請記住,僅當屏幕關閉時,僅存在IntentService並不能阻止CPU關閉,startForeground()與此無關。

此外,作爲一個側面說明,logcat的抱怨泄漏,如unregisterReceiver()不叫(除手動從用戶按下按鈕)..

您還需要註銷接收者在用戶退出活動之前。在onPause()中撥打onResume()unregisterReceiver()中的registerReceiver()通常是個好主意。

+9

文檔中沒有任何內容表明「不應該活幾秒鐘」。你在做這件事。服務可以永遠生活,如果他們想。 IntentService與實現普通的Service類沒有區別。 – AndroidDev

+4

@AndroidDev:「服務可以永遠活着,如果他們想要」 - 除非他們不能,因爲用戶和/或操作系統將在需要時擺脫它們。「IntentService與實現普通的Service類沒有什麼不同」 - 大概你在看來,Integer和普通的Object類沒有區別。 – CommonsWare

+4

從文檔:'如果服務被聲明在前臺運行(稍後討論),那麼它幾乎不會被終止「 - http://developer.android.com/guide/components/services.html。同樣的文檔還說:如果你不需要你的服務同時處理多個請求,'(IntentService)是最好的選擇,但是如果你想長時間/無限期地運行,它不會提及IntentService是一個不好的選擇服務。 –

3

(更新)我想有以下幾種可能的情況:

1)documentation爲IntentService規定:

根據需要啓動該服務,處理依次對每個意圖使用 工作者線程,並在工作不全時自行停止。

因此,它可能是onHandleIntent()完成後您的服務已停止正常(尤其是,因爲你提到startForeground()添加沒有額外的生命過程)。

2)您可以嘗試檢查,如果它在某種程度上可以與設備進入睡眠(或者也許你正在按計劃開始爲您服務,awkening裝置 - 在這種情況下,你可能需要獲得WakeLock

3)在非常罕見的情況下,系統仍然可以殺死前臺進程 - 所以,如果你做了很多分配的(真的很多),並在onHandleIntent()一些其他工作(而不是「等等等等等等」你的代碼) - 你可能會遇到它 - 但我認爲情況並非如此。

由於問題的標題是「使用startForeground()與IntentService」 - 想澄清過: 我相信沒有什麼(架構,最佳實踐,Android框架,Java文檔的IntentService)阻止你運行你的意圖服務作爲前景。當然,你需要仔細考慮它的用法以及你是否真的需要前臺服務。有些想法可用here。示例代碼見下面。 (示例代碼可以根據您的需要最終顯示,如果你排隊多個作業/意圖進入IntentService多個通知,所以有可能是更好的解決方案。)


public class ForegroundService extends IntentService { 

    private static final String TAG = "FrgrndSrv"; 

    public ForegroundService() { 
     super(TAG); 
    } 

    @Override 
    protected void onHandleIntent(Intent intent) { 

     Notification.Builder builder = new Notification.Builder(getBaseContext()) 
       .setSmallIcon(R.drawable.ic_foreground_service) 
       .setTicker("Your Ticker") // use something from something from R.string 
       .setContentTitle("Your content title") // use something from something from 
       .setContentText("Your content text") // use something from something from 
       .setProgress(0, 0, true); // display indeterminate progress 

     startForeground(1, builder.build()); 
     try { 
      doIntesiveWork(); 
     } finally { 
      stopForeground(true); 
     } 
    } 

    protected void doIntesiveWork() { 
     // Below should be your logic that takes lots of time 
     try { 
      Thread.sleep(10000); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
} 
+1

計算機編程的一般規則是:從不作出任何其他代表您獲取的資源的假設。你沒有創建'IntentService'使用的後臺線程;因此,你不應該假設你可以安全地使用它多久。我們用'AsyncTask'解決了這個問題,Google改變了'execute()'的規則,將所有任務限制爲一個線程。如果您想要保持一段時間超過一段時間,請創建您自己的線程。用於推薦糟糕的編程實踐的下調。 – CommonsWare

+0

@CommonsWare我明白你的觀點並理解它。這就說得通了。其實,我對你所作的陳述完全不同意:「它通常不會活幾秒鐘。」我並沒有試圖做出假設,只是閱讀java文檔和java文檔並沒有任何假設,比如「它不應該活着超過幾秒鐘,通常情況下」。 – GregoryK

相關問題