I'm trying to run exoplayer in a foreground service (not a MediaBrowserServiceCompat
).
Here is my service -
@AndroidEntryPoint
class PodcastPlayerService: Service() {
@Inject
lateinit var dataSourceFactory: DefaultDataSourceFactory
@Inject
lateinit var exoPlayer: SimpleExoPlayer
lateinit var podcastNotificationManager: PodcastNotificationManager
lateinit var podcast: Podcast
override fun onDestroy() {
super.onDestroy()
exoPlayer.release()
}
override fun onTaskRemoved(rootIntent: Intent?) {
super.onTaskRemoved(rootIntent)
exoPlayer.stop()
exoPlayer.release()
}
override fun onBind(p0: Intent?): IBinder? = null
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.i("Pit stop", "2")
val b = intent!!.getBundleExtra("test")
if (b != null) {
Log.i("Pit stop", "3")
podcast = b.getParcelable<Podcast>(ArgumentKeyAndValues.KEY_PODCAST)!!
}
val mediaSource = buildMediaSource(Uri.parse("https://something.etc/file.mp3"))
if (mediaSource != null) {
exoPlayer.prepare(mediaSource)
exoPlayer.playWhenReady = true
podcastNotificationManager =
PodcastNotificationManager(
this,
PodcastPlayerNotificationListener(this)
)
podcastNotificationManager.showNotification(exoPlayer)
}
return START_STICKY
}
private fun buildMediaSource(uri: Uri): MediaSource? {
return ProgressiveMediaSource.Factory(dataSourceFactory)
.createMediaSource(uri)
}
}
Notification Listener -
class PodcastPlayerNotificationListener(private val podcastPlayerService: PodcastPlayerService):
PlayerNotificationManager.NotificationListener {
override fun onNotificationPosted(
notificationId: Int,
notification: Notification,
ongoing: Boolean) {
super.onNotificationPosted(notificationId, notification, ongoing)
podcastPlayerService.apply {
if(ongoing) {
ContextCompat.startForegroundService(this,
Intent(applicationContext, this::class.java))
startForeground(OtherConstants.PODCAST_NOTIFICATION_ID, notification)
}
}
}
override fun onNotificationCancelled(notificationId: Int, dismissedByUser: Boolean) {
super.onNotificationCancelled(notificationId, dismissedByUser)
podcastPlayerService.apply {
stopForeground(true)
stopSelf()
}
}
}
Podcast Notification Manager -
class PodcastNotificationManager(private val context: Context,
notificationListener: PlayerNotificationManager.NotificationListener) {
private val notificationManager: PlayerNotificationManager
init {
notificationManager = PlayerNotificationManager.createWithNotificationChannel(
context,
OtherConstants.NOTIFICATION_CHANNEL_ID,
R.string.notification_channel_name,
R.string.notification_channel_description,
OtherConstants.PODCAST_NOTIFICATION_ID,
DescriptionAdapter(),
notificationListener
).apply {
setSmallIcon(R.drawable.exo_icon_play)
}
}
fun showNotification(player: Player) {
notificationManager.setPlayer(player)
}
private inner class DescriptionAdapter : PlayerNotificationManager.MediaDescriptionAdapter {
override fun getCurrentContentTitle(player: Player): String {
val window = player.currentWindowIndex
return "Title"
}
override fun getCurrentContentText(player: Player): String? {
val window = player.currentWindowIndex
return "Description"
}
override fun getCurrentLargeIcon(
player: Player,
callback: BitmapCallback
): Bitmap? = null
override fun createCurrentContentIntent(player: Player): PendingIntent? {
val window = player.currentWindowIndex
return null
}
}
}
Here is how I start the service -
val intent = Intent(context, PodcastPlayerService::class.java)
val serviceBundle = Bundle()
serviceBundle.putParcelable("test", podcast)
intent.putExtra(ArgumentKeyAndValues.KEY_PODCAST, serviceBundle)
context?.let { Util.startForegroundService(it, intent) }
However, when I do this onStartCommand
keeps getting called (I'm assuming that the OS keeps killing my service for some reason and START_STICKY
forces it to start again) and nothing happens.
If I place the media, notification manager and listener code in onCreate
the service works fine.
Where am I going wrong?
Turns out I was starting the foreground service twice -