Background, uygulamanın çalışmaya devam ettiği ancak ekranda görüntülenmediği bir yaşam döngüsü durumudur. iOS ve Android'de arka plan çalışmasının temellerini açıklıyoruz: kısıtlamalar, zaman aşımları, beginBackgroundTask, WorkManager ve Service aracılığıyla arka plan görevleri ve Background'ın doğru şekilde işlenmesi için en iyi uygulamalar.
Önemli Noktalar
Background, uygulamanın işletim sisteminde var olmaya devam ettiği, kod çalıştırdığı ve kaynak tükettiği ancak cihaz ekranında görüntülenmediği bir durumdur. Kullanıcı Ana Ekranda, başka bir uygulamadadır veya cihaz ekranı kilitlidir. iOS'te, Background Inactive'den sonra gelir — geçiş zinciri: Active → Inactive → Background. Android'de, onStop bir Activity'nin Background'a geçişini işaret eder.
Her iki platform da arka plan çalışmasına katı kısıtlamalar getirir. iOS, Background'a girdikten sonra kod yürütmek için sınırlı bir pencere (genellikle 30 saniye) sağlar, ardından uygulama Suspended'e geçer. Android daha esnektir: görünür bildirimli bir Foreground Service süresiz çalışabilir, ancak normal bir Background Service birkaç dakika ile sınırlıdır. Geliştiricinin temel görevi, durumu doğru şekilde kaydetmek ve sistem arka plan görev API'leri aracılığıyla çalışmanın devamını planlamaktır.
Sistem, bellek azaldığında arka plan uygulamasını herhangi bir zamanda sonlandırabilir. Sonlandırma sırasında kaydedilmemiş tüm veriler kaybolur. Bu nedenle, applicationDidEnterBackground (iOS) veya onStop (Android) içinde durumu kaydetmek kritik öneme sahiptir. Sonlandırmadan sonra, bir sonraki başlatma Not Running'dan soğuk başlatma ile başlar ve kaydedilen durumu geri yükler.
Background ve Suspended arasında ayrım yapmak önemlidir. Background — uygulama aktif olarak kod çalıştırıyor. Suspended — uygulama bellekte ancak kod çalıştırmıyor — donmuş durumda. iOS'te, uygulama arka plan görevlerini tamamladıktan sonra Background'dan Suspended'e geçer. Android'de Suspended yoktur — süreç ya vardır (Background dahil) ya da sonlandırılmıştır (Not Running). Ancak Android, LMK (Low Memory Killer) aracılığıyla iş parçacığı yürütmesini duraklatabilir.
| Özellik | iOS Background | Android Background |
|---|---|---|
| Kod çalıştırma | Evet, 30 saniyeye kadar | Evet, API'ye bağlı |
| UI görünür | Hayır | Hayır |
| Varsayılan zaman aşımı | ~30 sn (beginBackgroundTask) | Birkaç dakika (Service) |
| Sınırsız çalışma | Yalnızca özel kategoriler (ses, VoIP, navigasyon) | Bildirimli Foreground Service |
| Yürütme garantisi | Hayır — sistem her an sonlandırabilir | WorkManager yürütmeyi garanti eder |
| İzin gerekli | Evet — Info.plist'te capabilities | Evet — FOREGROUND_SERVICE izni |
| Sonraki durum | Suspended → Not Running | Not Running (veya yeniden başlatma) |
iOS'te, Background temsilci yöntemi applicationDidEnterBackground aracılığıyla işlenir. Bu yöntemde, geliştirici kullanıcı durumunu kaydetmeli, kaynakları serbest bırakmalı ve arka plan görevlerini tamamlamalıdır. Background'a girdikten sonra kod çalıştırmak için beginBackgroundTask(expirationHandler:) kullanılır — sistemden ek süre (genellikle 30 saniye) isteyen bir API. Görev bu süre içinde tamamlanmazsa, expirationHandler çağrılır ve uygulama zorla Suspended'e geçirilir.
iOS 13 ile Apple, BGTaskScheduler'ı tanıttı — arka plan görevlerini planlamak için modern bir API. Arka plana geçtikten sonra yalnızca bitirmek için süre veren beginBackgroundTask'ın aksine, BGTaskScheduler gelecekte görev yürütmeyi planlamaya olanak tanır — örneğin, saatte bir içerik güncelleme veya geceleri analiz yükleme. BGTaskScheduler yeni projeler için önerilen yaklaşımdır, çünkü pil açısından daha verimlidir.
import UIKit
import BackgroundTasks
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var backgroundTaskID: UIBackgroundTaskIdentifier = .invalid
// Uygulama arka plana geçti — arka plan görevi başlatılıyor
func applicationDidEnterBackground(_ application: UIApplication) {
saveAppState()
startBackgroundTask()
}
private func startBackgroundTask() {
backgroundTaskID = UIApplication.shared.beginBackgroundTask { [weak self] in
// Süre doldu — zorla sonlandırılıyor
self?.endBackgroundTask()
}
// Arka plan çalışması simüle ediliyor (veriler sunucuya kaydediliyor)
DispatchQueue.global().async { [weak self] in
uploadAnalyticsData()
self?.endBackgroundTask()
}
}
private func endBackgroundTask() {
guard backgroundTaskID != .invalid else { return }
UIApplication.shared.endBackgroundTask(backgroundTaskID)
backgroundTaskID = .invalid
}
// BGTaskScheduler kaydı
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)
}
}
}Kod, iOS'te tam Background işlemesini gösterir. applicationDidEnterBackground, zaman aşımı ve expirationHandler ile beginBackgroundTask aracılığıyla bir arka plan görevi başlatır. Aynı anda, BGTaskScheduler periyodik içerik güncellemeleri için kaydedilir. beginBackgroundTask acil kapatma görevleri için kullanılır, BGTaskScheduler uzun vadeli planlama için kullanılır. Her iki API de görev tanımlayıcılarının doğru yönetimini gerektirir.
Android'de, Background birkaç API aracılığıyla yönetilir. Geleneksel Service, arka planda kod çalıştırmaya izin verir, ancak Android 8+'dan (API 26) itibaren Background Service sınırlıdır: sistem, uygulama arka plana gittikten birkaç dakika sonra onu sonlandırır. Kalıcı bildirimli bir Foreground Service süresiz çalışabilir. WorkManager, cihaz yeniden başlatmasından sonra bile yürütme garantisi ile arka plan görevleri için önerilen çözümdür.
Android, iOS'in aksine, uzun süreli arka plan işlemlerini destekler. Foreground Service, kullanıcının görmesi gereken görevler (müzik çalma, navigasyon, egzersiz takibi) için kullanılır. JobScheduler ve WorkManager, ertelenebilecek görevler (veri senkronizasyonu, günlük yükleme, önbellek güncelleme) için kullanılır. Temel fark: Android, koşullarla (Wi-Fi, şarj, cihaz boşta) görev planlamaya izin verir — bu da pil ve trafik tasarrufu sağlar.
import android.app.Service
import android.content.Intent
import android.os.IBinder
import androidx.work.*
// 1. Uzun süreli arka plan çalışması için 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 {
// Sunucu ile veri senkronizasyonu
syncDataToServer()
stopForeground(STOP_FOREGROUND_REMOVE)
stopSelf()
}.start()
}
override fun onBind(intent: Intent?): IBinder? = null
}
// 2. Ertelenmiş arka plan görevleri için WorkManager
class DataSyncWorker(
private val context: Context,
private val params: WorkerParameters
) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
return try {
// Sunucuya analiz yükleme
uploadAnalytics()
Result.success()
} catch (e: Exception) {
if (runAttemptCount < 3) Result.retry() else Result.failure()
}
}
}
// WorkManager görev planlaması
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)
}Kod, Android'de arka plan çalışmasına iki yaklaşımı gösterir. SyncService — acil ve uzun süreli arka plan çalışması için bildirimli Foreground Service. DataSyncWorker — koşullarla (Wi-Fi, şarj) ertelenmiş görevler için WorkManager. WorkManager, cihaz yeniden başlatmasından sonra bile yürütmeyi garanti eder ve yeniden denemeler için üstel geri alma desteği sunar. Foreground Service, durum çubuğunda kalıcı bir bildirim gerektirir.
Her iki mobil platform da sürekli olarak arka plan çalışma kurallarını sıkılaştırıyor. iOS'te, işletim sisteminin her yeni nesli arka plan yürütme süresini azaltır ve yeni kısıtlamalar ekler. Android'de, Google giderek daha katı güç tasarrufu modları (Doze, App Standby) getiriyor. Geliştiriciler mevcut kısıtlamalardan haberdar olmalıdır, aksi takdirde uygulama sistem tarafından erken sonlandırılabilir.
iOS'te, iOS 13'ten başlayarak, sistem arka plan süresini kötüye kullanan uygulamalar için arka plan görevlerini devre dışı bırakır. Her uygulama, kullanıcı davranışına göre belirli sınırlar alır. BGTaskScheduler yürütmeyi en uygun zamanlarda planlar — örneğin, cihaz Wi-Fi'ye bağlıyken ve şarj olurken. BGTaskScheduler'ı doğru kullanan uygulamalar daha fazla arka plan süresi alır.
Android'de, Android 9'dan (API 28) başlayarak, arka plan çalışması, cihaz boştayken etkinleşen Doze modu tarafından kısıtlanır. Doze durumundaki uygulamalar arka plan görevlerini gerçekleştiremez, ağ bağlantısı kesilir, JobScheduler ve WorkManager, Doze'den çıkana kadar görevleri erteler. Foreground Service, Doze'yi atlamanın tek yoludur, ancak kötüye kullanım, uygulamanın kullanıcı tarafından engellenmesine ve izinlerin iptal edilmesine yol açar.
| Kısıtlama | iOS | Android |
|---|---|---|
| Arka plan görev zaman aşımı | ~30 saniye (beginBackgroundTask) | Birkaç dakika (JobScheduler) |
| Sınırsız arka plan | Ses, VoIP, navigasyon, Bluetooth | Foreground Service + bildirim |
| Güç tasarrufu | Low Power Mode — arka plan görevlerini devre dışı bırakır | Doze, App Standby, Pil Optimizasyonu |
| Planlama | BGTaskScheduler (iOS 13+) | WorkManager (Android Jetpack) |
| Yeniden başlatmadan sonra | Yalnızca push bildirimi | WorkManager görevleri korur |
| Maksimum yürütme süresi | ~30 dakika (ses) | Sınırsız (Foreground Service) |
Birinci kural — arka planda kaynak tüketimini en aza indirin. Çoğu arka plan görevi, cihaz şarj olurken ve Wi-Fi'ye bağlıyken ertelenebilir. Koşullu görev planlaması için BGTaskScheduler (iOS) ve WorkManager (Android) kullanın. Arka planda ağır hesaplamalar çalıştırmayın — bu pili tüketir ve CPU kısıtlamasına yol açar.
İkinci kural — beginBackgroundTask için her zaman bir expirationHandler belirtin. Uygulama, ayrılan süre içinde görevi tamamlamazsa, sistem onu zorla Suspended'e geçirir veya sonlandırır. ExpirationHandler, verileri kaydetmek ve işi doğru şekilde bitirmek için son şanstır. Android'de, WorkManager'de setForegroundAsync kullanın daha fazla süre gerekiyorsa normal bir görevi ön plana dönüştürmek için.
Üçüncü kural — başlatmadan önce arka plan çalışma kısıtlamalarını kontrol edin. iOS'te, kalan süreyi kontrol etmek için UIApplication.shared.backgroundTimeRemaining kullanın. Android'de, ActivityManager.isBackgroundRestricted() kontrol edin — true ise, uygulama arka plan görevlerini çalıştıramaz ve kullanıcıya ayarlardan kısıtlamaları kaldırmasını önermelisiniz. Bu, kritik arka plan işlevlerine sahip uygulamalar için özellikle önemlidir — alarmlar, takvimler, senkronizasyon.
Dördüncü kural — arka plan görevlerini gerçek bir cihazda test edin. Simülatörler ve emülatörler gerçek arka plan çalışma kısıtlamalarını yeniden üretmez. iOS'te, Xcode'da Debug → Simulate Background Fetch kullanın. Android'de, yeniden başlatmadan sonra WorkManager'ı test etmek için adb shell am broadcast -a android.intent.action.ACTION_BOOT_COMPLETED kullanın. Düşük pilli bir cihazda gerçek testler çoğu arka plan çalışma sorununu ortaya çıkarır.
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("Arka planda kalan süre: \(remaining) sn")
let task = UIApplication.shared.beginBackgroundTask { [weak self] in
print("Görev için süre doldu: \(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)
}
}Kod, kalan süreyi izleyen ve tanımlayıcıları yöneten bir arka plan görev yöneticisini gösterir. backgroundTimeRemaining, zorla sonlandırmadan önceki saniye sayısını döndürür — değer sonsuzsa, uygulama kısıtlama olmadan çalışıyordur (ses, navigasyon). Yönetici, farklı adlarla birden çok arka plan görevi başlatmaya ve her birini doğru şekilde tamamlamaya olanak tanır. Bu yaklaşım, arka plan görev sızıntılarını önler ve sistemin kapatılmamış görevler nedeniyle uygulamayı sonlandırmamasını sağlar.
Sıkça Sorulan Sorular
Evet, sınırlı sayıda kategori için: ses (AVAudioSession kategorisi .playback), VoIP (PushKit), navigasyon (allowsBackgroundLocationUpdates ile CLLocationManager), Bluetooth (merkezi arka plan modu), arka plan güncellemesi (BGTaskScheduler). Diğer tümü için — maksimum 30 saniye. iOS 16+'da Apple, izin verilen kategoriler için bile gereksinimleri sıkılaştırdı.
beginBackgroundTask, arka plana gittikten sonra uygulama ömrünü yaklaşık 30 saniye uzatan senkron bir API'dir. applicationDidEnterBackground içinde çağrılır. BGTaskScheduler, sistem tetikleyicileri (zaman, konum, içerik güncellemesi) aracılığıyla gelecekteki görevleri planlamak için asenkron bir API'dir. BGTaskScheduler, Apple tarafından iOS 13+ için önerilen modern yaklaşımdır.
Android 8'den (API 26) başlayarak, bir Background Service, uygulama arka plana gittikten birkaç dakika sonra sonlandırılır. Çözüm: uzun işlemler için bildirimli Foreground Service veya ertelenmiş görevler için WorkManager kullanın. Ayarlardan uygulamanız için Pil Optimizasyonu'nu kontrol edin — optimize edilmişse, sistem arka plan görevlerini erteleyebilir veya iptal edebilir.
Ana Ekrana gitmek için Cmd+Shift+H tuşlarına basın. Xcode'da Debug → Simulate Background Fetch kullanın. beginBackgroundTask'ı kontrol etmek için konsolu açın (Shift+Cmd+C) ve e UIApplication.shared.backgroundTimeRemaining çağrısını yapın. Xcode 15+'te, simülatörün Diagnostics sekmesinde Background Execution senaryosu mevcuttur.
Process Death, kaynaklar azaldığında veya arka planda boştayken sistem tarafından Android sürecinin sonlandırılmasıdır. iOS'in aksine, Android'de Suspended yoktur — süreç ya canlıdır (arka planda olabilir) ya da ölüdür (Not Running). Process Death, işletim sisteminin normal davranışıdır ve uygulama, sonrasında SavedStateHandle, onSaveInstanceState veya DataStore aracılığıyla durumu doğru şekilde geri yüklemelidir.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun