PlayerState
PlayerState is a Compose state holder for audio playback. It tracks playback state, handles loading, and triggers recomposition when the player state changes.
Basic usage
Create a play button that reacts to state changes:
@Composable
fun AudioPlayer(recording: AudioRecording) {
val playerState = rememberPlayerState(recording)
Button(
onClick = { playerState.toggle() },
enabled = playerState.isReady
) {
Text(
when {
playerState.isPlaying -> "⏸ Pause"
playerState.isFinished -> "🔄 Replay"
else -> "▶️ Play"
}
)
}
}
Load dynamically
Load recordings after the composable is created:
@Composable
fun DynamicPlayer() {
val playerState = rememberPlayerState()
var recording by remember { mutableStateOf<AudioRecording?>(null) }
// Load when recording changes
LaunchedEffect(recording) {
recording?.let { playerState.load(it) }
}
Column {
// Some UI to select/create a recording...
Button(
onClick = { playerState.toggle() },
enabled = playerState.isReady
) {
Text(if (playerState.isPlaying) "Pause" else "Play")
}
}
}
Record then play
Common pattern: record audio, then immediately enable playback:
@Composable
fun RecordAndPlay() {
val recorderState = rememberRecorderState()
val playerState = rememberPlayerState()
// Auto-load recording into player
LaunchedEffect(recorderState.recording) {
recorderState.recording?.let {
playerState.load(it)
}
}
Column {
// Record button
Button(onClick = { recorderState.toggle() }) {
Text(if (recorderState.isRecording) "⏹ Stop" else "🎙 Record")
}
// Play button (only when recording available)
if (recorderState.hasRecording) {
Button(
onClick = { playerState.toggle() },
enabled = playerState.isReady
) {
Text(if (playerState.isPlaying) "⏸ Pause" else "▶️ Play")
}
}
}
}
Error handling
Handle playback errors:
playerState.error?.let { error ->
AlertDialog(
onDismissRequest = { playerState.clearError() },
title = { Text("Playback Error") },
text = { Text(error.message ?: "Unable to play audio") },
confirmButton = {
TextButton(onClick = { playerState.clearError() }) {
Text("OK")
}
}
)
}
Complete example
A full playback UI with state indicators:
@Composable
fun CompletePlayer(recording: AudioRecording) {
val playerState = rememberPlayerState(recording)
Column(
modifier = Modifier.fillMaxWidth().padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
// Status indicator
Text(
text = when {
!playerState.isReady -> "⏳ Loading..."
playerState.isPlaying -> "🔊 Playing"
playerState.isPaused -> "⏸️ Paused"
playerState.isFinished -> "✅ Finished"
else -> "⏹️ Ready"
},
style = MaterialTheme.typography.bodyLarge
)
Spacer(Modifier.height(16.dp))
// Control buttons
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
// Play/Pause
Button(
onClick = { playerState.toggle() },
enabled = playerState.isReady
) {
Text(if (playerState.isPlaying) "⏸" else "▶️")
}
// Stop
Button(
onClick = { playerState.stop() },
enabled = playerState.isPlaying || playerState.isPaused
) {
Text("⏹")
}
}
// Error display
playerState.error?.let { error ->
Spacer(Modifier.height(8.dp))
Text(
text = "⚠️ ${error.message}",
color = MaterialTheme.colorScheme.error
)
}
}
}
API reference
Properties
- isPlaying: Boolean
Currently playing audio.
- isPaused: Boolean
Playback is paused (can resume).
- isReady: Boolean
Audio is loaded and ready to play.
- isFinished: Boolean
Playback has completed.
- recording: AudioRecording?
The currently loaded recording.
- error: AudioError?
Current error, if any.
Methods
- load(recording)
Load an
AudioRecordingfor playback.- play()
Start or resume playback.
- pause()
Pause playback.
- stop()
Stop playback and reset to beginning.
- toggle()
Play if stopped/paused, pause if playing.
- clearError()
Clear the current error state.
Last modified: 13 January 2026