WorkManager รองรับงานที่ทำงานต่อเนื่องอยู่แล้ว ในกรณีเช่นนี้ WorkManager สามารถส่งสัญญาณไปยังระบบปฏิบัติการว่าควรทำให้กระบวนการทำงานต่อไปได้หากเป็นไปได้ขณะที่งานนี้กำลังดำเนินการ เวิร์กเกอร์เหล่านี้ทำงานได้นานกว่า 10 นาที ตัวอย่าง Use Case สำหรับฟีเจอร์ใหม่นี้ ได้แก่ การอัปโหลดหรือดาวน์โหลดจํานวนมาก (ที่แบ่งเป็นกลุ่มไม่ได้) การคํานวณโมเดล ML ในเครื่อง หรืองานที่สําคัญต่อผู้ใช้ของแอป
เบื้องหลัง WorkManager จะจัดการและเรียกใช้บริการที่ทำงานอยู่เบื้องหน้าในนามของคุณเพื่อดำเนินการ WorkRequest
พร้อมกับแสดงการแจ้งเตือนที่กําหนดค่าได้
ตอนนี้ ListenableWorker
รองรับ setForegroundAsync()
API และ CoroutineWorker
รองรับ setForeground()
API ที่ระงับ API เหล่านี้ช่วยให้นักพัฒนาแอประบุได้ว่า WorkRequest
นี้สำคัญ (จากมุมมองผู้ใช้) หรือทำงานอยู่นาน
ตั้งแต่เวอร์ชัน 2.3.0-alpha03
เป็นต้นไป WorkManager ยังให้คุณสร้าง PendingIntent
ได้ด้วย ซึ่งใช้ยกเลิก PendingIntent
โดยไม่ต้องลงทะเบียนคอมโพเนนต์ Android ใหม่โดยใช้ createCancelPendingIntent()
API แนวทางนี้จะมีประโยชน์อย่างยิ่งเมื่อใช้กับ setForegroundAsync()
หรือ setForeground()
API ซึ่งสามารถใช้เพื่อเพิ่มการดำเนินการแจ้งเตือนเพื่อยกเลิก Worker
การสร้างและจัดการเวิร์กเกอร์ที่ทำงานต่อเนื่อง
คุณจะใช้วิธีการที่แตกต่างกันเล็กน้อยโดยขึ้นอยู่กับว่าคุณเขียนโค้ดเป็น Kotlin หรือ Java
Kotlin
นักพัฒนาซอฟต์แวร์ Kotlin ควรใช้ CoroutineWorker
คุณสามารถใช้วิธีดังกล่าวในเวอร์ชันที่ระงับแทน setForeground()
แทนการใช้ setForegroundAsync()
class DownloadWorker(context: Context, parameters: WorkerParameters) :
CoroutineWorker(context, parameters) {
private val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as
NotificationManager
override suspend fun doWork(): Result {
val inputUrl = inputData.getString(KEY_INPUT_URL)
?: return Result.failure()
val outputFile = inputData.getString(KEY_OUTPUT_FILE_NAME)
?: return Result.failure()
// Mark the Worker as important
val progress = "Starting Download"
setForeground(createForegroundInfo(progress))
download(inputUrl, outputFile)
return Result.success()
}
private fun download(inputUrl: String, outputFile: String) {
// Downloads a file and updates bytes read
// Calls setForeground() periodically when it needs to update
// the ongoing Notification
}
// Creates an instance of ForegroundInfo which can be used to update the
// ongoing notification.
private fun createForegroundInfo(progress: String): ForegroundInfo {
val id = applicationContext.getString(R.string.notification_channel_id)
val title = applicationContext.getString(R.string.notification_title)
val cancel = applicationContext.getString(R.string.cancel_download)
// This PendingIntent can be used to cancel the worker
val intent = WorkManager.getInstance(applicationContext)
.createCancelPendingIntent(getId())
// Create a Notification channel if necessary
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createChannel()
}
val notification = NotificationCompat.Builder(applicationContext, id)
.setContentTitle(title)
.setTicker(title)
.setContentText(progress)
.setSmallIcon(R.drawable.ic_work_notification)
.setOngoing(true)
// Add the cancel action to the notification which can
// be used to cancel the worker
.addAction(android.R.drawable.ic_delete, cancel, intent)
.build()
return ForegroundInfo(notificationId, notification)
}
@RequiresApi(Build.VERSION_CODES.O)
private fun createChannel() {
// Create a Notification channel
}
companion object {
const val KEY_INPUT_URL = "KEY_INPUT_URL"
const val KEY_OUTPUT_FILE_NAME = "KEY_OUTPUT_FILE_NAME"
}
}
Java
นักพัฒนาแอปที่ใช้ ListenableWorker
หรือ Worker
สามารถเรียกใช้ setForegroundAsync()
API ซึ่งจะแสดงผลเป็น ListenableFuture<Void>
นอกจากนี้ คุณยังโทรไปที่ setForegroundAsync()
เพื่ออัปเดตNotification
ที่ดำเนินอยู่ได้ด้วย
ต่อไปนี้เป็นตัวอย่างง่ายๆ ของงานที่ทำงานต่อเนื่องเป็นเวลานานซึ่งดาวน์โหลดไฟล์ เวิร์กเกอร์นี้จะติดตามความคืบหน้าเพื่ออัปเดต Notification
ที่ดำเนินการอยู่ ซึ่งแสดงความคืบหน้าในการดาวน์โหลด
public class DownloadWorker extends Worker {
private static final String KEY_INPUT_URL = "KEY_INPUT_URL";
private static final String KEY_OUTPUT_FILE_NAME = "KEY_OUTPUT_FILE_NAME";
private NotificationManager notificationManager;
public DownloadWorker(
@NonNull Context context,
@NonNull WorkerParameters parameters) {
super(context, parameters);
notificationManager = (NotificationManager)
context.getSystemService(NOTIFICATION_SERVICE);
}
@NonNull
@Override
public Result doWork() {
Data inputData = getInputData();
String inputUrl = inputData.getString(KEY_INPUT_URL);
String outputFile = inputData.getString(KEY_OUTPUT_FILE_NAME);
// Mark the Worker as important
String progress = "Starting Download";
setForegroundAsync(createForegroundInfo(progress));
download(inputUrl, outputFile);
return Result.success();
}
private void download(String inputUrl, String outputFile) {
// Downloads a file and updates bytes read
// Calls setForegroundAsync(createForegroundInfo(myProgress))
// periodically when it needs to update the ongoing Notification.
}
@NonNull
private ForegroundInfo createForegroundInfo(@NonNull String progress) {
// Build a notification using bytesRead and contentLength
Context context = getApplicationContext();
String id = context.getString(R.string.notification_channel_id);
String title = context.getString(R.string.notification_title);
String cancel = context.getString(R.string.cancel_download);
// This PendingIntent can be used to cancel the worker
PendingIntent intent = WorkManager.getInstance(context)
.createCancelPendingIntent(getId());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createChannel();
}
Notification notification = new NotificationCompat.Builder(context, id)
.setContentTitle(title)
.setTicker(title)
.setSmallIcon(R.drawable.ic_work_notification)
.setOngoing(true)
// Add the cancel action to the notification which can
// be used to cancel the worker
.addAction(android.R.drawable.ic_delete, cancel, intent)
.build();
return new ForegroundInfo(notificationId, notification);
}
@RequiresApi(Build.VERSION_CODES.O)
private void createChannel() {
// Create a Notification channel
}
}
เพิ่มประเภทบริการที่ทำงานอยู่เบื้องหน้าไปยังเวิร์กเกอร์ที่ทำงานต่อเนื่อง
หากแอปกำหนดเป้าหมายเป็น Android 14 (API ระดับ 34) ขึ้นไป คุณต้องระบุประเภทบริการที่ทำงานอยู่เบื้องหน้าสำหรับเวิร์กเกอร์ที่ทำงานอยู่นานทั้งหมด
หากแอปกำหนดเป้าหมายเป็น Android 10 (API ระดับ 29) ขึ้นไป และมี Worker ที่ทำงานอยู่นานซึ่งจำเป็นต้องเข้าถึงตำแหน่ง ให้ระบุว่า Worker ใช้บริการที่ทำงานอยู่เบื้องหน้าประเภท location
หากแอปกำหนดเป้าหมายเป็น Android 11 (API ระดับ 30) ขึ้นไป และมี Foreground Worker ที่ทำงานอยู่นานซึ่งจำเป็นต้องเข้าถึงกล้องหรือไมโครโฟน ให้ประกาศบริการที่ทำงานอยู่เบื้องหน้าประเภท camera
หรือ microphone
ตามลำดับ
หากต้องการเพิ่มประเภทบริการที่ทำงานอยู่เบื้องหน้าเหล่านี้ ให้ทำตามขั้นตอนที่อธิบายไว้ในส่วนต่อไปนี้
ประกาศประเภทบริการที่ทำงานอยู่เบื้องหน้าในไฟล์ Manifest ของแอป
ประกาศประเภทบริการที่ทำงานอยู่เบื้องหน้าของ WOrker ในไฟล์ Manifest ของแอป ในตัวอย่างต่อไปนี้ เจ้าหน้าที่ต้องเข้าถึงตำแหน่งและไมโครโฟน
<service android:name="androidx.work.impl.foreground.SystemForegroundService" android:foregroundServiceType="location|microphone" tools:node="merge" />
ระบุประเภทบริการที่ทำงานอยู่เบื้องหน้าขณะรันไทม์
เมื่อเรียกใช้ setForeground()
หรือ setForegroundAsync()
โปรดตรวจสอบว่าคุณได้ระบุประเภทบริการที่ทำงานอยู่เบื้องหน้า
Kotlin
private fun createForegroundInfo(progress: String): ForegroundInfo { // ... return ForegroundInfo(NOTIFICATION_ID, notification, FOREGROUND_SERVICE_TYPE_LOCATION or FOREGROUND_SERVICE_TYPE_MICROPHONE) }
Java
@NonNull private ForegroundInfo createForegroundInfo(@NonNull String progress) { // Build a notification... Notification notification = ...; return new ForegroundInfo(NOTIFICATION_ID, notification, FOREGROUND_SERVICE_TYPE_LOCATION | FOREGROUND_SERVICE_TYPE_MICROPHONE); }