2012-05-11 6 views
6

Ich habe die documentation about Bound Services gelesen, wo gezeigt wird, dass man leicht durch Nachrichten von einer Aktivität zu einem entfernten (dh nicht im gleichen Kontext) Service kommunizieren kann, aber ist es eine Möglichkeit Nachrichten aus dem Dienst senden an die gebunden Aktivität? Zum Beispiel ist meine Aktivität an einen laufenden Hintergrunddienst der gleichen Anwendung gebunden, sendet eine Nachricht an sie und beim Empfang dieser Nachricht antwortet der Dienst mit einer Nachricht an die Aktivität. Wie implementiere ich das? Kannst du mich auf eine Dokumentation verweisen, die dieses Thema erklärt?Wie kann ein Remote-Dienst Nachrichten an eine gebundene Aktivität senden?

Antwort

4

Gefundenes Beispiel in der Referenzdokumentation unter Remote Messenger Service Sample.

+0

Gibt es Situationen in der realen Welt, in denen wir eine Remotedienstbindung benötigen? –

25

HINWEIS: Dies ist nur für In-Process-Dienste und Aktivitäten, nicht remote wie Frage gestellt.

Um einen Dienst mit einer Aktivität zu kommunizieren, müssen Sie einen Listener erstellen, den Sie von der Aktivität an den Dienst übergeben können.

Sie müssen einen Dienst erstellen, der an eine Aktivität gebunden ist.

Der erste Schritt besteht darin, einen Service zu machen. Stellen Sie im Service sicher, dass Sie ein Binder-Objekt und die Methode zum Zurückgeben eines Binderobjekts haben. Im Folgenden finden Sie ein Beispiel, das ich in meinem Dienst verwendet habe, um meinen Ordner abzurufen. Beachten Sie außerdem, dass dieser Binder über eine Methode zum Festlegen eines Listeners verfügt, die im Service als BoundServiceListener-Typenfeld gespeichert wird.

/** 
* Class used for the client Binder. Because we know this service always 
* runs in the same process as its clients, we don't need to deal with IPC. 
*/ 
public class DownloadBgBinder extends Binder { 

    public DownloadBgService getService() { 
     // Return this instance of LocalService so clients can call public methods 
     return DownloadBgService.this; 
    } 

    public void setListener(BoundServiceListener listener) { 
     mListener = listener; 
    } 
} 

@Override 
public IBinder onBind(Intent intent) { 
    return mBinder; 
} 

Jetzt müssen Sie irgendeine Art von Oberfläche erstellen, die Sie an das Bindemittel-Objekt übergeben können, die Ihren Dienst, um Updates senden können. Unten ist mein BoundServiceListener.

public interface BoundServiceListener { 

    public void sendProgress(double progress); 
    public void finishedDownloading(); 
} 

Jetzt müssen Sie in Ihrer Aktivität ein ServiceConnection-Objekt erstellen, das zum Binden an einen Service verwendet wird. Fügen Sie so etwas hinzu.

/** Defines callbacks for service binding, passed to bindService() */ 
private ServiceConnection mConnection = new ServiceConnection() { 

    @Override 
    public void onServiceDisconnected(ComponentName arg0) { 
     mBound = false; 
    } 

    @Override 
    public void onServiceConnected(ComponentName name, IBinder service) { 
     // We've bound to LocalService, cast the IBinder and get LocalService instance 
     DownloadBgBinder binder = (DownloadBgBinder) service; 
     mService = binder.getService(); 
     binder.setListener(new BoundServiceListener() { 

      @Override 
      public void sendProgress(double progress) { 
       // Use this method to update our download progress 
      } 

      @Override 
      public void finishedDownloading() { 

      } 
     }); 

     mBound = true; 
    } 

Nun ist die wichtige Linie hier zu bemerken ist

binder.setListener(new BoundServiceListener() { 

    @Override 
    public void sendProgress(double progress) { 
     // Use this method to update our download progress 
    } 

    @Override 
    public void finishedDownloading() { 

    } 
}); 

Dieser Teil ist, wo ich eigentlich bin meine BoundServiceListener Schnittstelle zum Serviceklasse zu senden. Die Service-Klasse verwendet dann das Listener-Objekt hier

if (mListener!=null) 
     mListener.finishedDownloading(); 
    if (mListener!=null) 
     mListener.sendProgress(percent); 

Jetzt können Sie diese müssen Sie in Ihrer Serviceklasse überall setzen, und Ihre Aktivitäten werden Ihre Fortschritte Update erhalten.

Achten Sie auch darauf, dass Sie in Ihrer Aktivität Folgendes angeben, um den Dienst zu binden und zu starten.

Denken Sie daran, dass, obwohl Sie an einen Dienst binden, es tatsächlich nicht gestartet wird, bis Sie den Dienst starten. Die Bindung an den Dienst verbindet den Dienst nur mit einer Aktivität.der Startservice() -Methode ruft die Dienste

onStartCommand(Intent intent, int flags, int startId) 

auch Ihren Dienst in Ihrem Manifest

<service android:name=".services.DownloadBgService" /> 

Auch unbind den Dienst erklären, wenn die Aktivität von

verläßt
@Override 
protected void onStop() { 
    super.onStop(); 
    // Unbind from the service 
    if (mBound) { 
     unbindService(mConnection); 
     mBound = false; 
    } 
} 

Hoffnung, das hilft.

+1

Tolles Beispiel, vielen Dank, dass Sie so viel Zeit damit verbracht haben, das Konzept zu erklären. –

+0

@Danuofr dies funktioniert in-Prozess. Gibt es eine Möglichkeit, einen beliebigen Listener über Prozessgrenzen hinweg zu senden? – dcow

+2

Nur Problem mit dieser Antwort ist: Es ist nur für einen lokalen Dienst. Aber die Frage wird klar gefragt, wie man das mit einem Remote-Service macht. Aber danke, dass du das aufgeschrieben hast. Aber vielleicht beachten Sie, dass dies nicht die Antwort auf die echte Frage ist :) –