משימות רקע באנדרואיד עם WorkManager: ביצוע מובטח

משימות רקע מופרעות לעיתים קרובות כאשר האפליקציה ממוזערת, מה שגורם לאובדן דוחות ונתוני ניתוח. אנו מיישמים WorkManager במתכונת turnkey, ומבטיחים ביצוע משימות אמין גם בתנאים מאתגרים, עם תמיכה מתמשכת.

פיתוח ותמיכה בכל סוגי היישומים הניידים:

יישומים ניידים למידע ובידור
אפליקציות חדשות, משחקים, מדריכים, קטלוגים מקוונים, אפליקציות מזג אוויר, אפליקציות כושר ובריאות, אפליקציות נסיעות, אפליקציות חינוכיות, רשתות חברתיות ומסנג'רים, חידונים, בלוגים ופודקאסטים, פורומים, אגרגטורים
יישומים ניידים למסחר אלקטרוני
חנויות מקוונות, אפליקציות B2B, מרקטפלייסים, בורסות מקוונות, שירותי קאשבק, בורסות, פלטפורמות דרופשיפינג, תוכניות נאמנות, משלוחי מזון ומוצרים, מערכות תשלום.
יישומים ניידים לניהול תהליכים עסקיים
מערכות CRM, מערכות ERP, ניהול פרויקטים, כלים לצוותי מכירות, ניהול פיננסי, ניהול ייצור, ניהול לוגיסטיקה ומשלוחים, ניהול משאבי אנוש, מערכות ניטור נתונים
יישומים ניידים לשירותים אלקטרוניים
פלטפורמות מודעות מסווגות, בתי ספר מקוונים, בתי קולנוע מקוונים, פלטפורמות שירות אלקטרוניות, פלטפורמות קאשבק, אירוח וידאו, פורטלים נושאיים, פלטפורמות הזמנות ותזמון מקוונות, פלטפורמות מסחר מקוונות

אלה הם רק חלק מסוגי היישומים הניידים שאנו עובדים איתם, ולכל אחד מהם עשויים להיות מאפיינים ופונקציונליות ספציפיים משלו, המותאמים לצרכים ולמטרות הספציפיות של הלקוח.

השירותים שאנו מציעים
מציג 1 מתוך 1כל 1734 השירותים
משימות רקע באנדרואיד עם WorkManager: ביצוע מובטח
בינוני
~2-3 ימים

הכישורים שלנו:

שאלות נפוצות

העבודות האחרונות

  • פיתוח אפליקציית מובייל עבור FEEDME
    פיתוח אפליקציית מובייל עבור FEEDME
    971
  • פיתוח אפליקציית מובייל עבור XOOMER
    פיתוח אפליקציית מובייל עבור XOOMER
    869
  • פיתוח אפליקציית מובייל עבור RHL
    פיתוח אפליקציית מובייל עבור RHL
    1289
  • פיתוח אפליקציית מובייל עבור ZIPPY
    פיתוח אפליקציית מובייל עבור ZIPPY
    1143
  • פיתוח אפליקציית מובייל עבור Affhome
    פיתוח אפליקציית מובייל עבור Affhome
    1076
  • פיתוח אפליקציית מובייל עבור חברת FLAVORS
    פיתוח אפליקציית מובייל עבור חברת FLAVORS
    677

משימות רקע באנדרואיד עם WorkManager: ביצוע מובטח

בפרקטיקה שלנו, סנכרון נתונים ברקע — טעינת דוחות, שליחת אנליטיקה, עדכון מטמון — נקטע לעיתים קרובות כאשר האפליקציה ממוזערת. דוחות לא עוברים, אנליטיקה אובדת. זה חריף במיוחד במכשירי Xiaomi ו-Huawei עם ניהול סוללה אגרסיבי, שבהם JobScheduler אינו מבטיח ביצוע. WorkManager פותר זאת על ידי הבטחת ביצוע גם אם התהליך נהרג או לאחר אתחול. זה לא תחליף ל-Coroutines לפעולות על המסך: WorkManager מיועד למשימות דחויות או תקופתיות הדורשות אמינות. במשך למעלה מ-5 שנות פיתוח אנדרואיד, יישמנו WorkManager ביותר מ-20 פרויקטים, והפחתנו את אובדן הנתונים ב-40% בהשוואה לשימוש ישיר ב-JobScheduler, וחסכנו ללקוחות בממוצע 12,000 דולר בשנה בהכנסות שאבדו מסנכרונים כושלים.

