Báo cáo trạng thái công việc

Hướng dẫn này cho bạn biết cách báo cáo trạng thái của một yêu cầu công việc đang chạy trong dịch vụ nền cho thành phần đã gửi yêu cầu đó. Ví dụ: việc này cho phép bạn báo cáo trạng thái của yêu cầu trong giao diện người dùng của một đối tượng Activity. Bạn nên gửi và nhận trạng thái bằng LocalBroadcastManager. Phương thức này giới hạn các đối tượng Intent truyền tin ở các thành phần trong ứng dụng của bạn.

Báo cáo trạng thái từ JobIntentService

Để gửi trạng thái của yêu cầu công việc trong JobIntentService đến các thành phần khác, trước tiên, hãy tạo Intent chứa trạng thái trong dữ liệu mở rộng của nó. Bạn cũng có thể thêm một URI hành động và dữ liệu vào Intent này.

Tiếp theo, hãy gửi Intent bằng cách gọi LocalBroadcastManager.sendBroadcast(). Thao tác này sẽ gửi Intent đến bất kỳ thành phần nào trong ứng dụng đã đăng ký nhận thành phần đó. Để nhận một thực thể của LocalBroadcastManager, hãy gọi getInstance().

Ví dụ:

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

Bước tiếp theo là xử lý các đối tượng Intent truyền tin đến trong thành phần gửi yêu cầu công việc ban đầu.

Nhận thông báo trạng thái từ JobIntentService

Để nhận các đối tượng Intent truyền tin, hãy sử dụng một lớp con của BroadcastReceiver. Trong lớp con, hãy triển khai phương thức gọi lại BroadcastReceiver.onReceive()LocalBroadcastManager sẽ gọi khi nhận được Intent. LocalBroadcastManager truyền Intent đến cho BroadcastReceiver.onReceive().

Ví dụ:

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

Sau khi xác định BroadcastReceiver, bạn có thể xác định bộ lọc phù hợp với các hành động, danh mục và dữ liệu cụ thể. Để thực hiện việc này, hãy tạo một IntentFilter. Đoạn mã đầu tiên này cho thấy cách xác định bộ lọc:

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

Để đăng ký BroadcastReceiverIntentFilter với hệ thống, hãy lấy một thực thể của LocalBroadcastManager và gọi phương thức registerReceiver(). Đoạn mã tiếp theo cho biết cách đăng ký BroadcastReceiverIntentFilter của nó:

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

Một BroadcastReceiver có thể xử lý nhiều loại đối tượng Intent truyền tin, mỗi loại có một thao tác riêng. Tính năng này cho phép bạn chạy mã riêng cho từng thao tác mà không cần xác định BroadcastReceiver riêng cho mỗi thao tác. Để xác định một IntentFilter khác cho cùng một BroadcastReceiver, hãy tạo IntentFilter và lặp lại lệnh gọi đến registerReceiver(). Ví dụ:

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

Việc gửi một thông báo Intent sẽ không bắt đầu hoặc tiếp tục Activity. BroadcastReceiver cho Activity nhận và xử lý các đối tượng Intent ngay cả khi ứng dụng đang chạy trong nền, nhưng không buộc ứng dụng chạy ở nền trước. Nếu bạn muốn thông báo cho người dùng về một sự kiện xảy ra ở chế độ nền khi ứng dụng không hiển thị, hãy dùng Notification. Không bao giờ bắt đầu Activity để phản hồi tin nhắn đến Intent.