מדוע סנכרון ברקע מסובך יותר ממה שנדמה
תארו לעצמכם: משתמש פותח את שירות המשלוחים שלכם, אבל רשימת ההזמנות ריקה — הנתונים לא התעדכנו מאז הבוקר. התוצאה: ביקורת שלילית ולקוח אבוד. Background Fetch פותר זאת, אך הטמעתו דורשת טיפול זהיר במגבלות הפלטפורמה, בצריכת הסוללה ובמחזור חיי האפליקציה. אנו מגדירים Background Fetch במפתח מלא תוך 3–5 ימים לכל פלטפורמה, עם פעילות יציבה מובטחת. למעלה מ-5 שנים אנו מפתחים אפליקציות מובייל עם סנכרון ברקע ל-iOS ואנדרואיד. הניסיון שלנו: 50+ פרויקטים, כולל לבנקאות, קמעונאות ולוגיסטיקה.
בעיות שאנו פותרים
- נתונים מיושנים: הזמנות, הודעות או מלאי שלא עודכנו ברקע.
- צריכת סוללה: סנכרון לא מוגדר כראוי יכול לצרוך עד 5% לכל סשן.
- מגבלות פלטפורמה: iOS עשויה לדלג על משימות אם הסוללה נמוכה; Doze Mode של אנדרואיד מגביל את הביצוע.
- מרווחים לא עקביים: הסתמכות על
UIApplication.setMinimumBackgroundFetchIntervalב-iOS היא מיושנת ולא אמינה.
איך אנחנו עושים זאת
iOS Background Fetch עם מסגרת BGTask
iOS מודרנית משתמשת במסגרת BackgroundTasks. ה-BGTaskScheduler.shared.register( forTaskWithIdentifier: "com.myapp.refresh", using: nil ) { task in self.handleAppRefresh(task: task as! BGAppRefreshTask) } הישן מופסק. רישום משימה:
BGTaskScheduler.shared.register(
forTaskWithIdentifier: "com.myapp.refresh",
using: nil
) { task in
self.handleAppRefresh(task: task as! BGAppRefreshTask)
}המזהה חייב להיות רשום ב-Info.plist תחת BGTaskSchedulerPermittedIdentifiers. ללא זה, המשימה לא תירשם — אין שגיאה, רק שקט. זו מלכודת נפוצה. תזמון הריצה הבאה מתרחש בסוף הביצוע הנוכחי דרך BGAppRefreshTaskRequest. המרווח המינימלי מוגדר עם earliestBeginDate, אבל iOS מחליטה מתי להריץ בפועל את המשימה בהתבסס על סוללה ודפוסי שימוש. אין הבטחה לזמן ספציפי. קריטית: למשימת רקע יש מגבלת זמן CPU. אם המשימה לא מסתיימת בזמן, המערכת קוראת ל-task.expirationHandler. עליכם לשמור התקדמות ולקרוא ל-task.setTaskCompleted(success: false). בשימוש בסנכרון אינקרמנטלי, נפח הנתונים יורד ב-60%, וחוסך עד 25% סוללה בהשוואה לטעינות מלאות.
סנכרון ברקע באנדרואיד עם WorkManager
WorkManager הוא הכלי הנכון למשימות תקופתיות באנדרואיד. הוא אמין פי 10 מ-AlarmManager ב-Doze Mode ושורד אתחולים. הוא מחליף את JobScheduler, AlarmManager ו-SyncAdapter ברוב המקרים.
val refreshRequest = PeriodicWorkRequestBuilder<DataRefreshWorker>(
repeatInterval = 1,
repeatIntervalTimeUnit = TimeUnit.HOURS,
flexTimeInterval = 15,
flexTimeIntervalUnit = TimeUnit.MINUTES
)
.setConstraints(
Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresBatteryNotLow(true)
.build()
)
.build()
WorkManager.getInstance(context).enqueueUniquePeriodicWork(
"data_refresh",
ExistingPeriodicWorkPolicy.KEEP,
refreshRequest
)val refreshRequest = PeriodicWorkRequestBuilder<DataRefreshWorker>( repeatInterval = 1, repeatIntervalTimeUnit = TimeUnit.HOURS, flexTimeInterval = 15, flexTimeIntervalUnit = TimeUnit.MINUTES ) .setConstraints( Constraints.Builder() .setRequiredNetworkType(NetworkType.CONNECTED) .setRequiresBatteryNotLow(true) .build() ) .build() WorkManager.getInstance(context).enqueueUniquePeriodicWork( "data_refresh", ExistingPeriodicWorkPolicy.KEEP, refreshRequest ) מונע החלפה של המשימה הקיימת אם ExistingPeriodicWorkPolicy.KEEP נקרא שוב (חשוב בכל הפעלת אפליקציה). המרווח המינימלי עבור enqueue הוא 15 דקות — המערכת לא תאפשר פחות. אם לא תגדירו PeriodicWorkRequest, המערכת עשויה להריץ את המשימה מיד לאחר סיום המרווח, מה שמגביר את צריכת הסוללה ב-15–20%.
השוואה: iOS Background Fetch מול Android WorkManager
| פרמטר | iOS (BGAppRefreshTask) | אנדרואיד (WorkManager) |
|---|---|---|
| תקופתיות | מרווח מינימלי מוגדר אך לא מובטח | מינימום 15 דקות, מובטח כשהתנאים מתקיימים |
| ניהול סוללה | אוטומטי, מבוסס על דפוסי שימוש | אילוצים ניתנים להגדרה: רמת סוללה, טעינה, רשת |
| נדרשת רישום | כן, ב-Info.plist | לא, אוטומטי דרך הגדרות |
| ביטול משימה | flexTimeInterval |
cancel(taskRequestWithIdentifier:) עם מדיניות enqueueUniquePeriodicWork |
| טיפול בשגיאות | CANCEL_AND_REENQUEUE |
expirationHandler, Result.retry() |
מקרה אמיתי: סנכרון אינקרמנטלי באפליקציית משלוחי מזון
עבדנו על שירות משלוחי מזון שבו האפליקציה הורידה את כל רשימת ההזמנות (בממוצע 15 MB) כל 15 דקות. זה גרם לצריכת סוללה חמורה ולזמני פסק זמן תכופים. עיצבנו מחדש את הסנכרון לשימוש בחותמות זמן: עכשיו האפליקציה מעבירה רק שינויים מהשעה האחרונה (כ-200 KB), והמשימה ברקע מסתיימת תוך 2 שניות. צריכת הסוללה ירדה ב-40%, וכשלי הסנכרון ירדו מ-25% ל-3%.
בחירה בין סנכרון מלא לאינקרמנטלי
| קריטריון | סנכרון מלא | סנכרון אינקרמנטלי |
|---|---|---|
| נפח נתונים | כל מערך הנתונים (5–50 MB) | רק שינויים (0.1–1 MB) |
| זמן ביצוע | 10–30 שניות | 1–3 שניות |
| צריכת סוללה | 2–5% לכל סשן | 0.2–1% לכל סשן |
| סיכון לפסק זמן | גבוה (עד 30% כשלים) | נמוך (מתחת ל-5% כשלים) |
סנכרון אינקרמנטלי מהיר פי 4 מסנכרון מלא ומשתמש בפי 10 פחות תעבורה. אנו ממליצים על גישה אינקרמנטלית לאפליקציות עם עדכוני רקע תכופים. זה מהיר פי 4 ויעיל פי 10 בתעבורה. הגדרת סנכרון ברקע במפתח מלא מתחילה ב-$1,500 לכל פלטפורמה. בקשו ייעוץ — נעזור לכם לבחור את אסטרטגיית הסנכרון האופטימלית לפרויקט שלכם.
מה לעשות במשימת רקע
משימת רקע צריכה להיות מינימלית: לבקש רק מה שהשתנה (סנכרון אינקרמנטלי), לשמור למסד נתונים מקומי (Room / Core Data), ולשלוח התראה מקומית אם יש עדכונים חשובים. הימנעו מחישובים כבדים, מבקשות HTTP גדולות ללא פסק זמן, או מפעולות UI סינכרוניות.
איך לנפות באגים בסנכרון ברקע: שלב אחר שלב
-
iOS: השתמשו ב-Xcode עם דגל
Result.failure()והפעילו רישום דרךBGTaskScheduler.shared.register. הפעילו את המשימה באמצעותOSSignposterבסימולטור. -
אנדרואיד: הוסיפו
simulateBackgroundFetchלקוד והדפיסו את הסטטוס. לריצה כפויה, השתמשו ב-WorkManager.getWorkInfosByTag("data_refresh"). - ודאו שהמשימה לא חורגת ממגבלת ה-CPU: ב-iOS — 30 שניות, באנדרואיד — 10 דקות (בהתחשב במגבלות Doze Mode).
- באנדרואיד, הסתמכו על
adb shell am broadcast -a android.intent.action.BOOT_COMPLETED— הוא מטפל נכון באילוצי סוללה, בניגוד ל-AlarmManagerשלא יפעל ב-Doze Mode.
React Native ו-Flutter
ב-React Native, משימות רקע מיושמות דרך מודולים מקוריים. הספרייה WorkManager עוטפת את BGAppRefreshTask ב-iOS ואת JobScheduler/WorkManager באנדרואיד ל-API אחיד ב-JS. ב-Flutter, השתמשו בתוסף react-native-background-fetch לאנדרואיד וב-workmanager ל-iOS. אותן מגבלות פלטפורמה חלות — האבסטרקציה לא מסירה אותן. ציר זמן הטמעה: 3–5 ימים לפלטפורמה אחת, 1–1.5 שבועות ל-iOS + אנדרואיד עם בדיקת מקרי קצה (סוללה, ללא רשת, Doze Mode באנדרואיד).
תוצרים
- ביקורת על היישום הנוכחי של משימות רקע
- עיצוב ארכיטקטורה לסנכרון (אינקרמנטלי, קאשינג)
- אינטגרציה של BGTask / WorkManager לפי שיטות העבודה המומלצות של הפלטפורמה
- הגדרת התראות push להתראות על שינויים
- אופטימיזציה של צריכת סוללה באמצעות פרופיילרים — הפחתה של עד 30%
- בדיקות על 10+ מכשירים עם גרסאות מערכת הפעלה שונות
- תיעוד והמלצות לניטור ייצור
- גישה לקוד המקור ולתיעוד הפרויקט
- סשן הדרכה לצוות הפיתוח שלכם
- חודש תמיכה חינם לאחר הפריסה
מדוע סנכרון ברקע עלול להיכשל?
שתי הסיבות הנפוצות ביותר: המערכת מסיימת את האפליקציה עקב לחץ זיכרון, או שהמשימה חורגת ממגבלת זמן ה-CPU שלה. פתרונות כוללים סנכרון אינקרמנטלי וקאשינג יעיל של נתונים.צרו קשר כדי לדון בפרויקט שלכם. קבלו ייעוץ על הטמעת סנכרון ברקע עוד היום.







