Skip to content
advanced Phase 9 · Background Processing

Foreground Services

Run long-running operations with foreground services and persistent notifications.

45m
2 problems
Topic Progress 0%

When to Use Foreground Services

The Problem with Background Work

Android aggressively restricts background execution to preserve battery life. Apps cannot run long-running operations in the background after the user leaves the app. A foreground service solves this by elevating the process priority and showing a persistent notification.

When a Foreground Service Is Required

Use a foreground service when the user must be aware the app is doing work and the work cannot be interrupted:

  • Music playback — playing audio while the app is in the background
  • GPS tracking — recording location during navigation or fitness tracking
  • File downloads — large downloads that must complete without interruption
  • Data synchronization — ongoing sync with a server
  • Phone calls — VoIP apps maintaining a connection

When NOT to Use a Foreground Service

  • Periodic data refresh — use WorkManager instead
  • One-shot network calls — use coroutines with WorkManager
  • Short processing — WorkManager or JobIntentService

Android Version Restrictions

Version Restriction
Android 8.0+ Background service start限制. Must use startForeground() within 5 seconds
Android 12+ Cannot start foreground services from background unless exempt
Android 14+ TYPE_LOCATION and TYPE_MICROPHONE foreground service types require runtime permissions
// Android 12+: Check if you can start a foreground service
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
    val am = getSystemService<ActivityManager>()
    if (!am?.isForegroundServiceLaunchAllowed) {
        // Show explanation or use WorkManager instead
        return
    }
}

Foreground Service vs WorkManager

Feature Foreground Service WorkManager
User visibility Persistent notification No notification
Duration Indefinite Up to 10 minutes
Process priority Foreground Expedited worker
Use case Music, GPS, calls Sync, upload, cleanup

Implementing Foreground Services

Service Declaration

Register the service in AndroidManifest.xml. For Android 9+, declare the foreground service type.

<service
    android:name=".MusicService"
    android:foregroundServiceType="mediaPlayback"
    android:exported="false" />

Service Implementation

A foreground service must call startForeground() with a notification within 5 seconds of being started, or the system kills the process.

class MusicService : Service() {

    private val binder = MusicBinder()
    private var mediaPlayer: MediaPlayer? = null

    inner class MusicBinder : Binder() {
        fun getService(): MusicService = this@MusicService
    }

    override fun onBind(intent: Intent): IBinder = binder

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        when (intent?.action) {
            ACTION_PLAY -> play(intent.getStringExtra(EXTRA_TRACK_URL))
            ACTION_PAUSE -> pause()
            ACTION_STOP -> stopSelf()
        }
        return START_STICKY  // restart if killed by system
    }

    private fun play(url: String?) {
        url?.let {
            mediaPlayer = MediaPlayer().apply {
                setDataSource(it)
                prepare()
                start()
            }
            startForeground(NOTIFICATION_ID, buildNotification("Playing"))
        }
    }

    private fun pause() {
        mediaPlayer?.pause()
        updateNotification("Paused")
    }

    override fun onDestroy() {
        mediaPlayer?.release()
        mediaPlayer = null
        super.onDestroy()
    }

    private fun buildNotification(text: String): Notification {
        val intent = Intent(this, MainActivity::class.java)
        val pending = PendingIntent.getActivity(
            this, 0, intent, PendingIntent.FLAG_IMMUTABLE
        )

        return NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle("Music Player")
            .setContentText(text)
            .setSmallIcon(R.drawable.ic_music)
            .setContentIntent(pending)
            .build()
    }

    companion object {
        const val NOTIFICATION_ID = 1
        const val CHANNEL_ID = "music_channel"
        const val ACTION_PLAY = "com.example.PLAY"
        const val ACTION_PAUSE = "com.example.PAUSE"
        const val ACTION_STOP = "com.example.STOP"
        const val EXTRA_TRACK_URL = "track_url"
    }
}

Starting the Service

// Start from an Activity or Fragment
val intent = Intent(this, MusicService::class.java).apply {
    action = MusicService.ACTION_PLAY
    putExtra(MusicService.EXTRA_TRACK_URL, trackUrl)
}

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    startForegroundService(intent)
} else {
    startService(intent)
}

Service Lifecycle

  1. CreatedonCreate() called once when service is first created
  2. StartedonStartCommand() called each time startService() is invoked
  3. BoundonBind() called when a client binds via bindService()
  4. DestroyedonDestroy() called when service is stopped

Notification Channels

Android 8.0+ requires a notification channel for foreground service notifications:

fun createNotificationChannel() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val channel = NotificationChannel(
            CHANNEL_ID,
            "Music Playback",
            NotificationManager.IMPORTANCE_LOW
        )
        getSystemService(NotificationManager::class.java)
            .createNotificationChannel(channel)
    }
}

Use IMPORTANCE_LOW so the notification does not make sound or appear on the lock screen — it is just a persistent indicator.

Quiz

1. How long does an Android foreground service have to call startForeground() after being started?

Question 1 options

2. Which foreground service type should a music player use on Android 14+?

Question 2 options

3. What does `START_STICKY` return from `onStartCommand` do?

Question 3 options

4. Why should you use IMPORTANCE_LOW for a foreground service notification channel?

Question 4 options

Flashcards

Question

When must you use a foreground service instead of WorkManager?

Answer

When the user must be aware of ongoing work (persistent notification required) and the work cannot be interrupted or time-boxed — such as music playback, GPS tracking, or VoIP calls.

Question

What happens if a foreground service does not call startForeground() within 5 seconds?

Answer

The system kills the process with an ANR (Application Not Responding) error on Android 8.0+.

Question

What is the difference between startService() and bindService()?

Answer

startService() sends a command to the service; it runs independently of the caller. bindService() creates a connection — the caller can interact with the service through a Binder, and the service stops when all clients unbind.

Question

How do you start a foreground service on Android 8.0+?

Answer

Use startForegroundService(intent) instead of startService(). The service must call startForeground() with a notification within 5 seconds.

Revision Notes

Key Takeaways

  • 1. Foreground services are for long-running, user-visible work that cannot be interrupted
  • 2. startForeground() must be called within 5 seconds or the process is killed
  • 3. Android 12+ restricts foreground service starts from the background — check exemptions
  • 4. Use WorkManager for periodic or deferrable work instead of foreground services

Interview Tips

  • Explain the tradeoff: foreground services keep work alive but drain battery and show notifications
  • Know when to recommend WorkManager over foreground services — interviewers ask this
  • Mention Android version restrictions as a real-world concern
  • Be ready to explain service lifecycle (onStartCommand, onBind, onDestroy)

Cheat Sheet

Foreground Services Cheat Sheet

Use When:

  • User must know about ongoing work
  • Work must not be interrupted
  • Duration is indefinite (music, GPS, calls)

Avoid When:

  • Periodic background work → WorkManager
  • Short network calls → Coroutines

Key Requirements:

  • Call startForeground() within 5 seconds
  • Show a persistent notification
  • Declare foregroundServiceType in manifest
  • Android 14+: Runtime permissions for location/mic types

Service Lifecycle:

  • onCreate → onStartCommand → onDestroy
  • onBind for bound services
  • START_STICKY: restart after killed

Notification Channels:

  • Create with IMPORTANCE_LOW
  • No sound or lock screen — just an indicator

Android 12+ Restrictions:

  • Cannot start from background unless exempt
  • Use isForegroundServiceLaunchAllowed to check