Binden Sie den Dienst an die Aktivität in Android


88

Ich versuche, einen einfachen Mediaplayer zu schreiben, der Streaming-Audio mit RTSP wiedergibt. Ich habe eine GUI-Aktivität und einen Dienst, der die Wiedergabe durchführt. Meine Frage ist, wie man am besten zwischen der Aktivität und dem Dienst kommuniziert (z. B. Aktualisierung der GUI basierend auf dem Spielerstatus).

Ich weiß, dass ich den Dienst mit onBind () an die Aktivität binden kann, aber wenn ich das richtig verstehe, wird der Dienst dadurch gestoppt, wenn die Aktivität beendet wird. Ich möchte die Wiedergabe fortsetzen, auch wenn der Benutzer die Aktivität beendet. Gibt es eine Standard- oder bevorzugte Methode, um mit diesem Problem umzugehen?

Antworten:


152

"Wenn Sie einen Android-Dienst mit startService(..)diesem Dienst starten , wird er weiterhin ausgeführt, bis Sie ihn explizit aufrufen stopService(..). Es gibt zwei Gründe, warum ein Dienst vom System ausgeführt werden kann. Wenn jemand anruft, ruft Context.startService()das System den Dienst ab (erstellt ihn und ruft seine onCreate()Methode auf, wenn erforderlich) und rufen Sie dann seine onStartCommand(Intent, int, int)Methode mit den vom Client angegebenen Argumenten auf. Der Dienst wird zu diesem Zeitpunkt weiter ausgeführt, bis Context.stopService()oder stopSelf()aufgerufen wird. Beachten Sie, dass mehrere Aufrufe Context.startService()nicht verschachtelt werden sollen (obwohl sie zu mehreren entsprechenden Aufrufen führen onStartCommand()), also nein Unabhängig davon, wie oft ein Dienst gestartet wird, wird er einmal gestoppt Context.stopService()oder stopSelf()aufgerufen. Dienste können jedoch ihre Dienste verwendenstopSelf(int) Methode, um sicherzustellen, dass der Dienst nicht gestoppt wird, bis die gestarteten Absichten verarbeitet wurden.

Clients können auch Context.bindService()eine dauerhafte Verbindung zu einem Dienst herstellen. Dadurch wird der Dienst ebenfalls erstellt, wenn er noch nicht ausgeführt wird ( onCreate()währenddessen anruft ), aber nicht anruft onStartCommand(). Der Client erhält das IBinderObjekt, das der Dienst von seiner onBind(Intent)Methode zurückgibt , sodass der Client dann den Dienst zurückrufen kann. Der Dienst wird so lange ausgeführt, wie die Verbindung hergestellt wurde (unabhängig davon, ob der Client eine Referenz auf dem Dienst behält oder nicht IBinder). Normalerweise IBinderbezieht sich die Rückgabe auf eine komplexe Schnittstelle, die in AIDL geschrieben wurde.

Ein Dienst kann sowohl gestartet als auch mit Verbindungen verbunden werden. In einem solchen Fall hält das System den Dienst so lange am Laufen, wie er entweder gestartet wird oder eine oder mehrere Verbindungen mit dem Context.BIND_AUTO_CREATEFlag bestehen. Sobald keine dieser Situationen zutrifft, wird die onDestroy()Methode des Dienstes aufgerufen und der Dienst effektiv beendet. Alle Bereinigungen (Stoppen von Threads, Aufheben der Registrierung von Empfängern) sollten nach der Rückkehr von abgeschlossen sein onDestroy(). "


1
ein wenig Verwirrung: Stimmt es, dass bei einer Zerstörung der Aktivität auch der Dienst zerstört wird? Oder wird dieser Dienst nicht nur zerstört, wenn ich meine eigene AIDL implementiere? Ich frage, weil bei Verwendung von startService (insbesondere bei IntentService) der Dienst beendet wird, wenn seine Arbeit erledigt ist, und nicht, wenn die Aktivität stirbt. Stimmt es also, dass, wenn die Aktivität stirbt, auch der (ausschließlich) gebundene Dienst stirbt?
Katedral Pillon

1
Wenn Sie einen einfachen Server verwenden, indem Sie startService aufrufen, wird der Dienst erst beendet, wenn Sie stopSelf () oder stopService () aufrufen. Und das nächste Mal, wenn Sie bindService verwenden, stirbt yes service, wenn alle verbundenen / bindenden Komponenten zerstört werden.
Asif Mushtaq

1
@UnKnown Wenn der Dienst mit startService () gestartet wird, wird er unabhängig vom Binden oder Aufheben der Bindung weiter ausgeführt und kann nur durch Aufrufen von stopService () oder stopSelf () zerstört werden. Selbst wenn die an den Dienst gebundene Aktivität zerstört wird, wird der Dienst nicht zerstört.
CopsOnRoad