כיצד WorkManager מבטיח ביצוע משימות רקע

WorkManager היא ספריית Android Jetpack הבנויה על גבי JobScheduler, AlarmManager ו-Firebase JobDispatcher. בחירת היישום אוטומטית, ומספקת API אחיד לכל גרסאות האנדרואיד (החל מ-API 14). JobScheduler זמין רק מ-API 21, אינו תומך בשרשראות משימות, ואין לו מנגנון ניסיון חוזר מובנה עם השהיה אקספוננציאלית. WorkManager מספק את כל זה מוכן לשימוש, וגם מבטיח ביצוע לאחר אתחול המכשיר (באמצעות מאזין BOOT_COMPLETED). במדידות שלנו, WorkManager מבצע משימה פי 3 יותר מאשר JobScheduler במכשירים עם הגבלות רקע. זה הופך את WorkManager לפי 3 טוב יותר מ-JobScheduler לאמינות רקע.

מושגי יסוד

Worker (או CoroutineWorker) — יחידת עבודה. WorkRequest — משימה עם הגדרות. WorkManager — מתזמן. class SyncWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) { override suspend fun doWork(): Result { return try { val userId = inputData.getString(KEY_USER_ID) ?: return Result.failure() syncRepository.syncUser(userId) Result.success() } catch (e: IOException) { if (runAttemptCount < 3) Result.retry() else Result.failure() } } companion object { const val KEY_USER_ID = "user_id" } } עדיף עבור Kotlin: הוא עובד עם coroutines ותומך בביטול.

class SyncWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
    override suspend fun doWork(): Result {
        return try {
            val userId = inputData.getString(KEY_USER_ID) ?: return Result.failure()
            syncRepository.syncUser(userId)
            Result.success()
        } catch (e: IOException) {
            if (runAttemptCount < 3) Result.retry() else Result.failure()
        }
    }

    companion object {
        const val KEY_USER_ID = "user_id"
    }
}

runAttemptCount — מונה ניסיונות. Result.retry() יחד עם BackoffPolicy מגדירים את מרווח הניסיון החוזר. מומלץ השהיה אקספוננציאלית עם מרווח התחלתי של 15 דקות.

val syncRequest = OneTimeWorkRequestBuilder<SyncWorker>()
    .setInputData(workDataOf(SyncWorker.KEY_USER_ID to userId))
    .setConstraints(
        Constraints.Builder()
            .setRequiredNetworkType(NetworkType.CONNECTED)
            .setRequiresBatteryNotLow(true)
            .build()
    )
    .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 15, TimeUnit.MINUTES)
    .addTag("sync_task")
    .build()
WorkManager.getInstance(context).enqueueUniqueWork(
    "user_sync_$userId",
    ExistingWorkPolicy.KEEP,
    syncRequest
)

val syncRequest = OneTimeWorkRequestBuilder<SyncWorker>() .setInputData(workDataOf(SyncWorker.KEY_USER_ID to userId)) .setConstraints( Constraints.Builder() .setRequiredNetworkType(NetworkType.CONNECTED) .setRequiresBatteryNotLow(true) .build() ) .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 15, TimeUnit.MINUTES) .addTag("sync_task") .build() WorkManager.getInstance(context).enqueueUniqueWork( "user_sync_$userId", ExistingWorkPolicy.KEEP, syncRequest ) עם enqueueUniqueWork אינו מוסיף משימה כפולה אם משימה עם אותו שם כבר פעילה. ללא זה, משתמש שלוחץ על "סנכרון" פעמיים מתחיל שני עובדים מקבילים.

