En esta guía, se muestra cómo informar el estado de una solicitud de trabajo ejecutada en un servicio en segundo plano
al componente que envió la solicitud. Esto te permite, por ejemplo, informar el estado de
la solicitud en la IU de un objeto Activity
. La forma recomendada de enviar y
de recepción es usar un LocalBroadcastManager
,
limita los objetos Intent
de transmisión a los componentes de tu propia app.
Cómo informar el estado de un JobIntentService
Para enviar el estado de una solicitud de trabajo de un objeto JobIntentService
a otros componentes, primero crea un Intent
que contenga el estado en sus datos extendidos. Como opción, puedes agregar una acción y un URI de datos a este
Intent
A continuación, llama a Intent
para enviar el elemento.
LocalBroadcastManager.sendBroadcast()
Esto envía el Intent
a cualquier
de tu aplicación que se haya registrado para recibirlo.
Para obtener una instancia de LocalBroadcastManager
, llama a
getInstance()
Por ejemplo:
Kotlin
... // Defines a custom Intent action const val BROADCAST_ACTION = "com.example.android.threadsample.BROADCAST" ... // Defines the key for the status "extra" in an Intent const val EXTENDED_DATA_STATUS = "com.example.android.threadsample.STATUS" ... class RSSPullService : JobIntentService() { ... /* * Creates a new Intent containing a Uri object * BROADCAST_ACTION is a custom Intent action */ val localIntent = Intent(BROADCAST_ACTION).apply { // Puts the status into the Intent putExtra(EXTENDED_DATA_STATUS, status) } // Broadcasts the Intent to receivers in this app. LocalBroadcastManager.getInstance(this).sendBroadcast(localIntent) ... }
Java
public final class Constants { ... // Defines a custom Intent action public static final String BROADCAST_ACTION = "com.example.android.threadsample.BROADCAST"; ... // Defines the key for the status "extra" in an Intent public static final String EXTENDED_DATA_STATUS = "com.example.android.threadsample.STATUS"; ... } public class RSSPullService extends JobIntentService { ... /* * Creates a new Intent containing a Uri object * BROADCAST_ACTION is a custom Intent action */ Intent localIntent = new Intent(Constants.BROADCAST_ACTION) // Puts the status into the Intent .putExtra(Constants.EXTENDED_DATA_STATUS, status); // Broadcasts the Intent to receivers in this app. LocalBroadcastManager.getInstance(this).sendBroadcast(localIntent); ... }
El siguiente paso es controlar los objetos Intent
de la transmisión entrante en
el componente que envió la solicitud de trabajo original.
Cómo recibir transmisiones de estado de un JobIntentService
Para recibir objetos de Intent
de transmisión, usa una subclase de BroadcastReceiver
. En la subclase, implementa el
Devolución de llamada de BroadcastReceiver.onReceive()
que LocalBroadcastManager
invoca cuando recibe
un Intent
. LocalBroadcastManager
pasa el Intent
entrante a BroadcastReceiver.onReceive()
.
Por ejemplo:
Kotlin
// Broadcast receiver for receiving status updates from the IntentService. private class DownloadStateReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { ... /* * Handle Intents here. */ ... } }
Java
// Broadcast receiver for receiving status updates from the IntentService. private class DownloadStateReceiver extends BroadcastReceiver { // Called when the BroadcastReceiver gets an Intent it's registered to receive @Override public void onReceive(Context context, Intent intent) { ... /* * Handle Intents here. */ ... } }
Una vez que definas el BroadcastReceiver
, podrás definir filtros
que coinciden con acciones, categorías y datos específicos. Para ello, crea
un objeto IntentFilter
. En este primer fragmento, se muestra cómo definir el siguiente filtro:
Kotlin
// Class that displays photos class DisplayActivity : FragmentActivity() { ... override fun onCreate(savedInstanceState: Bundle?) { ... super.onCreate(savedInstanceState) ... // The filter's action is BROADCAST_ACTION var statusIntentFilter = IntentFilter(BROADCAST_ACTION).apply { // Adds a data filter for the HTTP scheme addDataScheme("http") } ...
Java
// Class that displays photos public class DisplayActivity extends FragmentActivity { ... public void onCreate(Bundle stateBundle) { ... super.onCreate(stateBundle); ... // The filter's action is BROADCAST_ACTION IntentFilter statusIntentFilter = new IntentFilter( Constants.BROADCAST_ACTION); // Adds a data filter for the HTTP scheme statusIntentFilter.addDataScheme("http"); ...
Para registrar el BroadcastReceiver
y el
IntentFilter
con el sistema, obtén una instancia de
LocalBroadcastManager
y llama a su
registerReceiver()
. En el siguiente fragmento, se muestra cómo registrar el BroadcastReceiver
y su IntentFilter
:
Kotlin
// Instantiates a new DownloadStateReceiver val downloadStateReceiver = DownloadStateReceiver() // Registers the DownloadStateReceiver and its intent filters LocalBroadcastManager.getInstance(this) .registerReceiver(downloadStateReceiver, statusIntentFilter) ...
Java
// Instantiates a new DownloadStateReceiver DownloadStateReceiver downloadStateReceiver = new DownloadStateReceiver(); // Registers the DownloadStateReceiver and its intent filters LocalBroadcastManager.getInstance(this).registerReceiver( downloadStateReceiver, statusIntentFilter); ...
Un solo elemento BroadcastReceiver
puede controlar más de un tipo de transmisión
Un objeto Intent
, cada uno con su propia acción. Esta función te permite
ejecutar un código diferente para cada acción, sin tener que definir un
BroadcastReceiver
para cada acción. Para definir otro
IntentFilter
por el mismo valor
BroadcastReceiver
, crea IntentFilter
y
repetir la llamada a
registerReceiver()
Por ejemplo:
Kotlin
/* * Instantiates a new action filter. * No data filter is needed. */ statusIntentFilter = IntentFilter(ACTION_ZOOM_IMAGE) // Registers the receiver with the new filter LocalBroadcastManager.getInstance(this) .registerReceiver(downloadStateReceiver, statusIntentFilter)
Java
/* * Instantiates a new action filter. * No data filter is needed. */ statusIntentFilter = new IntentFilter(Constants.ACTION_ZOOM_IMAGE); // Registers the receiver with the new filter LocalBroadcastManager.getInstance(this).registerReceiver( downloadStateReceiver, statusIntentFilter);
Enviar un Intent
de transmisión no inicia ni reanuda un objeto Activity
. El BroadcastReceiver
de un Activity
recibe y procesa objetos Intent
incluso cuando tu app está en segundo plano, pero no fuerza a tu app a estar en primer plano. Si
quieres notificar al usuario sobre un evento que ocurrió en segundo plano mientras la app no estaba
visible, usa un Notification
. Nunca inicies un
Activity
en respuesta a una transmisión entrante
Intent