Documentation Index
Fetch the complete documentation index at: https://mintlify.com/AmolPardeshi99/android-performance-skills/llms.txt
Use this file to discover all available pages before exploring further.
Android Services and JobService components run their lifecycle callbacks on the main thread. Any blocking work in onStartCommand, onCreate, or onStartJob can trigger an ANR — and on Android 14+, JobService violations now produce explicit ANR reports.
ANR Timeout Reference
| Service callback | ANR timeout |
|---|
Service.onCreate | ~20 seconds |
Service.onStartCommand | ~20 seconds |
Service.onBind | ~20 seconds |
startForegroundService without startForeground | 5 s (Android 8–14) / 3 s (Android 15+) |
JobService.onStartJob | few seconds (Android 14+, explicit ANR) |
JobService.onStopJob | few seconds (Android 14+, explicit ANR) |
Service Lifecycle ANRs
The most common Service ANR pattern is performing I/O or network work directly inside onStartCommand. Because this method runs on the main thread, any blocking call holds the entire UI pipeline.
Bad: blocking download in onStartCommand
// ❌ ANR: long-running blocking work in onStartCommand (Main thread)
class DownloadService : Service() {
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
downloadFile(intent?.getStringExtra("url")) // blocks Main → ANR at ~20s
return START_NOT_STICKY
}
}
Correct: dispatch to a background coroutine
Return from onStartCommand immediately, dispatch all work to a coroutine on Dispatchers.IO, and call stopSelf(startId) when done so the Service does not linger.
// ✅ CORRECT: dispatch to background; stop self when done
class DownloadService : Service() {
private val serviceScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val url = intent?.getStringExtra("url") ?: return START_NOT_STICKY
serviceScope.launch {
try { downloadFile(url) }
finally { stopSelf(startId) }
}
return START_NOT_STICKY
}
override fun onDestroy() { serviceScope.cancel() }
}
On Android 15 (API 35+), startForegroundService requires a call to startForeground within 3 seconds of onStartCommand — down from 5 seconds on Android 8–14. Failure to call it within that window produces an ANR and a ForegroundServiceDidNotStartInTimeException. Call startForeground as the very first statement in onStartCommand.
// Android 8+: startForegroundService must call startForeground within 5 seconds (3s on Android 15+)
class ForegroundDownloadService : Service() {
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
startForeground(NOTIF_ID, buildNotification()) // MUST be called immediately — 3s limit on API 35+
// ... dispatch work
return START_NOT_STICKY
}
}
JobService ANR (Android 14+)
Before Android 14, a JobService that blocked in onStartJob or onStopJob would silently miss its deadline. Starting with Android 14 (API 34), these violations produce explicit ANR reports with the description "No response to onStartJob", surfaced in Android Vitals and ApplicationExitInfo.
Bad: blocking work in onStartJob
// ❌ BAD: blocking work in onStartJob (Main thread)
class SyncJobService : JobService() {
override fun onStartJob(params: JobParameters): Boolean {
syncData() // blocking on Main → ANR on Android 14+
return false
}
}
Correct: return true, launch a coroutine, call jobFinished when done
Returning true from onStartJob tells the system that work is ongoing. The system will not fire an ANR as long as your coroutine eventually calls jobFinished. In onStopJob, cancel the scope and return true to request rescheduling.
// ✅ CORRECT: dispatch async; call jobFinished when done
class SyncJobService : JobService() {
private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
override fun onStartJob(params: JobParameters): Boolean {
scope.launch {
syncData()
jobFinished(params, false) // false = no reschedule
}
return true // true = work is ongoing; system won't ANR
}
override fun onStopJob(params: JobParameters): Boolean {
scope.cancel()
return true // true = reschedule
}
}