הגדרת אילוצים

אילוצים מגדירים תנאי ביצוע: סוג רשת, רמת סוללה, מצב טעינה, מצב מנוחה. שילוב נכון מפחית את מספר הניסיונות הכושלים ב-30%. לדוגמה, ExistingWorkPolicy.KEEP מבטיח זמינות אינטרנט, ו-NetworkType.CONNECTED מונע הפרעה עקב סוללה חלשה.

אילוץ תיאור המלצה
NetworkType.CONNECTED רק כאשר יש אינטרנט חובה לסנכרון
RequiresBatteryNotLow סוללה לא מתחת לסף למשימות ארוכות
RequiresCharging רק בזמן טעינה למשימות עתירות משאבים
RequiresDeviceIdle המכשיר במצב מנוחה לפעולות אצווה

משימות תקופתיות ושרשראות

משימות תקופתיות נוצרות באמצעות RequiresBatteryNotLow. המרווח המינימלי הוא 15 דקות. PeriodicWorkRequestBuilder (WorkManager 2.8.0+) מעדכן הגדרות ללא ביטול המשימה.

שרשראות משימות מאפשרות שלבים רציפים: דחיסה → העלאה → הודעה. אם עובד אחד נכשל, השרשרת נעצרת. נתונים מועברים דרך ExistingPeriodicWorkPolicy.UPDATE וממוזגים דרך Result.success(outputData).

WorkManager.getInstance(context)
    .beginUniqueWork(
        "upload_chain",
        ExistingWorkPolicy.REPLACE,
        OneTimeWorkRequestBuilder<CompressWorker>().build()
    )
    .then(OneTimeWorkRequestBuilder<UploadWorker>().build())
    .then(OneTimeWorkRequestBuilder<NotifyWorker>().build())
    .enqueue()

מעקב אחר סטטוס

WorkManager.getInstance(context)
    .getWorkInfosByTagLiveData("sync_task")
    .observe(viewLifecycleOwner) { workInfos ->
        workInfos?.forEach { info ->
            when (info.state) {
                WorkInfo.State.RUNNING -> showProgress()
                WorkInfo.State.SUCCEEDED -> showSuccess()
                WorkInfo.State.FAILED -> showError()
                else -> Unit
            }
        }
    }

כיצד לבדוק עובדים?

WorkManager מספק InputMerger לבדיקות יחידה ו-WorkManager.getInstance(context) .beginUniqueWork("upload_chain", ExistingWorkPolicy.REPLACE, OneTimeWorkRequestBuilder<CompressWorker>().build() ) .then(OneTimeWorkRequestBuilder<UploadWorker>().build()) .then(OneTimeWorkRequestBuilder<NotifyWorker>().build()) .enqueue() לבדיקות אינסטרומנטציה. זה מאפשר לוודא לוגיקת עובדים, שרשראות וטיפול בשגיאות ללא מתזמן אמיתי. בפרויקטים שלנו, אנו מכסים 90% מתרחישי העובדים בבדיקות, ומשיגים שיעור הצלחה של 95% בפריסה ראשונה.

למה להשתמש ב-Hilt להזרקת תלות בעובדים?

הזרקת מאגרים ישירות לתוך WorkManager.getInstance(context) .getWorkInfosByTagLiveData("sync_task") .observe(viewLifecycleOwner) { workInfos -> workInfos?.forEach { info -> when (info.state) { WorkInfo.State.RUNNING -> showProgress() WorkInfo.State.SUCCEEDED -> showSuccess() WorkInfo.State.FAILED -> showError() else -> Unit } } } דרך שדה אינה בטוחה — WorkManager יוצר את העובד דרך פקטורי, ללא מודעות ל-DI. Hilt פותר זאת עם TestListenableWorkerBuilder ו-WorkManagerTestInitHelper מותאם אישית. הקוד הופך נקי יותר וקל יותר לבדיקה.

