This repository is no longer maintained or consumed. As of 2026-09-10 the player source was
vendored into the losikov/react-native-track-player fork
(branch dev-android-auto-turbo-media3, android/src/main/java/com/doublesymmetry/kotlinaudio/)
and is being migrated there from ExoPlayer 2.19.1 to AndroidX Media3. The JitPack artifact built
from this repo (last pin: c98a0dd28492489b3ad52bf431312e79e2f096ab) stays available for rollback
only. Do not open PRs or push fixes here; make them in the RNTP fork.
KotlinAudio is an Android audio player written in Kotlin, making it simpler to work with audio playback from streams and files.
Inspired by SwiftAudioEx. Our aim is to have feature parity with the iOS equivalent.
Blaze sponsors KotlinAudio by providing super fast Apple Silicon based macOS Github Action Runners. Use the discount code RNTP50 at checkout to get 50% off your first year.
To see the audio player in action, run the example project! To run the example project, clone the repo, then open in Android Studio. Choose "kotlin-audio-example" in the run target and run it in a simulator (or on an actual device).
minSDK 21
implementation 'com.github.doublesymmetry:kotlinaudio:v2.0.0'To get started playing some audio:
let player = AudioPlayer()
let audioItem = DefaultAudioItem(audioUrl: "someUrl", type: MediaType.DEFAULT)
player.load(item: audioItem, playWhenReady: true) // Load the item and start playing when the player is ready.To listen for events in the AudioPlayer, subscribe to events found in the event property of the AudioPlayer.
To subscribe to an event:
// jetpack compose
val state = player.event.stateChange.collectAsState(initial = AudioPlayerState.IDLE)
// normal
player.event.stateChange.collect {}The QueuedAudioPlayer is a subclass of AudioPlayer that maintains a queue of audio tracks.
let player = QueuedAudioPlayer()
let audioItem = DefaultAudioItem(audioUrl: "someUrl", type: MediaType.DEFAULT)
player.add(item: audioItem, playWhenReady: true) // Since this is the first item, we can supply playWhenReady: true to immedietaly start playing when the item is loaded.When a track is done playing, the player will load the next track and update the queue.
All AudioItems are stored in either previousItems or nextItems, which refers to items that come prior to the currentItem and after, respectively. The queue is navigated with:
player.next() // Increments the queue, and loads the next item.
player.previous() // Decrements the queue, and loads the previous item.
player.jumpToItem(index:) // Jumps to a certain item and loads that item. player.remove(index:) // Remove a specific item from the queue.
player.removeUpcomingItems() // Remove all items in nextItems.Instrumented tests need a running emulator or device:
./gradlew :kotlin-audio:connectedDebugAndroidTest
# one class:
./gradlew :kotlin-audio:connectedDebugAndroidTest \
-Pandroid.testInstrumentationRunnerArguments.class=com.doublesymmetry.kotlinaudio.CbrMp3SeekAccuracyTestCbrMp3SeekAccuracyTest guards the constant-bitrate MP3 seeking in
players/components/CbrMp3Extractor.kt. It plays a committed 5-minute CBR fixture through the same
extractor stack BaseAudioPlayer uses, with a DataSource.Factory that records every byte offset
requested, and asserts each seek fetches within one MPEG frame of firstAudioFrame + t * bitrate / 8.
Measured on an API 30 emulator: within 33–309 bytes with the extractor, and up to 25465 bytes
(1.59 s of audio) without it.
Two notes on the build, both fixed here rather than worked around in the tests:
com.android.tools:r8:8.2.42is pinned on the buildscript classpath. The D8 that ships with AGP 7.3.1 refuses to dex aPermittedSubclassesattribute ("Sealed classes are not supported as program classes"), which Kotlin 1.7.10 atjvmTarget = 17emits for everysealed classinmodels/— so this project could not dex its own library for instrumentation. Nothing about the published AAR changes; itsclasses.jaris dexed by the consuming app.AudioPlayerTestandQueuedAudioPlayerTestnow pass amediaSessionCallback(utils/NoopMediaSessionCallback). They had not been updated when the argument became required, and the wholeandroidTestsource set failed to compile without it.
KotinAudio is available under the MIT license. See the LICENSE file for more info.