تقديم الدعم للعاملين الدائمين

يوفّر WorkManager دعمًا مضمَّنًا للعاملين على المدى البعيد. في مثل هذه الحالات، يمكن أن يقدم WorkManager إشارة لنظام التشغيل بضرورة استمرار العملية إن أمكن أثناء تنفيذ هذا العمل. يمكن لهؤلاء العاملين العمل لفترة أطول من 10 دقيقة. من أمثلة حالات الاستخدام لهذه الميزة الجديدة التحميلات المجمّعة أو عمليات التنزيل (التي لا يمكن تجزئتها) أو معالجة نموذج تعلُّم الآلة محليًا أو مهمة المهم لمستخدم التطبيق.

الخيارات المتقدمة، يدير WorkManager خدمة تعمل في المقدّمة ويديرها نيابةً عنك لتنفيذ WorkRequest، مع عرض رمز قابل للضبط أيضًا .

أصبحت ListenableWorker متوافقة الآن مع setForegroundAsync() API يتوافق CoroutineWorker مع واجهة برمجة تطبيقات setForeground() للتعليق. هذه تتيح واجهات برمجة التطبيقات للمطوّرين تحديد أنّ WorkRequest مهمة هذه (بدءًا من منظور المستخدم) أو على المدى الطويل.

بدءًا من 2.3.0-alpha03، يسمح لك WorkManager أيضًا بإنشاء PendingIntent، التي يمكن استخدامها لإلغاء الموظفين بدون الحاجة إلى تسجيل مكوّن Android جديد باستخدام createCancelPendingIntent() واجهة برمجة التطبيقات. ويكون هذا المنهج مفيدًا بشكل خاص عند استخدامه مع واجهات برمجة التطبيقات setForegroundAsync() أو setForeground()، والتي يمكن استخدامها لإضافة إشعار لإلغاء Worker.

خلق عمالة طويلة الأمد وإدارتها

ستستخدم أسلوبًا مختلفًا قليلاً اعتمادًا على ما إذا كنت تقوم بالترميز في Kotlin أو Java.

Kotlin

على مطوّري Kotlin استخدام CoroutineWorker. بدلاً من استخدام setForegroundAsync()، يمكنك استخدام الإصدار المعلَّق من هذه الطريقة، setForeground()

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 (المستوى 34 لواجهة برمجة التطبيقات) أو إصدارًا أحدث، عليك تحديد لنوع الخدمة التي تعمل في المقدّمة لجميع العاملين منذ فترة طويلة. إذا كان تطبيقك يستهدف الإصدار 10 من نظام التشغيل Android (المستوى 29 من واجهة برمجة التطبيقات) أو إصدارًا أحدث ويحتوي على عاملًا منذ فترة طويلة يتطلب الوصول إلى موقع جغرافي، إلى أن يشير إلى أنّ العامل تستخدم نوع الخدمة التي تعمل في المقدّمة من location.

إذا كان تطبيقك يستهدف الإصدار 11 من نظام التشغيل Android (المستوى 30 من واجهة برمجة التطبيقات) أو الإصدارات الأحدث ويحتوي على عامل عريقة يتطلب الوصول إلى الكاميرا أو الميكروفون، توضيح camera أو microphone في المقدّمة أنواع الخدمات على التوالي.

لإضافة هذه الأنواع من الخدمات التي تعمل في المقدّمة، عليك إكمال الخطوات الموضّحة في الأقسام التالية.

تعريف أنواع الخدمات التي تعمل في المقدّمة في بيان التطبيق

يُرجى تعريف نوع الخدمة التي تعمل في المقدّمة في بيان التطبيق في بيان التطبيق. في جلسة المعمل، على سبيل المثال، يطلب العامل الوصول إلى الموقع والميكروفون:

ملف AndroidManifest.xml

<service
   android:name="androidx.work.impl.foreground.SystemForegroundService"
   android:foregroundServiceType="location|microphone"
   tools:node="merge" />

تحديد أنواع الخدمات التي تعمل في المقدّمة في وقت التشغيل

عند استدعاء setForeground() أو setForegroundAsync()، تأكد من تحديد نوع الخدمة التي تعمل في المقدّمة:

MyLocationAndMicrophoneWorker

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