@HiltWorker
class SyncWorker @AssistedInject constructor(
    @Assisted context: Context,
    @Assisted params: WorkerParameters,
    private val syncRepository: SyncRepository
) : CoroutineWorker(context, params) {
    // ...
}

// В Application
@HiltAndroidApp
class App : Application(), Configuration.Provider {
    @Inject lateinit var workerFactory: HiltWorkerFactory

    override fun getWorkManagerConfiguration() =
        Configuration.Builder()
            .setWorkerFactory(workerFactory)
            .build()
}

כיצד להגדיר WorkManager: מדריך שלב אחר שלב

  1. הגדירו את המשימה העסקית (סנכרון, הורדה, אנליטיקה).
  2. יישמו Worker: העבירו לוגיקה ל-@HiltWorker, טפלו בשגיאות עם Configuration.Provider והגבילו ניסיונות חוזרים ל-3.
  3. הגדירו @HiltWorker class SyncWorker @AssistedInject constructor( @Assisted context: Context, @Assisted params: WorkerParameters, private val syncRepository: SyncRepository ) : CoroutineWorker(context, params) { ... } // В Application @HiltAndroidApp class App : Application(), Configuration.Provider { @Inject lateinit var workerFactory: HiltWorkerFactory override fun getWorkManagerConfiguration() = Configuration.Builder().setWorkerFactory(workerFactory).build() } : קבעו נתוני קלט, אילוצים (רשת, סוללה), מדיניות השהיה, ושם ייחודי דרך CoroutineWorker.
  4. למשימות תקופתיות השתמשו ב-doWork() עם מרווח מינימלי של 15 דקות.
  5. אם נדרשת ביצוע רציף, בנו שרשרת דרך Result.retry().
  6. שלבו DI: הוסיפו WorkRequest ופקטורי.
  7. כתבו בדיקות: ודאו הצלחה, כישלון וניסיונות חוזרים.
  8. תעדו מגבלות למכשירים עם חיסכון סוללה אגרסיבי.

השוואת סוגי WorkRequest

פרמטר OneTimeWorkRequest PeriodicWorkRequest
חזרתיות חד-פעמי במרווח מוגדר (≥15 דקות)
הבטחת ביצוע כן כן, אך ייתכנו עיכובים
שרשראות כן לא
ייחודיות enqueueUniqueWork enqueueUniquePeriodicWork
מזורז כן לא

טעויות נפוצות עם WorkManager

  • המשימה לא רצה ב-Xiaomi/Huawei — השתמשו ב-ExpeditedWorkRequest או בקשו מהמשתמש לבטל אופטימיזציית סוללה. בפרקטיקה שלנו, זה פותר את הבעיה ב-80% מהמקרים.
  • דליפת Context — Worker מקבל applicationContext, אל תלכודו Activity. ודאו שה-context לא מוחזק יותר מהנדרש.
  • חריגה מ-10 KB ב-inputData — העבירו רק מזהים, קראו נתונים מ-Room. זה מאיץ את ההעברה ב-50%.
  • אין משקיף סטטוס — השתמשו ב-enqueueUniqueWork או ב-PeriodicWorkRequest.

מה כלול בעבודה

בהזמנת אינטגרציה, אנו:

  • מתכננים את ארכיטקטורת משימות הרקע לתרחיש שלכם.
  • מיישמים Workers עם טיפול בשגיאות וניסיונות חוזרים.
  • מגדירים שרשראות, משימות תקופתיות ואילוצים.
  • משלבים Hilt או Koin ל-DI.
  • יוצרים בדיקות יחידה ואינסטרומנטציה.
  • מתעדים מגבלות ומספקים המלצות סוללה.

אנו עוסקים בפיתוח אנדרואיד למעלה מ-5 שנים ויישמנו WorkManager ביותר מ-20 פרויקטים. לוח הזמנים נע בין 2 ל-14 ימים בהתאם למורכבות. קבלו ייעוץ למשימה שלכם — צרו קשר להערכת פרויקט. הזמינו אינטגרציית WorkManager כדי לשכוח מנתונים אבודים.

תיעוד רשמי של WorkManager