2010-04-12 6 views
41

Ich habe zZ einen Service in Android, der ein Beispiel VOIP-Klient ist, also hört er nach SIP-Nachrichten und wenn er einen erhält, startet er einen Tätigkeitsbildschirm mit UI-Bestandteilen.Effizientere Art der UI-Aktualisierung von Service als Intents?

Dann bestimmen die folgenden SIP-Nachrichten, welche Aktivität auf dem Bildschirm angezeigt werden soll. Zum Beispiel, wenn es ein ankommender Anruf ist, wird es Answer oder Reject oder einen ausgehenden Anruf anzeigen, es wird ein Wahlbildschirm angezeigt.

In der Minute verwende ich Intents, um der Aktivität mitzuteilen, welchen Status sie anzeigen soll.

Ein Beispiel ist wie folgt:


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

So ist die Aktivität eines Rundfunkempfänger für diese Absichten registriert haben wird und seinen Zustand wechseln entsprechend der letzten Absicht es empfangen.

Beispielcode wie folgt:


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

Dies funktioniert jedoch scheint es, wie es nicht sehr effizient ist, werden die Intents Broadcast-System breit bekommen und Intents für verschiedene Zustände zu feuern, die scheint Wie es ineffizient werden könnte, desto mehr muss ich hinzufügen und Komplexität hinzufügen.

Also habe ich mich gefragt, ob es eine andere effizientere und sauberere Möglichkeit gibt, dies zu tun?

Gibt es eine Möglichkeit Intents nur in einer Anwendung zu senden?

Wären Rückrufe eine bessere Idee? Wenn ja, warum und auf welche Weise sollten sie umgesetzt werden?

Antwort

52

UPDATE 2015:

Diese Frage/Antwort bekommt immer noch ein wenig Aktivität, aber es ist mehr als 5 Jahre alt und die Dinge haben sich stark verändert. Vor 5 Jahren war die Antwort unten, wie ich es gehandhabt hätte. Später schrieb ich eine sehr leichte Abhängigkeitsinjektionslösung, die ich eine Zeit lang benutzt hatte (was ich in den Kommentaren erwähnte). Heutzutage würde ich diese Frage mit Dolch und RxAndroid beantworten. Dolch, um eine "Mediator" -Klasse sowohl in den Service als auch in alle Aktivitäten, die benachrichtigt werden müssen, zu injizieren, würde der Dienst die Statusaktualisierung an die Mediatorklasse weitergeben und die Mediatorklasse würde eine Observable für die Aktivitäten aufdecken, die die Statusaktualisierung verbrauchen (anstelle des OP-Rundfunkempfängers).

Ursprüngliche Antwort

ich in der Regel Unterklasse Anwendung und lassen Sie meine In-App-Kommunikation über diese Klasse gehen (oder einen Mediator von der Anwendung im Besitz haben tun die Arbeit ... unabhängig, die Anwendung ist der Einstiegspunkt für den Dienst mit zu kommunizieren). Ich habe einen gebundenen Dienst, der auch die Benutzeroberfläche aktualisieren muss (viel einfacher als deins, aber die gleiche Idee) und es teilt der App im Grunde ihren neuen Status mit und die App kann diese Informationen dann auf die eine oder andere Weise an die aktuelle weitergeben aktive Aktivität.Sie können auch einen Zeiger auf die gerade aktive Aktivität verwalten (wenn es mehrere gibt) und Entscheidungen treffen, ob Sie einfach die aktuelle Aktivität aktualisieren oder nicht, die Absicht, eine andere Aktivität zu starten, senden, die Nachricht ignorieren usw. würde ich tun Unterklasse Aktivität und lassen Sie Ihre neue Aktivitätsbasisklasse der Anwendung mitteilen, dass sie derzeit in onResume aktiv ist und in onPause pausiert ist (für Fälle, in denen Ihr Dienst im Hintergrund ausgeführt wird und alle Aktivitäten pausiert sind).

EDIT:

Als Reaktion auf den Kommentar, hier ist mehr Besonderheiten.

Ihre Anwendung besteht zur Zeit hauptsächlich aus aktivitäts- und service-abgeleiteten Klassen. Inhärent erhalten Sie Funktionalität von einer Instanz der android.app.Application-Klasse. Dies wird in Ihrem Manifest (Standard) mit der folgenden Zeile erklärt:

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

Das Applikationselement in Ihrem Manifest verwendet nicht das android: name-Attribut, so dass es nur eine Instanz des Standard android.app erstellt .Application-Klasse zur Darstellung Ihres globalen Anwendungskontexts

In meinen Anwendungen erstelle ich eine Unterklasse der Anwendung (z. B. ApplicationEx), und ich erzähle meiner App über das Manifest, dass dies die Klasse ist, die als MEIN globaler Anwendungskontext instanziiert wird. Zum Beispiel:

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

kann ich jetzt Methoden ApplicationEx hinzufügen für Aktivitäten und Dienstleistungen zu kommunizieren. Es gibt immer eine einzige Instanz Ihres globalen Anwendungskontextes. Dies ist also Ihr Ausgangspunkt, wenn Ihre App global sein muss. Ein zweites Stück davon ist, dass, anstatt meine Dienste und Aktivitäten aus Service und Aktivität abzuleiten, ich eine Unterklasse von jedem mit einer getAppContext-Methode erzeuge, die den Rückgabewert von getApplicationContext (der bereits in diesen beiden Klassen existiert) erzeugt Sie stammen von Context) zu meiner ApplicationEx-Klasse.

So ........

, dass alle gesagt wird, fügen Sie eine CurrentActivity Eigenschaft auf Ihre ApplicationEx Klasse vom Typ Aktivität (oder Activitybase, wenn Sie es eine Unterklasse wie ich). In der onResume-Methode von ActivityBase übergeben Sie sich selbst an ApplicationEx, um CurrentActivity für diese Aktivität festzulegen. Jetzt können Sie Methoden in ApplicationEx bereitstellen, um Informationen direkt an die aktuelle Aktivität zu übergeben, anstatt sich auf die Intent-Mechanismen zu verlassen.

die etwa so klar ist, wie ich es machen kann

+0

Ich habe Ihren Beitrag ein paar Mal gelesen Rich und ich bin mir nicht sicher, was du meinst. Könnten Sie einen Link zu einem Beispiel dafür geben, wie es so gemacht wurde? –

+4

Ich habe oben eine weitere Erklärung gegeben ... lassen Sie mich wissen, wenn Sie mehr haben? S oder wenn es nicht klar ist. – Rich

+0

Danke für das Rich, ausgezeichnete Post! –

2

Sie Broadcast Absichten System nur auf Ihre eigene Anwendung senden und nicht breit mit LocalBroadcastManager:

Helfer für sich registrieren und Sendungen von Intents auf lokale Objekte senden in deinem Prozess. Dies hat eine Reihe von Vorteilen gegenüber globale Sendungen mit sendBroadcast (Intent) zu senden:

Sie wissen, dass die Daten, die Sie senden Ihre App nicht verlassen, so muß nicht über undichte private Daten sorgen.

Es ist nicht möglich, dass andere Anwendungen diese Broadcasts an Ihre App senden. Sie müssen sich also keine Sorgen über Sicherheitslücken machen, die sie ausnutzen können.

Es ist effizienter als das Senden einer globalen Übertragung durch das System.

Allerdings würde ich noch empfehlen, mit dem Service-Ansatz gehen und vor Ort verbindlich und reden über Handler bei Bedarf UI-Komponenten für Effizienz zu aktualisieren.

Verwandte Themen