2010-04-12 43 views
41

我目前在Android中有一個Service,它是一個示例VOIP客戶端,因此它偵聽出SIP消息,如果它接收到它,它將啓動一個帶UI組件的Activity屏幕。從服務更新UI更有效的方式比意圖?

然後下列SIP消息確定活動在屏幕上顯示的內容。 例如,如果它的來電將顯示應答或拒絕或撥出電話,它將顯示一個撥號屏幕。

當時我使用Intents讓活動知道它應該顯示什麼狀態。

一個例子是如下:


 Intent i = new Intent(); 
     i.setAction(SIPEngine.SIP_TRYING_INTENT); 
     i.putExtra("com.net.INCOMING", true); 
     sendBroadcast(i); 

     Intent x = new Intent(); 
     x.setAction(CallManager.SIP_INCOMING_CALL_INTENT); 
     sendBroadcast(x); 
     Log.d("INTENT SENT", "INTENT SENT INCOMING CALL AFTER PROCESSINVITE"); 

所以活動將對這些意圖註冊的廣播reciever,並且將根據它接收的最後意圖切換其狀態。

示例代碼如下:


 SipCallListener = new BroadcastReceiver(){ 

      @Override 
      public void onReceive(Context context, Intent intent) { 
        String action = intent.getAction(); 

        if(SIPEngine.SIP_RINGING_INTENT.equals(action)){ 
         Log.d("cda ", "Got RINGING action SIPENGINE"); 
         ringingSetup(); 
        }   

        if(CallManager.SIP_INCOMING_CALL_INTENT.equals(action)){ 
         Log.d("cda ", "Got PHONE RINGING action"); 
         incomingCallSetup(); 
        } 
      } 
     }; 
     IntentFilter filter = new IntentFilter(CallManager.SIP_INCOMING_CALL_INTENT); 
     filter.addAction(CallManager.SIP_RINGING_CALL_INTENT); 
     registerReceiver(SipCallListener, filter); 

然而,這作品好像不是很有效的,該意圖將獲得廣播系統,寬到必須解僱了不同的狀態似乎意圖喜歡它可能會變得低效,我必須包括更多,以及增加複雜性。

所以我想知道是否有一個不同的更有效和更乾淨的方式來做到這一點?

有沒有辦法讓Intent只在應用程序內部播放?

回調會是一個更好的主意嗎?如果有的話,爲什麼以及如何實施?

回答

52

UPDATE 2015年:

這個問題/答案仍然得到活動的一點點,但它是在5歲或事情已經改變了不少。 5年前,下面的答案是我將如何處理它。後來我寫了一個非常輕量級的依賴注入解決方案,我曾經使用了一段時間(我在評論中提到過)。現在,我會用Dagger和RxAndroid回答這個問題。 Dagger向服務和所有需要通知的活動注入「中介」類,服務會將狀態更新推送到中介類,並且中介類將公開活動的觀察點以消耗狀態更新(代替OP的廣播接收機)。

原來的答覆

我通常的子類的應用,讓通過這個類我的應用程序內通信去(或者通過應用程序做的工作......不管,應用作爲切入點擁有的調停爲服務溝通)。我有一個需要更新UI的綁定服務(比你的更簡單,但同樣的想法),它基本上告訴應用程序它的新狀態,然後應用程序可以以這種或那種方式將此信息傳遞給當前積極活動。您還可以維護一個指向當前活動活動的指針(如果有多個活動),並且決定是否簡單地更新當前活動,廣播啓動不同活動的意圖,忽略消息等等。我會還子類的活動,並有新的活動基地類告訴它是目前活躍之一的onResume的應用程序,它被暫停在的onPause(因爲你的服務是在後臺運行的情況和活動​​都暫停)。

編輯:

在迴應的意見,這裏的更多的細節。

您的應用程序目前包括活動衍生和服務的派生類大部分的。本質上,你可以從android.app.Application類的實例中獲得功能。這是在你的清單中聲明(默認)使用以下行:

<application android:icon="@drawable/icon" android:label="@string/app_name"> 

在清單中的應用程序元素不使用android:name屬性,所以它只是創建默認android.app的實例.Application類來表示您的全局應用程序上下文。

在我的應用程序,創建應用程序的一個子類(ApplicationEx,例如),我告訴我的應用程序通過清單,這是實例作爲我的全球應用程序上下文的類。例如:

<application 
    android:name="com.mycompany.myapp.app.ApplicationEx" 
    android:icon="@drawable/app_icon" 
    android:label="@string/app_name"> 

我現在可以向ApplicationEx添加用於通信的活動和服務的方法。總是有一個全局應用程序上下文的實例,所以如果您的應用程序需要全局化,那麼這就是您的出發點。

第二件事是,我不是從Service和Activity派生我的服務和活動,而是使用getAppContext方法創建每個類的子類,該方法可以轉換getApplicationContext的返回值(它已經存在於這兩個類中,因爲他們從上下文派生)到我的ApplicationEx類。

所以........

之所以這麼說,你一個CurrentActivity屬性添加到您的ApplicationEx類類型的活動(或ACTIVITYBASE如果你繼承它像我一樣)。在ActivityBase的onResume方法中,您將自己傳遞給ApplicationEx以便將CurrentActivity設置爲該活動。現在,您可以在ApplicationEx上公開方法,將信息直接傳遞給當前活動,而不是依賴於Intent機制。

這是我們所清楚的,因爲我可以把它

+0

我已閱讀您的文章幾次豐富,我不知道你的意思。你能否提供一個關於如何完成它的例子的鏈接? – 2010-04-13 13:25:08

+4

我在上面提供了進一步的解釋...讓我知道你是否有更多?或者如果它不明確。 – Rich 2010-04-13 13:59:04

+0

感謝您豐富,優秀的職位! – 2010-04-14 10:03:07

2

您可以發送廣播意圖只是爲了自己的應用程序,而不是全系統與LocalBroadcastManager

助手來註冊和意向發送的廣播本地對象在你的過程中。這是多年來一直與sendBroadcast(意向)發送全局廣播的許多優點:

你知道你正在廣播數據不會離開你的應用程序,所以不必擔心泄露隱私數據。

這是不可能的其它應用這些廣播發送到您的應用程序,所以你不必擔心有他們可以利用的安全漏洞。

它比通過系統發送全局廣播更有效率。

但是,我仍然建議使用Service方法和本地綁定,並在必要時通過Handler進行通話以更新UI組件以提高效率。