Ho letto l'documentation about Bound Services, qualora sia dimostrato che si può facilmente comunicare attraverso messaggi da un'attività ad una distanza (cioè non nello stesso contesto) servizio, ma c'è un modo per inviare messaggi dal Servizio all'attività associata? Ad esempio, la mia attività si limita a un servizio in background in esecuzione della stessa applicazione, invia un messaggio ad esso e alla ricezione di questo messaggio il servizio risponde con un messaggio all'attività .. come posso implementarlo? Puoi indicarmi qualche documentazione che spiega questo argomento?In che modo un servizio remoto può inviare messaggi a un'attività associata?
risposta
esempio reperibili nella documentazione di riferimento a Remote Messenger Service Sample.
NOTA: questo è solo per servizi e attività in-process, non remoti come richiesto.
Utilizzando un servizio per comunicare con un'attività consiste nel fare un ascoltatore che è possibile passare al servizio dall'attività.
È necessario creare un servizio associato a un'attività.
Il primo passo è rendere un servizio. Nel servizio assicurati di avere un oggetto Binder e il metodo per restituire un oggetto binder. Di seguito è riportato un esempio che ho utilizzato nel mio servizio per recuperare il mio raccoglitore. Si noti inoltre che questo raccoglitore ha un metodo per impostare un listener, che verrà salvato nel servizio come un campo di 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;
}
Ora è necessario creare una sorta di interfaccia che è possibile passare all'oggetto legante che il servizio può utilizzare per inviare gli aggiornamenti. Di seguito è il mio BoundServiceListener.
public interface BoundServiceListener {
public void sendProgress(double progress);
public void finishedDownloading();
}
Ora nella vostra attività è necessario creare un oggetto ServiceConnection che viene utilizzato per il legame a un servizio. Quindi aggiungi qualcosa di simile.
/** 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;
}
Ora la linea di chiave da notare è
binder.setListener(new BoundServiceListener() {
@Override
public void sendProgress(double progress) {
// Use this method to update our download progress
}
@Override
public void finishedDownloading() {
}
});
Questa parte è dove sono in realtà mando la mia interfaccia BoundServiceListener alla classe di servizio. La classe di servizio utilizza quindi l'oggetto ascoltatore qui
if (mListener!=null)
mListener.finishedDownloading();
if (mListener!=null)
mListener.sendProgress(percent);
Ora si può mettere questo ovunque è necessario nella classe di servizio, e la vostra attività riceverà l'aggiornamento progresso.
anche essere sicuri di includere le seguenti nella vostra attività di legare realtà e avviare il servizio.
Intent intent = new Intent(this, DownloadBgService.class);
startService(intent);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
Tenete a mente che anche se si associa a un servizio, non effettivamente iniziato fino a quando si chiama il servizio di avvio. Il collegamento al servizio collega solo il servizio a un'attività.il metodo StartService() chiama i servizi
onStartCommand(Intent intent, int flags, int startId)
dichiarare anche il vostro servizio nella vostra manifesta
<service android:name=".services.DownloadBgService" />
svincolare Anche il servizio quando l'attività lascia da
@Override
protected void onStop() {
super.onStop();
// Unbind from the service
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
Spero che questo aiuti.
Ottimo esempio, grazie per aver speso così tanto tempo a spiegare il concetto. –
@Danuofr funziona in-process. C'è un modo per inviare un listener arbitrario oltre i limiti del processo? – dcow
L'unico problema con questa risposta è: è solo per un servizio locale. Ma la domanda viene posta chiaramente su come farlo con un servizio remoto. Ma grazie comunque per averlo scritto. Ma forse nota che questa non è la risposta alla vera domanda :) –
Esiste qualche situazione del mondo reale in cui avremmo bisogno di un collegamento di servizio remoto? –