Сообщить о статусе работы

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