Background — حالتی از چرخه حیات برنامه است که در آن به اجرا ادامه میدهد اما روی صفحه نمایش داده نمیشود. مبانی کار پسزمینه در iOS و Android را توضیح میدهیم: محدودیتها، مهلتهای زمانی، وظایف پسزمینه از طریق beginBackgroundTask، WorkManager و Service، و همچنین بهترین روشها برای پردازش صحیح Background.
نکات اصلی
Background — حالتی از برنامه که در آن همچنان در سیستم عامل وجود دارد، کد اجرا میکند و منابع مصرف میکند، اما روی صفحه دستگاه نمایش داده نمیشود. کاربر در صفحه اصلی، در برنامه دیگر یا صفحه دستگاه قفل است. در iOS Background پس از Inactive قرار میگیرد — زنجیره انتقال: Active → Inactive → Background. در Android onStop انتقال Activity به Background را نشان میدهد.
هر دو پلتفرم محدودیتهای سختی برای کار پسزمینه اعمال میکنند. iOS یک پنجره محدود (معمولاً ۳۰ ثانیه) برای اجرای کد پس از رفتن به Background فراهم میکند، پس از آن برنامه به Suspended منتقل میشود. Android انعطافپذیرتر است: Foreground Service با اعلان قابل مشاهده میتواند به طور نامحدود کار کند، اما Background Service معمولی به چند دقیقه محدود است. وظیفه کلیدی توسعهدهنده — ذخیره صحیح وضعیت و برنامهریزی ادامه کار از طریق APIهای سیستمی وظایف پسزمینه است.
سیستم میتواند در هر زمان در صورت کمبود حافظه، برنامه پسزمینه را خاتمه دهد. در صورت خاتمه، تمام دادههای ذخیرهنشده از بین میروند. بنابراین ذخیره وضعیت در applicationDidEnterBackground (iOS) یا onStop (Android) بسیار حیاتی است. پس از خاتمه، در راهاندازی بعدی برنامه از Not Running با راهاندازی سرد شروع میکند و وضعیت ذخیرهشده را بازیابی میکند.
تشخیص Background و Suspended مهم است. Background — برنامه به طور فعال کد اجرا میکند. Suspended — برنامه در حافظه است اما کد اجرا نمیکند — منجمد شده است. در iOS برنامه پس از اتمام وظایف پسزمینه از Background به Suspended منتقل میشود. در Android Suspended وجود ندارد — فرآیند要么 وجود دارد (از جمله در پسزمینه) یا خاتمه یافته (Not Running). با این حال Android میتواند اجرای رشتهها را از طریق LMK (Low Memory Killer) متوقف کند.
| ویژگی | iOS Background | Android Background |
|---|---|---|
| کد اجرا میشود | بله، تا ۳۰ ثانیه | بله، بستگی به API دارد |
| UI قابل مشاهده | خیر | خیر |
| مهلت پیشفرض | ~۳۰ ثانیه (beginBackgroundTask) | چند دقیقه (Service) |
| کار نامحدود | فقط دستههای خاص (صوت، VoIP، ناوبری) | Foreground Service با اعلان |
| ضمانت اجرا | خیر — سیستم میتواند در هر زمان خاتمه دهد | WorkManager ضمانت اجرا دارد |
| مجوز لازم است | بله — capabilities در Info.plist | بله — مجوز FOREGROUND_SERVICE |
| وضعیت بعدی | Suspended → Not Running | Not Running (یا راهاندازی مجدد) |
در iOS Background از طریق متد نماینده applicationDidEnterBackground پردازش میشود. در این متد توسعهدهنده باید وضعیت کاربر را ذخیره کند، منابع را آزاد کند و وظایف پسزمینه را به پایان برساند. برای اجرای کد پس از رفتن به Background از beginBackgroundTask(expirationHandler:) استفاده میشود — API که از سیستم زمان اضافی (معمولاً ۳۰ ثانیه) درخواست میکند. اگر وظیفه در این زمان به پایان نرسد، expirationHandler فراخوانی میشود و برنامه به زور به Suspended منتقل میشود.
از iOS 13، Apple BGTaskScheduler را معرفی کرد — API مدرن برای برنامهریزی وظایف پسزمینه. بر خلاف beginBackgroundTask که فقط پس از رفتن به پسزمینه زمان برای اتمام میدهد، BGTaskScheduler امکان برنامهریزی اجرای وظایف در آینده را فراهم میکند — به عنوان مثال، بهروزرسانی محتوا هر ساعت یا آپلود آنالیتیکس در شب. BGTaskScheduler رویکرد توصیهشده برای پروژههای جدید است، زیرا از نظر باتری کارآمدتر است.
import UIKit
import BackgroundTasks
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var backgroundTaskID: UIBackgroundTaskIdentifier = .invalid
// برنامه به پسزمینه رفت — وظیفه پسزمینه را شروع میکنیم
func applicationDidEnterBackground(_ application: UIApplication) {
saveAppState()
startBackgroundTask()
}
private func startBackgroundTask() {
backgroundTaskID = UIApplication.shared.beginBackgroundTask { [weak self] in
// زمان تمام شد — به زور خاتمه میدهیم
self?.endBackgroundTask()
}
// کار پسزمینه را شبیهسازی میکنیم (ذخیره دادهها روی سرور)
DispatchQueue.global().async { [weak self] in
uploadAnalyticsData()
self?.endBackgroundTask()
}
}
private func endBackgroundTask() {
guard backgroundTaskID != .invalid else { return }
UIApplication.shared.endBackgroundTask(backgroundTaskID)
backgroundTaskID = .invalid
}
// ثبت BGTaskScheduler
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
BGTaskScheduler.shared.register(
forTaskWithIdentifier: "com.example.refresh",
using: nil
) { task in
handleAppRefresh(task: task as! BGAppRefreshTask)
}
return true
}
func scheduleAppRefresh() {
let request = BGAppRefreshTaskRequest(identifier: "com.example.refresh")
request.earliestBeginDate = Date(timeIntervalSinceNow: 3600)
try? BGTaskScheduler.shared.submit(request)
}
func handleAppRefresh(task: BGAppRefreshTask) {
scheduleAppRefresh()
task.expirationHandler = { task.setTaskCompleted(success: false) }
fetchLatestData { result in
task.setTaskCompleted(success: result)
}
}
}کد پردازش کامل Background در iOS را نشان میدهد. applicationDidEnterBackground یک وظیفه پسزمینه را از طریق beginBackgroundTask با مهلت زمانی و expirationHandler شروع میکند. به موازات آن، BGTaskScheduler برای بهروزرسانی دورهای محتوا ثبت میشود. beginBackgroundTask برای اتمام فوری کار استفاده میشود، BGTaskScheduler — برای برنامهریزی بلندمدت. هر دو API نیاز به مدیریت صحیح شناسههای وظایف دارند.
در Android Background از طریق چندین API مدیریت میشود. Service سنتی امکان اجرای کد در پسزمینه را فراهم میکند، اما از Android 8+ (API 26) Background Service محدود شده است: سیستم آن را چند دقیقه پس از رفتن برنامه به پسزمینه خاتمه میدهد. Foreground Service با اعلان دائمی میتواند به طور نامحدود کار کند. WorkManager — راهحل توصیهشده برای وظایف پسزمینه با ضمانت اجرا حتی پس از راهاندازی مجدد دستگاه.
Android، بر خلاف iOS، از فرآیندهای پسزمینه طولانیمدت پشتیبانی میکند. Foreground Service برای وظایفی استفاده میشود که کاربر باید ببیند — پخش موسیقی، ناوبری، ثبت تمرین. JobScheduler و WorkManager — برای وظایفی که میتوانند به تعویق بیفتند: همگامسازی دادهها، آپلود لاگها، بهروزرسانی کش. تفاوت کلیدی: Android امکان برنامهریزی وظایف با شرایط را میدهد — Wi-Fi، شارژ، عدم فعالیت دستگاه، که باعث صرفهجویی در باتری و ترافیک میشود.
import android.app.Service
import android.content.Intent
import android.os.IBinder
import androidx.work.*
// 1. Foreground Service برای کار طولانی پسزمینه
class SyncService : Service() {
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val notification = createNotification()
startForeground(NOTIFICATION_ID, notification)
performBackgroundWork()
return START_STICKY
}
private fun performBackgroundWork() {
Thread {
// همگامسازی دادهها با سرور
syncDataToServer()
stopForeground(STOP_FOREGROUND_REMOVE)
stopSelf()
}.start()
}
override fun onBind(intent: Intent?): IBinder? = null
}
// 2. WorkManager برای وظایف به تعویق افتاده پسزمینه
class DataSyncWorker(
private val context: Context,
private val params: WorkerParameters
) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
return try {
// آپلود آنالیتیکس روی سرور
uploadAnalytics()
Result.success()
} catch (e: Exception) {
if (runAttemptCount < 3) Result.retry() else Result.failure()
}
}
}
// برنامهریزی وظیفه WorkManager
fun scheduleBackgroundSync(context: Context) {
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresBatteryNotLow(true)
.build()
val request = OneTimeWorkRequestBuilder<DataSyncWorker>()
.setConstraints(constraints)
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 30, TimeUnit.SECONDS)
.build()
WorkManager.getInstance(context).enqueue(request)
}کد دو رویکرد برای کار پسزمینه در Android را نشان میدهد. SyncService — Foreground Service با اعلان برای کار فوری و طولانی پسزمینه. DataSyncWorker — WorkManager برای وظایف به تعویق افتاده با شرایط (Wi-Fi، شارژ). WorkManager ضمانت اجرا حتی پس از راهاندازی مجدد دستگاه را دارد و از exponential backoff برای تلاشهای مجدد پشتیبانی میکند. Foreground Service نیاز به اعلان دائمی در نوار وضعیت دارد.
هر دو پلتفرم موبایل دائماً قوانین کار پسزمینه را سختتر میکنند. در iOS هر نسل جدید سیستم عامل زمان کار در پسزمینه را کاهش میدهد و محدودیتهای جدیدی اضافه میکند. در Android Google حالتهای صرفهجویی در انرژی سختتری را معرفی میکند (Doze، App Standby). توسعهدهنده باید از محدودیتهای فعلی آگاه باشد تا برنامه قبل از موعد توسط سیستم خاتمه نیابد.
در iOS از iOS 13، سیستم وظایف پسزمینه را برای برنامههایی که از زمان پسزمینه سوءاستفاده میکنند غیرفعال میکند. هر برنامه بر اساس رفتار کاربر محدودیتهای خاصی دریافت میکند. BGTaskScheduler اجرا را در زمان بهینه برنامهریزی میکند — مثلاً وقتی دستگاه به Wi-Fi متصل است و در حال شارژ است. برنامههایی که به درستی از BGTaskScheduler استفاده میکنند، زمان پسزمینه بیشتری دریافت میکنند.
در Android از Android 9 (API 28) کار پسزمینه توسط حالت Doze محدود میشود که در زمان عدم فعالیت دستگاه فعال میشود. برنامههای در Doze نمیتوانند وظایف پسزمینه را اجرا کنند، شبکه قطع میشود، JobScheduler و WorkManager وظایف را تا خروج از Doze به تعویق میاندازند. Foreground Service تنها راه دور زدن Doze است، اما سوءاستفاده منجر به مسدود شدن برنامه توسط کاربر و حذف مجوزها میشود.
| محدودیت | iOS | Android |
|---|---|---|
| مهلت وظیفه پسزمینه | ~۳۰ ثانیه (beginBackgroundTask) | چند دقیقه (JobScheduler) |
| پسزمینه نامحدود | صوت، VoIP، ناوبری، Bluetooth | Foreground Service + اعلان |
| صرفهجویی انرژی | Low Power Mode — غیرفعال کردن وظایف پسزمینه | Doze، App Standby، Battery Optimization |
| برنامهریزی | BGTaskScheduler (iOS 13+) | WorkManager (Android Jetpack) |
| پس از راهاندازی مجدد | فقط اعلان push | WorkManager وظایف را حفظ میکند |
| حداکثر زمان اجرا | ~۳۰ دقیقه (صوت) | نامحدود (Foreground Service) |
قاعده اول — مصرف منابع در پسزمینه را به حداقل برسانید. بیشتر وظایف پسزمینه را میتوان به زمانی موکول کرد که دستگاه در حال شارژ و متصل به Wi-Fi است. از BGTaskScheduler (iOS) و WorkManager (Android) برای برنامهریزی وظایف با شرایط استفاده کنید. محاسبات سنگین در پسزمینه اجرا نکنید — این کار باتری را تخلیه کرده و باعث throttling CPU میشود.
قاعده دوم — همیشه برای beginBackgroundTask expirationHandler تعیین کنید. اگر برنامه وظیفه را در زمان تعیینشده به پایان نرساند، سیستم به زور آن را به Suspended منتقل یا خاتمه میدهد. ExpirationHandler آخرین شانس برای ذخیره دادهها و پایان صحیح کار است. در Android از setForegroundAsync در WorkManager استفاده کنید برای تبدیل وظیفه معمولی به foreground، اگر زمان بیشتری نیاز است.
قاعده سوم — قبل از راهاندازی محدودیتهای کار پسزمینه را بررسی کنید. در iOS از UIApplication.shared.backgroundTimeRemaining برای بررسی زمان باقیمانده استفاده کنید. در Android ActivityManager.isBackgroundRestricted() را بررسی کنید — اگر true باشد، برنامه نمیتواند وظایف پسزمینه را اجرا کند و باید به کاربر پیشنهاد دهید محدودیتها را در تنظیمات بردارد. این به ویژه برای برنامههای با وظایف حیاتی پسزمینه مهم است — ساعتهای زنگدار، تقویمها، همگامسازی.
قاعده چهارم — وظایف پسزمینه را روی دستگاه واقعی تست کنید. شبیهساز و emulator محدودیتهای واقعی کار پسزمینه را بازتولید نمیکنند. در iOS از Debug → Simulate Background Fetch در Xcode استفاده کنید. در Android — adb shell am broadcast -a android.intent.action.ACTION_BOOT_COMPLETED برای تست WorkManager پس از راهاندازی مجدد. تستهای واقعی روی دستگاه با باتری کم بیشتر مشکلات کار پسزمینه را آشکار میکنند.
import UIKit
final class BackgroundTaskManager {
static let shared = BackgroundTaskManager()
private var tasks: [String: UIBackgroundTaskIdentifier] = [:]
func startTask(name: String, expiration: @escaping () -> Void) {
let remaining = UIApplication.shared.backgroundTimeRemaining
print("زمان باقیمانده در پسزمینه: \(remaining) ثانیه")
let task = UIApplication.shared.beginBackgroundTask { [weak self] in
print("زمان برای وظیفه به پایان رسید: \(name)")
expiration()
self?.endTask(name: name)
}
tasks[name] = task
}
func endTask(name: String) {
guard let task = tasks.removeValue(forKey: name),
task != .invalid
else { return }
UIApplication.shared.endBackgroundTask(task)
}
}کد مدیر وظایف پسزمینه را نشان میدهد که زمان باقیمانده را ردیابی کرده و شناسهها را مدیریت میکند. backgroundTimeRemaining تعداد ثانیههای باقیمانده تا خاتمه اجباری را برمیگرداند — اگر مقدار بینهایت باشد، برنامه بدون محدودیت کار میکند (صوت، ناوبری). مدیر امکان اجرای چندین وظیفه پسزمینه با نامهای مختلف و پایان صحیح هر یک را فراهم میکند. این رویکرد از نشت وظایف پسزمینه جلوگیری کرده و تضمین میکند که سیستم برنامه را به دلیل وظایف بستهنشده خاتمه ندهد.
سوالات متداول
بله، برای تعداد محدودی از دستهها: صوت (AVAudioSession دسته .playback)، VoIP (PushKit)، ناوبری (CLLocationManager با allowsBackgroundLocationUpdates)، Bluetooth (حالت پسزمینه مرکزی)، بهروزرسانی پسزمینه (BGTaskScheduler). برای بقیه — حداکثر ۳۰ ثانیه. در iOS 16+ Apple الزامات را حتی برای دستههای مجاز سختتر کرده است.
beginBackgroundTask — API همزمان برای افزایش عمر برنامه به مدت ~۳۰ ثانیه پس از رفتن به پسزمینه. در applicationDidEnterBackground فراخوانی میشود. BGTaskScheduler — API ناهمزمان برای برنامهریزی وظایف در آینده از طریق محرکهای سیستمی (زمان، مکان، بهروزرسانی محتوا). BGTaskScheduler رویکرد مدرنی است که توسط Apple برای iOS 13+ توصیه میشود.
از Android 8 (API 26)، Background Service چند دقیقه پس از رفتن برنامه به پسزمینه خاتمه مییابد. راهحل: برای عملیات طولانی از Foreground Service با اعلان یا برای وظایف به تعویق افتاده از WorkManager استفاده کنید. Battery Optimization برنامه خود را در تنظیمات بررسی کنید — اگر بهینهسازی شده باشد، سیستم میتواند وظایف پسزمینه را به تعویق بیندازد یا لغو کند.
Cmd+Shift+H را برای رفتن به صفحه اصلی فشار دهید. در Xcode از Debug → Simulate Background Fetch استفاده کنید. برای بررسی beginBackgroundTask کنسول را باز کنید (Shift+Cmd+C) و e UIApplication.shared.backgroundTimeRemaining را فراخوانی کنید. در Xcode 15+ سناریوی Background Execution در برگه Diagnostics شبیهساز در دسترس است.
Process Death — خاتمه فرآیند Android توسط سیستم در زمان کمبود منابع یا عدم فعالیت در پسزمینه. بر خلاف iOS، Android Suspended ندارد — فرآیند یا زنده است (میتواند در پسزمینه باشد) یا مرده (Not Running). Process Death رفتار عادی سیستم عامل است و برنامه باید وضعیت را پس از آن از طریق SavedStateHandle، onSaveInstanceState یا DataStore به درستی بازیابی کند.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.