作業ステータスを報告する

このガイドでは、バックグラウンド サービスで実行された作業リクエストのステータスを、そのリクエストを送信したコンポーネントに報告する方法について説明します。これにより、たとえば Activity オブジェクトの UI 内で、リクエストのステータスを報告できるようになります。ステータスの送受信には、LocalBroadcastManager を使用することをおすすめします。これは、ブロードキャスト Intent オブジェクトの対象をアプリ内のコンポーネントに制限します。

JobIntentService からステータスを報告する

JobIntentService 内の作業リクエストのステータスを他のコンポーネントに送信するには、まず、拡張データ内にステータスを格納する Intent を作成します。必要に応じて、この Intent にアクションやデータ URI を追加します。

次に、LocalBroadcastManager.sendBroadcast() を呼び出して Intent を送信します。Intent は、それを受信するように登録されているアプリ内のコンポーネントに送信されます。LocalBroadcastManager のインスタンスを取得するには、getInstance() を呼び出します。

たとえば、次のようになります。

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);
    ...
    }
    

次に、元の作業リクエストを送信したコンポーネント内の受信ブロードキャスト Intent オブジェクトを処理します。

JobIntentService からステータス ブロードキャストを受信する

ブロードキャスト Intent オブジェクトを受信するには、BroadcastReceiver のサブクラスを使用します。このサブクラス内に、BroadcastReceiver.onReceive() コールバック メソッドを実装します。これは、LocalBroadcastManagerIntent を受信したときに呼び出すメソッドです。LocalBroadcastManager は、受信 IntentBroadcastReceiver.onReceive() に渡します。

たとえば、次のようになります。

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.
             */
    ...
        }
    }
    

BroadcastReceiver を定義したら、それに対し、特定のアクションや、カテゴリ、データとの照合を行うフィルタを定義できます。そのためには、IntentFilter を作成します。フィルタを定義する方法を次のスニペットに示します。

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");
            ...
    

BroadcastReceiverIntentFilter をシステムに登録するには、LocalBroadcastManager のインスタンスを取得して、その registerReceiver() メソッドを呼び出します。BroadcastReceiver とその 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);
            ...
    

1 つの BroadcastReceiver で複数のタイプのブロードキャスト Intent オブジェクトを処理できます。このオブジェクトは、それぞれ独自のアクションを持ちます。この機能により、アクションごとに異なるコードを実行できます。その際、アクションごとに個別の BroadcastReceiver を定義する必要はありません。同じ BroadcastReceiver に対して別の IntentFilter を定義するには、IntentFilter を作成して、registerReceiver() の呼び出しを繰り返します。たとえば、次のようになります。

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);
    

ブロードキャスト Intent 送信しても、Activity の起動や再開は行われません。ActivityBroadcastReceiver は、アプリがバックグラウンドにある場合でも、Intent オブジェクトを受信して処理します。アプリをフォアグラウンドに移すことはありません。アプリが表示されていないときにバックグラウンドで発生したイベントをユーザーに通知するには、Notification を使用します。受信ブロードキャスト Intent へのレスポンスとして Activity を起動しないでください。