He estado pensando en esto recientemente al implementar account authenticators con flujos de autorización de tres patas. Volver a enviar el resultado al servicio para su procesamiento es mejor que procesarlo en la actividad. También proporciona una mejor separación de preocupaciones.
No está claramente documentado, pero Android proporciona una forma sencilla de enviar y recibir resultados en cualquier lugar (incluidos los servicios) con ResultReceiver
.
He encontrado que es mucho más limpio que pasar actividades, ya que eso siempre conlleva el riesgo de filtrar esas actividades. Además, llamar a métodos concretos es menos flexible.
Para utilizar ResultReceiver
en un servicio, tendrá que hacerla una subclase y proporcionar una manera de procesar el resultado recibido, por lo general en una clase interna:
public class SomeService extends Service {
/**
* Code for a successful result, mirrors {@link Activity.RESULT_OK}.
*/
public static final int RESULT_OK = -1;
/**
* Key used in the intent extras for the result receiver.
*/
public static final String KEY_RECEIVER = "KEY_RECEIVER";
/**
* Key used in the result bundle for the message.
*/
public static final String KEY_MESSAGE = "KEY_MESSAGE";
// ...
/**
* Used by an activity to send a result back to our service.
*/
class MessageReceiver extends ResultReceiver {
public MessageReceiver() {
// Pass in a handler or null if you don't care about the thread
// on which your code is executed.
super(null);
}
/**
* Called when there's a result available.
*/
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
// Define and handle your own result codes
if (resultCode != RESULT_OK) {
return;
}
// Let's assume that a successful result includes a message.
String message = resultData.getString(KEY_MESSAGE);
// Now you can do something with it.
}
}
}
Al iniciar una actividad en el servicio, crear un receptor de resultado y el paquete en los extras intención:
/**
* Starts an activity for retrieving a message.
*/
private void startMessageActivity() {
Intent intent = new Intent(this, MessageActivity.class);
// Pack the parcelable receiver into the intent extras so the
// activity can access it.
intent.putExtra(KEY_RECEIVER, new MessageReceiver());
startActivity(intent);
}
y, por último, en la actividad, descomprimir y utilizar el receptor ResultReceiver#send(int, Bundle)
para enviar un resultado de nuevo.
Puede enviar un resultado en cualquier momento, pero aquí he elegido para hacerlo antes de terminar:
public class MessageActivity extends Activity {
// ...
@Override
public void finish() {
// Unpack the receiver.
ResultReceiver receiver =
getIntent().getParcelableExtra(SomeService.KEY_RECEIVER);
Bundle resultData = new Bundle();
resultData.putString(SomeService.KEY_MESSAGE, "Hello world!");
receiver.send(SomeService.RESULT_OK, resultData);
super.finish();
}
}
Se puede lograr con un simple corte, mediante el uso de SharedPreferences, [SO] (http://stackoverflow.com/a/31461941/4859873) –