В этом руководстве показано, как сообщить о состоянии рабочего запроса, запущенного в фоновой службе, компоненту, отправившему запрос. Это позволяет, например, сообщать о состоянии запроса в пользовательском интерфейсе объекта 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 .