Ich schreibe meine erste Android-Anwendung und versuche, mich mit der Kommunikation zwischen Diensten und Aktivitäten vertraut zu machen. Ich habe einen Dienst, der im Hintergrund ausgeführt wird und einige GPS- und zeitbasierte Protokollierungen durchführt. Ich werde eine Aktivität haben, mit der der Dienst gestartet und gestoppt wird.
Zuerst muss ich herausfinden können, ob der Dienst ausgeführt wird, wenn die Aktivität gestartet wird. Hier gibt es noch einige andere Fragen, daher denke ich, dass ich das herausfinden kann (aber ich kann Ihnen gerne Ratschläge geben).
Mein eigentliches Problem: Wenn die Aktivität ausgeführt und der Dienst gestartet wird, muss der Dienst Nachrichten an die Aktivität senden können. Einfache Zeichenfolgen und Ganzzahlen an dieser Stelle - meistens Statusmeldungen. Die Nachrichten werden nicht regelmäßig gesendet, daher denke ich nicht, dass das Abrufen des Dienstes ein guter Weg ist, wenn es einen anderen Weg gibt. Ich möchte diese Kommunikation nur, wenn die Aktivität vom Benutzer gestartet wurde. Ich möchte die Aktivität nicht über den Dienst starten. Mit anderen Worten, wenn Sie die Aktivität starten und der Dienst ausgeführt wird, werden in der Benutzeroberfläche der Aktivität einige Statusmeldungen angezeigt, wenn etwas Interessantes passiert. Wenn Sie die Aktivität nicht starten, werden diese Nachrichten nicht angezeigt (sie sind nicht so interessant).
Es scheint, als sollte ich feststellen können, ob der Dienst ausgeführt wird, und wenn ja, die Aktivität als Listener hinzufügen. Entfernen Sie dann die Aktivität als Listener, wenn die Aktivität angehalten oder gestoppt wird. Ist das eigentlich möglich? Die einzige Möglichkeit, dies herauszufinden, besteht darin, dass die Aktivität Parcelable implementiert und eine AIDL-Datei erstellt, damit ich sie über die Remote-Schnittstelle des Dienstes weiterleiten kann. Das scheint jedoch übertrieben zu sein, und ich habe keine Ahnung, wie die Aktivität writeToParcel () / readFromParcel () implementieren soll.
Gibt es einen einfacheren oder besseren Weg? Vielen Dank für jede Hilfe.
BEARBEITEN:
Für alle, die sich später dafür interessieren, gibt es im Beispielverzeichnis einen Beispielcode von Google, der dies über AIDL handhabt: /apis/app/RemoteService.java
quelle
busy-wait
die Aktivität? Kannst du bitte erklären ?Activity.onCreate()
?Intents
Daten überParcellable
Nachrichten zwischen ihnen senden möchten ?Der Fragesteller ist wahrscheinlich längst daran vorbeigekommen, aber falls jemand anderes danach sucht ...
Es gibt noch einen anderen Weg, der meiner Meinung nach der einfachste ist.
Fügen Sie
BroadcastReceiver
Ihrer Aktivität ein hinzu. Registrieren Sie es, um eine benutzerdefinierte Absicht zu erhalten,onResume
und heben Sie die Registrierung aufonPause
. Senden Sie diese Absicht dann von Ihrem Dienst aus, wenn Sie Ihre Statusaktualisierungen senden möchten oder was Sie haben.Stellen Sie sicher, dass Sie nicht unglücklich wären, wenn eine andere App auf Sie hören würde
Intent
(könnte jemand etwas Böses tun?), Aber darüber hinaus sollten Sie in Ordnung sein.Codebeispiel wurde angefordert:
In meinem Dienst habe ich Folgendes:
(
RefreshTask.REFRESH_DATA_INTENT
ist nur eine konstante Zeichenfolge.)In meiner Höraktivität definiere ich meine
BroadcastReceiver
:Ich erkläre meinen Empfänger zum Klassenbesten:
Ich überschreibe
onResume
, um dies hinzuzufügen:Und ich überschreibe,
onPause
um hinzuzufügen:Jetzt wartet meine Aktivität darauf, dass mein Dienst sagt: "Hey, aktualisiere dich." Ich könnte Daten in der übergeben,
Intent
anstatt Datenbanktabellen zu aktualisieren und dann zurück zu gehen, um die Änderungen in meiner Aktivität zu finden, aber da ich möchte, dass die Änderungen trotzdem bestehen bleiben, ist es sinnvoll, die Daten über die Datenbank zu übergeben.quelle
Broadcasts
sind fantastisch und wenn Sie nicht möchten, dass Ihre Sendung über Ihren eigenen Prozess hinausgeht, sollten SieLocalBroadcast
Verwenden Sie
LocalBroadcastManager
diese Option , um einen Empfänger zu registrieren, der auf eine Sendung wartet, die vom lokalen Dienst in Ihrer App gesendet wurde. Die Referenz finden Sie hier:http://developer.android.com/reference/android/support/v4/content/LocalBroadcastManager.html
quelle
LocalBroadcastManager
ist jetzt zugunstenLiveData
oder anderer Beobachtermuster-Tools veraltet : developer.android.com/reference/androidx/localbroadcastmanager/…Ich bin überrascht, dass niemand auf die Otto Event Bus Bibliothek Bezug genommen hat
http://square.github.io/otto/
Ich habe dies in meinen Android-Apps verwendet und es funktioniert nahtlos.
quelle
android:process=":my_service"
sie nicht kommunizieren können.Die Verwendung eines Messenger ist eine weitere einfache Möglichkeit, zwischen einem Dienst und einer Aktivität zu kommunizieren.
Erstellen Sie in der Aktivität einen Handler mit einem entsprechenden Messenger. Dadurch werden Nachrichten von Ihrem Dienst verarbeitet.
Der Messenger kann an den Dienst übergeben werden, indem er an eine Nachricht angehängt wird:
Ein vollständiges Beispiel finden Sie in den API-Demos: MessengerService und MessengerServiceActivity . Im vollständigen Beispiel erfahren Sie, wie MyService funktioniert.
quelle
myService.send(message);
solltemessenger.send(message);
stattdessen sein.Die andere Methode, die in den anderen Kommentaren nicht erwähnt wird, besteht darin, mit bindService () eine Bindung an den Dienst aus der Aktivität herzustellen und eine Instanz des Dienstes im ServiceConnection-Rückruf abzurufen. Wie hier beschrieben http://developer.android.com/guide/components/bound-services.html
quelle
Sie können das auch
LiveData
wie ein verwendenEventBus
.Fügen Sie dann einen Beobachter von Ihrem hinzu
Activity
.Sie können mehr von diesem Blog lesen .
quelle
Eine andere Möglichkeit könnte darin bestehen, Beobachter mit einer gefälschten Modellklasse über die Aktivität und den Dienst selbst zu verwenden und eine MVC-Mustervariation zu implementieren. Ich weiß nicht, ob es der beste Weg ist, dies zu erreichen, aber es ist der Weg, der für mich funktioniert hat. Wenn Sie ein Beispiel brauchen, fragen Sie danach und ich werde etwas posten.
quelle
Meine Methode:
Klasse zum Verwalten des Sendens und Empfangens von Nachrichten von / zu Service / Aktivität:
Im Aktivitätsbeispiel:
Im Servicebeispiel:
Senden Sie eine Nachricht von Aktivität / Service:
So funktioniert das:
auf die Aktivität, die Sie starten oder den Dienst binden. Die Service "OnBind" -Methoden geben den Binder an seinen MessageManager zurück. In der Aktivität über die "Service Connection" -Schnittstellenimplementierung "OnServiceConnected" erhalten Sie diesen IBinder und initiieren den MessageManager damit. Nachdem die Aktivität seinen MessageManager initiiert hat, sendet der MessageHandler und Handshake an den Dienst, damit er seinen Absender "MessageHandler" (den "privaten Messenger mMsgSender" in MessageManager) festlegen kann. Dabei weiß der Dienst, wer seine Nachrichten sendet.
Sie können dies auch mithilfe einer Liste / Warteschlange des Messenger "Absenders" im MessageManager implementieren, um mehrere Nachrichten an verschiedene Aktivitäten / Dienste zu senden, oder Sie können eine Liste / Warteschlange des Messenger "Empfängers" im MessageManager verwenden, um mehrere zu empfangen Nachricht von verschiedenen Aktivitäten / Diensten.
In der Instanz "MessageManager" haben Sie eine Liste aller empfangenen Nachrichten.
Da Sie sehen können, dass die Verbindung zwischen "Activity's Messenger" und "Service Messenger" mithilfe dieser "MessageManager" -Instanz automatisch erfolgt, erfolgt dies über die "OnServiceConnected" -Methode und über den "Handshake".
Hoffe das ist hilfreich für dich :) Vielen Dank! Tschüss: D.
quelle
Um die Antwort von @MrSnowflake mit einem Codebeispiel zu verfolgen. Dies ist die jetzt Open Source-
Application
Klasse von XABBER . DieApplication
Klasse zentralisiert und koordiniertListeners
und ManagerInterfaces und mehr. Manager aller Art werden dynamisch geladen.Activity´s
Im Xabber gestartet wird gemeldet, in welcher ArtListener
sie sind. Und wenn einService
Start erfolgt, meldet er sichApplication
wie gestartet in der Klasse. Jetzt eine Nachricht an eine sendenActivity
alles , was Sie Ihr machen zu tun haben ,Activity
ein gewordenlistener
, welche Art Sie benötigen. ImOnStart()
OnPause()
Register / unreg. SieService
können dieApplication
Klasse nur darum bitten, dasslistener
sie mit ihr sprechen muss, und wenn sie dort ist, ist die Aktivität bereit zu empfangen.Wenn Sie durch die
Application
Klasse gehen, werden Sie sehen, dass eine Beute mehr los ist als diese.quelle
Bindung ist eine andere Art zu kommunizieren
Implementieren Sie die Schnittstelle in der Aktivität
Stellen Sie die Implementierung für die Methode bereit
Binden Sie die Aktivität an den Service
Registrieren und Aufheben der Registrierung des Rückrufs, wenn der Dienst an die Aktivität gebunden und nicht mehr gebunden ist.
Rückruf initialisieren
Rufen Sie bei Bedarf die Rückrufmethode auf
quelle
serviceConnection
bist rausonCreate
. Bitte bearbeiten Sie es.Wie von Madhur erwähnt, können Sie einen Bus für die Kommunikation verwenden.
Bei Verwendung eines Busses haben Sie einige Möglichkeiten:
Otto Event Bus Bibliothek (veraltet zugunsten von RxJava)
http://square.github.io/otto/
EventBus des grünen Roboters
http://greenrobot.org/eventbus/
NYBus (RxBus, implementiert mit RxJava. Sehr ähnlich dem EventBus)
https://github.com/MindorksOpenSource/NYBus
quelle
Neben LocalBroadcastManager, Event Bus und Messenger , die in dieser Frage bereits beantwortet wurden, können wir Pending Intent verwenden , um vom Dienst aus zu kommunizieren.
Wie hier in meinem Blogbeitrag erwähnt
quelle