回報工作狀態

本指南說明如何向傳送要求的元件回報背景服務執行的工作要求狀態。舉例來說,您可以在 Activity 物件的 UI 中回報要求的狀態。如要傳送及接收狀態,建議您使用 LocalBroadcastManager,這會將廣播 Intent 物件限制為應用程式中的元件。

透過 JobIntentService 回報狀態

如要將 JobIntentService 中的工作要求狀態傳送至其他元件,請先建立在延伸資料中包含狀態的 Intent。您可以選擇將動作和資料 URI 新增至這個 Intent

接下來,呼叫 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() 回呼方法,LocalBroadcastManager 會在收到 Intent 時叫用該方法。LocalBroadcastManager 會將傳入的 Intent 傳遞至 BroadcastReceiver.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);
        ...

單一 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請勿啟動 Activity 以回應傳入的廣播 Intent