Audio player
Quickplay Player supports audio playback, providing a seamless listening experience. It includes background playback, playlist, offline playback, and Android Auto support.
Setup
Complete the following steps to enable audio playback functionality.
- Add the following permissions and service to your AndroidManifest.xml:
<manifest>
<!-- Add the necessary permissions -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<service
android:name=".AudioBrowserService"
android:enabled="true"
android:exported="true"
android:foregroundServiceType="mediaPlayback">
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService"/>
</intent-filter>
</service>
</manifest>
- Start the audio player service at application launch, as it's required for the service to be initialized and ready.
AudioControllerAdapter.getInstance()
Create the audio player
To build an audio player, you need a mediaPlaylistItem. Adding MediaMetadata lets the Android system display the current track information on the lock screen.
//Create Playback Properties Builder
val playbackPropertiesBuilder: PlaybackProperties.Builder = PlaybackProperties.Builder()
//Create media Media data builder
var mediaMetadataBuilder = MediaMetadata.Builder()
.putString(MediaMetadata.METADATA_KEY_DISPLAY_ICON_URI, IMAGE_URL)
.putString(MediaMetadata.METADATA_KEY_MEDIA_ID, mediaID)
//Create media Meta data
val mediaMetadata = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mediaMetadataBuilder
.putString(MediaMetadata.METADATA_KEY_MEDIA_URI, playbackItem.contentURL)
.build()
} else {
mediaMetadataBuilder.build()
}
//Create media Playlist Item
val mediaPlaylistItem = MediaPlaylistItem.Builder(
MediaPlaylistItem.BaseConfiguration(
playbackItem.contentURL,
mediaType, // MediaType.OTHER, MediaType.DASH etc.,.
mediaID,
mediaMetadata
)
).build()
//Create audio player
val audioPlayer = AudioPlayerServiceBuilder()
.playbackProperties(playbackProperties) //Configures [PlaybackProperties] to apply for playback customization/optimization.
.logger(logger) //Configures [Logger] used for call tracing.
.mediaPlaylistItem(mediaPlaylistItem) //Adds media item to the builder
.build() //This will return core audio player
The audio player is created with a single media item. You can listen to events such as changes in player state, buffering state, seek state, and playback errors by registering a listener or delegate.
If your audio player requires heartbeat tracking, bookmarking, or stream concurrency management, it must be a ComposablePlayer:
player = composablePlayerWith(audioPlayer)
// Adding a lister to listen the heartbeat tracking, bookmarking, or stream concurrency management
player.addListener(this)
Start playback
The Player supports the following control operations:
- play - Play paused or loaded content.
- pause - Pause playing content.
- seek - Seek content to a specified position in the playback window.
Stop and abort
- Invoking stop() stops rendering and releases all underlying resources.
- Invoking abort(error: Error) has the same effect as stop(). Additionally, the onError() callback on the attached Player.Listener is invoked.
Offline playback
To play downloaded content, you need to configure the download ID in the player MediaPlaylistItem.
//Create Media Playlist Item
val mediaPlaylistItem = MediaPlaylistItem.Builder(
MediaPlaylistItem.BaseConfiguration(
completedDownload.mediaURL,
completedDownload.MediaType, // Indicates other Media Container formats such as MP4 , WMV etc.
completedDownload.id,
completedDownload.mediaMetadata
)
).build()
mediaPlaylistItem.downloadConfiguration.let {
MediaPlaylistItem.DownloadConfiguration(downloadID)
}
val audioPlayer = AudioPlayerServiceBuilder()
.playbackProperties(playbackProperties) //Configures [PlaybackProperties] to apply for playback customization/optimization.
.logger(logger) //Configures [Logger] used for call tracing.
.mediaPlaylistItem(mediaPlaylistItem) //Adds media item to the builder
.build() //This will return core audio player
//Want to play the downloaded content
audioPlayer.play()
Android Auto
Create service
Create a service that extends AudioBrowserService and declare it in the manifest.
<manifest>
<!-- Add the necessary permissions -->
<!-- According to the intent action, the player control's actions on lock screen and android auto will be enabled/disabled-->
<service
android:name=".<service-created>"
android:enabled="true"
android:exported="true"
android:foregroundServiceType="mediaPlayback">
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService"/>
</intent-filter>
</service>
</manifest>
Define playback actions
The application service extending AudioMediaService must implement all required playback actions. Missing actions may lead to partial or non-functioning controls.
override fun getSupportedPrepareActions(): Long =
PlaybackStateCompat.ACTION_PREPARE_FROM_MEDIA_ID or
PlaybackStateCompat.ACTION_PREPARE_FROM_URI or
PlaybackStateCompat.ACTION_PLAY_FROM_URI or
PlaybackStateCompat.ACTION_PLAY_FROM_MEDIA_ID or
PlaybackStateCompat.ACTION_PREPARE_FROM_SEARCH or
PlaybackStateCompat.ACTION_PLAY_FROM_SEARCH or
PlaybackStateCompat.ACTION_SET_PLAYBACK_SPEED or
PlaybackStateCompat.ACTION_STOP or
PlaybackStateCompat.ACTION_REWIND or
PlaybackStateCompat.ACTION_FAST_FORWARD or
PlaybackStateCompat.ACTION_SKIP_TO_NEXT or
PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS or
PlaybackStateCompat.ACTION_SKIP_TO_QUEUE_ITEM or
PlaybackStateCompat.ACTION_SEEK_TO
Clients extending AudioBrowserService can access currentPlayer of type Exoplayer, mediaSession of type MediaSession, and mediaSessionConnector of type MediaSessionConnector to manage playback, update metadata, or control the media session.
Platform extensions
Android Auto listens to QP Player events for Bookmarks, New Relic monitoring, Conviva analytics, and Playlist callbacks.
//Creating a player
val player =
AudioPlayerServiceBuilder().isPlayerForHeadUnit(true).build()
audioPlayer = composablePlayerWith(player)
//Adding a listener to listen Bookmarks, New Relic monitoring, Conviva analytics, Playlist callbacks
audioPlayer?.addListener(listener)
Handle process cleanup
To prevent memory leaks caused by MediaBrowserService, you must forcefully terminate the process in onTaskRemoved(). This prevents the process from persisting after the user removes the task from Recent Apps.
override fun onTaskRemoved(rootIntent: Intent?) {
android.os.Process.killProcess(android.os.Process.myPid())
}
- Don't set FLAG_STOP_WITH_TASK in the manifest, as it prevents onTaskRemoved() from being triggered.
- This issue is a known Android bug and affects all OS versions.