В этом руководстве показано, как сообщить о состоянии рабочего запроса, запущенного в фоновой службе, компоненту, отправившему запрос. Это позволяет, например, сообщать о состоянии запроса в пользовательском интерфейсе объекта Activity
. Рекомендуемый способ отправки и получения статуса — использовать LocalBroadcastManager
, который ограничивает широковещательные объекты Intent
компонентами вашего собственного приложения.
Статус отчета из JobIntentService
Чтобы отправить статус рабочего запроса в JobIntentService
другим компонентам, сначала создайте Intent
, содержащий статус в своих расширенных данных. В качестве опции вы можете добавить к этому Intent
URI действия и данных.
Затем отправьте Intent
, вызвав LocalBroadcastManager.sendBroadcast()
. При этом Intent
будет отправлено любому компоненту вашего приложения, который зарегистрировался для его получения. Чтобы получить экземпляр LocalBroadcastManager
, вызовите getInstance()
.
Например:
Котлин
... // 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) ... }
Ява
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); ... }
Следующим шагом является обработка входящих широковещательных объектов Intent
в компоненте, который отправил исходный рабочий запрос.
Получать широковещательные сообщения о состоянии от JobIntentService.
Чтобы получать широковещательные объекты Intent
, используйте подкласс BroadcastReceiver
. В подклассе реализуйте метод обратного вызова BroadcastReceiver.onReceive()
, который LocalBroadcastManager
вызывает при получении Intent
. LocalBroadcastManager
передает входящее Intent
в BroadcastReceiver.onReceive()
.
Например:
Котлин
// Broadcast receiver for receiving status updates from the IntentService. private class DownloadStateReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { ... /* * Handle Intents here. */ ... } }
Ява
// 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. */ ... } }
Определив BroadcastReceiver
, вы можете определить для него фильтры, соответствующие определенным действиям, категориям и данным. Для этого создайте IntentFilter
. В этом первом фрагменте показано, как определить фильтр:
Котлин
// 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") } ...
Ява
// 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"); ...
Чтобы зарегистрировать BroadcastReceiver
и IntentFilter
в системе, получите экземпляр LocalBroadcastManager
и вызовите его метод registerReceiver()
. В следующем фрагменте показано, как зарегистрировать BroadcastReceiver
и его IntentFilter
:
Котлин
// Instantiates a new DownloadStateReceiver val downloadStateReceiver = DownloadStateReceiver() // Registers the DownloadStateReceiver and its intent filters LocalBroadcastManager.getInstance(this) .registerReceiver(downloadStateReceiver, statusIntentFilter) ...
Ява
// Instantiates a new DownloadStateReceiver DownloadStateReceiver downloadStateReceiver = new DownloadStateReceiver(); // Registers the DownloadStateReceiver and its intent filters LocalBroadcastManager.getInstance(this).registerReceiver( downloadStateReceiver, statusIntentFilter); ...
Один BroadcastReceiver
может обрабатывать более одного типа широковещательного объекта Intent
, каждый со своим собственным действием. Эта функция позволяет запускать разный код для каждого действия без необходимости определять отдельный BroadcastReceiver
для каждого действия. Чтобы определить другой IntentFilter
для того же BroadcastReceiver
, создайте IntentFilter
и повторите вызов registerReceiver()
. Например:
Котлин
/* * 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)
Ява
/* * 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);
Отправка широковещательного Intent
не запускает и не возобновляет Activity
. BroadcastReceiver
для Activity
получает и обрабатывает объекты Intent
даже когда ваше приложение находится в фоновом режиме, но не переводит ваше приложение на передний план. Если вы хотите уведомить пользователя о событии, которое произошло в фоновом режиме, пока ваше приложение не было видно, используйте Notification
. Никогда не запускайте Activity
в ответ на входящий широковещательный Intent
.