2012-05-11 6 views
6

He leído el documentation about Bound Services, donde se demuestra que se puede comunicar fácilmente a través de mensajes de una actividad a una distancia (es decir, no en el mismo contexto) de servicio, pero ¿hay alguna manera de enviar mensajes desde el Servicioa la actividad enlazada? Por ejemplo, mi actividad limita a un servicio en segundo plano en ejecución de la misma aplicación, le envía un mensaje y al recibir este mensaje, el servicio responde con un mensaje a la actividad ... ¿cómo implemento esto? ¿Puede indicarme alguna documentación que explique este tema?¿Cómo puede un servicio remoto enviar mensajes a una actividad vinculada?

Respuesta

4

Se encontró un ejemplo en la documentación de referencia en Remote Messenger Service Sample.

+0

¿Hay alguna situación del mundo real en la que necesitaríamos un enlace de servicio remoto? –

25

NOTA: Esto es solo para servicios y actividades en proceso, no remota como la pregunta.

Usar un servicio para comunicarse con una actividad implica hacer que un oyente pueda pasar al servicio de la actividad.

Necesita realizar un servicio vinculado a una actividad.

El primer paso es hacer un servicio. En el servicio, asegúrese de tener un objeto Binder y el método para devolver un objeto binder. A continuación se muestra un ejemplo que utilicé en mi servicio para recuperar mi carpeta. También observe que esta carpeta tiene un método para configurar un oyente, que se guardará en el servicio como un campo de tipo BoundServiceListener.

/** 
* 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; 
} 

Ahora tiene que crear algún tipo de interfaz que se puede pasar al objeto de aglutinante que su servicio puede utilizar para enviar actualizaciones a. A continuación está mi BoundServiceListener.

public interface BoundServiceListener { 

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

En su actividad es necesario crear un objeto ServiceConnection que se utiliza para la unión a un servicio. ASÍ, agregue algo como esto.

/** 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; 
    } 

Ahora la línea clave para notar aquí es

binder.setListener(new BoundServiceListener() { 

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

    @Override 
    public void finishedDownloading() { 

    } 
}); 

Esta parte es donde en realidad estoy enviando mi interfaz BoundServiceListener a la clase de servicio. La clase de servicio a continuación, utiliza ese objeto a la escucha aquí

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

Ahora se puede poner esto en cualquier lugar que necesita en su clase de servicio, y su actividad recibirá el progreso de la actualización.

También asegúrese de incluir lo siguiente en su actividad para vincular e iniciar el servicio.

Intent intent = new Intent(this, DownloadBgService.class); 
startService(intent); 
bindService(intent, mConnection, Context.BIND_AUTO_CREATE); 

Tenga en cuenta que, aunque se enlace a un servicio, en realidad no se inicia hasta que llame al servicio de inicio. La vinculación al servicio solo conecta el servicio a una actividad.el método StartService() llama a los servicios de

onStartCommand(Intent intent, int flags, int startId) 

también declarar su servicio en su manifiesto

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

también desenlazar el servicio cuando la actividad sale por

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

Espero que esto ayude.

+1

Gran ejemplo, gracias por haber pasado tanto tiempo explicando el concepto. –

+0

@Danuofr esto funciona en proceso. ¿Hay alguna manera de enviar un oyente arbitrario a través de los límites del proceso? – dcow

+2

El único problema con esta respuesta es: Es solo para un servicio local. Pero la pregunta es clara sobre cómo hacer esto con un servicio remoto. Pero gracias de todos modos por escribir esto. Pero tal vez tenga en cuenta que esta no es la respuesta a la pregunta real :) –

Cuestiones relacionadas