DEV Community

myougaTheAxo
myougaTheAxo

Posted on

Android Foreground Service Guide — Background Processing with Notifications

Foreground Services allow long-running background tasks with visible notifications. Essential for music players, fitness trackers, and navigation apps.

Manifest Setup

Declare foreground service permissions:

<!-- AndroidManifest.xml -->
<manifest>
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />

    <application>
        <service
            android:name=".MusicService"
            android:foregroundServiceType="mediaPlayback" />
    </application>
</manifest>
Enter fullscreen mode Exit fullscreen mode

Basic MusicService Implementation

Create a foreground service:

class MusicService : Service() {
    private val binder = MusicBinder()

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        val notification = createNotification()
        startForeground(NOTIFICATION_ID, notification)
        return START_STICKY
    }

    private fun createNotification(): Notification {
        val channel = NotificationChannel(
            CHANNEL_ID,
            "Music Service",
            NotificationManager.IMPORTANCE_LOW
        )
        (getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager)
            .createNotificationChannel(channel)

        return NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle("Now Playing")
            .setContentText("Song name")
            .setSmallIcon(R.drawable.ic_music)
            .build()
    }

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

    override fun onBind(intent: Intent?): IBinder? = binder
}
Enter fullscreen mode Exit fullscreen mode

Compose Control UI

Start and stop service from Compose:

@Composable
fun MusicControlScreen() {
    val context = LocalContext.current
    var isPlaying by remember { mutableStateOf(false) }

    Column {
        Button(
            onClick = {
                val intent = Intent(context, MusicService::class.java)
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    context.startForegroundService(intent)
                } else {
                    context.startService(intent)
                }
                isPlaying = true
            }
        ) {
            Text("Start Music")
        }

        Button(
            onClick = {
                val intent = Intent(context, MusicService::class.java)
                context.stopService(intent)
                isPlaying = false
            }
        ) {
            Text("Stop Music")
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Permission Launcher

Request runtime permissions:

@Composable
fun PermissionRequest() {
    val permissionLauncher = rememberLauncherForActivityResult(
        ActivityResultContracts.RequestPermission()
    ) { isGranted ->
        if (isGranted) {
            // Permission granted, start service
        }
    }

    Button(
        onClick = {
            permissionLauncher.launch(Manifest.permission.FOREGROUND_SERVICE)
        }
    ) {
        Text("Request Permission")
    }
}
Enter fullscreen mode Exit fullscreen mode

Timer Service with Binder

Long-running background work:

class TimerService : Service() {
    private var timeElapsed = 0
    private var isRunning = false

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        startTimer()
        return START_STICKY
    }

    private fun startTimer() {
        isRunning = true
        viewModelScope.launch {
            while (isRunning) {
                timeElapsed++
                updateNotification()
                delay(1000)
            }
        }
    }

    fun stopTimer() {
        isRunning = false
    }

    inner class TimerBinder : Binder() {
        fun getTimeElapsed(): Int = timeElapsed
    }
}
Enter fullscreen mode Exit fullscreen mode

Android 14+ Service Types

Specify foregroundServiceType for different use cases:

<!-- Camera service -->
<service
    android:name=".CameraService"
    android:foregroundServiceType="camera" />

<!-- Location tracking -->
<service
    android:name=".LocationService"
    android:foregroundServiceType="location" />

<!-- Health/fitness tracking -->
<service
    android:name=".FitnessService"
    android:foregroundServiceType="health" />

<!-- Short jobs (< 1 minute) -->
<service
    android:name=".QuickService"
    android:foregroundServiceType="shortService" />
Enter fullscreen mode Exit fullscreen mode

Foreground Services power critical background features in production apps.

8 Android app templates available: Gumroad

Top comments (0)