2013-04-22 34 views
2

我的應用程序需要偵聽廣播事件(HEADSET事件)並採取相應措施。我發現HEADSET事件不能通過最小接收器使用,因爲此事件啓用了標誌FLAG_RECEIVER_REGISTERED_ONLY。因此,您只能在程序中動態註冊此事件。由於我的應用程序在事件期間不會處於活動狀態,因此我需要一個服務來處理此事件,我在onCreate中註冊並在onDestroy中取消註冊。到現在爲止還挺好。我實現了服務並開始測試它,我發現系統在資源緊縮的情況下可以終止服務,系統將自動重新啓動服務。然而,令人驚訝的是,殺死和重啓之間的延遲是完全隨機的,可能會很大。有時候,這是在幾秒鐘內,而其他時間是在幾個小時內。所以,當廣播事件發生時,您無法確定您的服務正在運行!BroadcastReceiver in a Service:設計問題

我瀏覽過的stackoverflow上有各種建議。有一個虛擬線程什麼也不做,這會增加服務的「重要性」,使用startForeground服務 - 這會導致通知。所有這些看起來都像解決方法,而不是萬無一失。

有沒有辦法以一種萬無一失的方式解決這個問題?什麼可以成爲處理「REGISTERED_ONLY」廣播事件的備用解決方案?

謝謝。

+0

我已經與startForeground運氣相當好。也就是說,這可能不是萬無一失的,但對我來說這是非常萬無一失的。 – Catherine 2013-04-22 03:33:05

+0

您註冊了哪些耳機事件? – 2013-04-22 03:36:55

+0

@凱瑟琳:感謝您的評論。 「startForeground」不會爲最終用戶造成令人困惑的通知嗎? – Sudhee 2013-04-22 04:39:40

回答

6

我做了很多試錯法編程,並找到了解決方案。所以,我回答我自己的問題。

在服務重新啓動Android的行爲: 衆所周知的是一個Android服務可以強制停下來的情況下,有資源危機的系統。 Android會自動重啓這項服務。這是不可避免的,您需要對您的服務進行編程以優雅地處理這種情況。請注意,服務強制停止和重新啓動之間有延遲。這種延遲看似是隨機的,可以在幾個小時內完成。我發現這種延遲存在模式。在第一次強制停止之後,Android以5000ms(5秒)重新啓動應用程序。此外,如果服務在第一次重新啓動後的60秒內再次強制停止(第二次),則Android會將下次重新啓動的延遲更新4次(即,5000 x 4 = 20000ms = 20秒)。 20秒後,Android再次重新啓動服務(第三次)。如果服務在60秒內再次強制停止(第三次),第三次重新啓動後,延遲更新爲4次20000毫秒= 80000毫秒= 80秒,依此類推。因此,如果您的服務在自動重新啓動的60秒內被強行殺死,則延遲呈指數級增長(5s,20s,80s,320s,1280s,..........)。如果您的服務在60秒內沒有再次被強制終止,則延遲計時器將重置爲5秒,以便下一次強制停止並重新啓動。 在我看來,擁有超過20秒的重啓計時器是不合理的,如果你甚至不確定你的服務是否正在運行,程序員應該如何編寫可靠的應用程序和服務?

已知的解決方案&解決方法: 有幾個答案已經在堆棧溢出其中把重點放在如何確保你的服務沒有在第一時間殺死。其中最重要的是讓服務在前臺開始。看到這裏看看如何做到這一點。這會在服務啓動時產生通知。在foreGround中啓動服務可確保它幾乎不會被殺死。還有其他建議的方法,例如從服務中產生連續運行的線程(此線程無需執行任何操作)。這應該會提高線程的「重要性」,並且服務不會經常死亡。不過,我懷疑這可能會耗盡電池。

新的解決方案,我發現: 我發現這個規避問題,這並不需要一個前臺的服務或電池耗盡線程的另一種方法。當意圖爲空時(例如,假設服務創建時返回START_STICKY),您需要在onStartCommand中的服務中調用startService()。當您調用startService()時,重啓計時器延遲將始終重置爲5秒。示例如下

public class MyService extends Service { 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) 
    { 
     if(null == intent) 
     { 
      Log.d("MyServiceTag", "This is a System Restart"); 
      /* restart the service with startService(). 
      * This will ensure that the delay between system force-stop and restart 
      * is always 5 seconds 
      */ 
      startService(new Intent(getBaseContext(), MyService.class)); 
     } 

     return START_STICKY; 
    } 


    @Override 
    public void onDestroy() 
    { 
     Log.d("MyServiceTag", "In onDestroy"); 
    } 


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

} 

如果你有,你是通過一個意圖參數傳遞給你的服務更復雜的情形,你正在使用START_REDELIVER_INTENT,您可能需要使用「標誌」,發現重新啓動並重新創建調用startService()之前,您的意圖中的附加參數。

爲我工作。希望這可以幫助。