I05 — Foreground music service
Build a media playback service with a notification, a media session and a foreground service type. Learn why the notification is mandatory, what the type buys you, and when the system will stop the service.
A foreground service is the platform's answer to "this must keep running". It comes with a notification the user cannot dismiss while the service is foreground, a declared type, and a set of restrictions that are easy to discover only by hitting them.
What you are building#
A service that plays a looping audio file, shows a media notification, and exposes play/pause through
a MediaSession. It declares a foreground service type, starts from a user action, and shuts down
cleanly when playback stops.
Steps#
- Add a notification channel
Create a channel at app startup with a name, a description and an importance. On Android 8.0 and later, a notification without a channel is not shown.1
You should seeThe channel exists before the notification. - Declare the service and its type
Add the service with
android:foregroundServiceType="mediaPlayback"and the matching permission. Since Android 14, a foreground service must declare a type, and the type must match what it does.You should seeThe manifest lists the type. - Build the notification
Use a media style notification with a
MediaSession. The notification is the user's control surface and the platform's evidence that the service is visible.You should seeA notification with a play/pause action. - Start the service from a user action
Start it in response to a button press, not from a background receiver. Background starts are restricted, and a user action is the cleanest way to satisfy the restriction.2
You should seeThe service starts and the notification appears. - Call startForeground
Call
startForegroundwith the notification within the allowed window. A service that starts but never calls it is killed.You should seeThe notification is posted and the service is foreground. - Play audio
Use
MediaPlayeror Media3'sExoPlayerfor the loop. The point is the service lifetime, not the decoder; either works.You should seeAudio plays and continues when the app is backgrounded. - Stop cleanly
On pause or stop, stop the foreground state and stop the service. A service that stays foreground without doing work is a battery complaint and a policy violation.
You should seeThe notification disappears. - Hit the limit deliberately
Try starting the service from a background context and observe the restriction. Then try a type that does not match the work and observe the platform's response. These failures are the actual lesson.
You should seeAn exception or a stopped service.
The service entry point:
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val notification = buildNotification()
startForeground(NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK)
return START_NOT_STICKY
}adb shell dumpsys activity services com.example.musicservice
adb shell dumpsys notification | grep -i -A 5 com.example.musicservice
adb shell am start-foreground-service -n com.example.musicservice/.PlaybackServiceExample output
Illustrative output — package and service names differ.Verification#
Background the app and confirm the audio continues and the notification stays. Then force-stop the app and confirm both stop. The difference is the point: a foreground service survives backgrounding and does not survive a force-stop.
What you learned#
- The notification is the contract. A foreground service is visible by design, and the notification is how the user knows.
- The type is mandatory and semantic. It is not a label; it constrains what the service may do and for how long.
- Background starts are restricted. The supported path is a user action, or a documented exemption.
- Stopping is part of the design. A service that never stops is a bug even when it works.
Read Foreground services for when a foreground service is the right tool, and Notifications for the channel model.
Extend it#
- Add a media session callback so hardware media keys control playback.
- Add a second type for a download that happens alongside playback, and observe the type combination rules.
- Replace the player with Media3 and compare the session and notification plumbing.
Sources#
Sources
Every version number, API level, class name and date on this page is traced to one of these. Pages are re-verified against them; last_verified above says when.
- docsNotifications overviewdeveloper.android.comaccessed 2026-10-27↩
- docsForeground services overview | Background workdeveloper.android.comaccessed 2026-10-27↩
- docsMedia3 overviewdeveloper.android.comaccessed 2026-10-27↩
- docsBehavior changes: Apps targeting Android 13 or higherdeveloper.android.comaccessed 2026-10-27↩
- docsסקירה כללית על תכונות וממשקי APIdeveloper.android.comaccessed 2026-10-27↩
- docsBackground tasks overview | Background workdeveloper.android.comaccessed 2026-10-27↩