Können Sie mir bitte bei dieser Frage helfen stackoverflow.com/questions/51508046/…
Rajesh K

24

Zunächst zwei Dinge, die wir verstehen müssen

Klient

  • Es stellt eine Anfrage an einen bestimmten Server

    bindService(new 
        Intent("com.android.vending.billing.InAppBillingService.BIND"),
            mServiceConn, Context.BIND_AUTO_CREATE);`

Hier mServiceConnist eine Instanz der ServiceConnectionKlasse (eingebaut). Es handelt sich tatsächlich um eine Schnittstelle, die wir mit zwei Methoden (1. für Netzwerkverbindung und 2. Netzwerk nicht verbunden) implementieren müssen, um den Netzwerkverbindungsstatus zu überwachen.

Server

  • Es verarbeitet die Anforderung des Clients und erstellt eine eigene Replik, die nur für den Client privat ist, der die Anforderung sendet, und diese Replik des Servers wird auf einem anderen Thread ausgeführt.

Wie kann man nun auf der Clientseite auf alle Servermethoden zugreifen?

  • Server-Sende-Antwort mit IBind Object.so IBind-Objekt ist unser Handler, der mit dem Operator (.) auf alle Servicemethoden zugreift.

    MyService myService;
    public ServiceConnection myConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder binder) {
            Log.d("ServiceConnection","connected");
            myService = binder;
        }
        //binder comes from server to communicate with method's of 
    
        public void onServiceDisconnected(ComponentName className) {
            Log.d("ServiceConnection","disconnected");
            myService = null;
        }
    }

Nun, wie man eine Methode aufruft, die im Dienst liegt

myservice.serviceMethod();

Hier myServiceist Objekt und serviceMethodeMethode in Betrieb. Auf diese Weise wird die Kommunikation zwischen Client und Server hergestellt.


10

ich habe versucht anzurufen

startService(oIntent);
bindService(oIntent, mConnection, Context.BIND_AUTO_CREATE);

folglich und ich könnte einen klebrigen Dienst erstellen und daran binden. Detailliertes Tutorial für das Beispiel eines gebundenen Dienstes .


5

Es gibt eine Methode namens unbindService , die eine ServiceConnection übernimmt, die Sie beim Aufrufen von bindService erstellt haben. Auf diese Weise können Sie die Verbindung zum Dienst trennen, während er noch ausgeführt wird.

Dies kann ein Problem darstellen, wenn Sie erneut eine Verbindung herstellen, da Sie wahrscheinlich nicht wissen, ob es ausgeführt wird oder nicht, wenn Sie die Aktivität erneut starten. Daher müssen Sie dies in Ihrem Aktivitätscode berücksichtigen.

Viel Glück!


-1

Dies ist eine voreingenommene Antwort, aber ich habe eine Bibliothek geschrieben, die die Verwendung von Android-Diensten vereinfachen kann, wenn sie lokal im selben Prozess wie die App ausgeführt werden: https://github.com/germnix/acacia

Grundsätzlich definieren Sie eine Schnittstelle, die mit @Service und seiner implementierenden Klasse versehen ist, und die Bibliothek erstellt und bindet den Service, verwaltet die Verbindung und den Hintergrund-Worker-Thread:

@Service(ServiceImpl.class)
public interface MyService {
    void doProcessing(Foo aComplexParam);
}

public class ServiceImpl implements MyService {
    // your implementation
}

MyService service = Acacia.createService(context, MyService.class);
service.doProcessing(foo);

<application
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme">
    ...
    <service android:name="com.gmr.acacia.AcaciaService"/>
    ...
</application>

Sie können eine Instanz des zugehörigen android.app.Service abrufen, um dauerhafte Benachrichtigungen auszublenden / anzuzeigen, Ihren eigenen android.app.Service zu verwenden und das Threading manuell durchzuführen, wenn Sie dies wünschen.


-5

Wenn der Benutzer zurücktritt, wird die onDestroy()Methode aufgerufen. Mit dieser Methode wird jeder Dienst gestoppt, der in der Anwendung verwendet wird. Wenn Sie den Dienst fortsetzen möchten, auch wenn der Benutzer die Anwendung verlässt, löschen Sie ihn einfach onDestroy(). Ich hoffe das hilft.


Sie müssten die Funktion überschreiben und den Standardaufruf für onDestroy () der Oberklasse löschen, wenn Ihre IDE automatisch einen erstellt. aber warum willst du das jemals tun?
Riptyde4
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.