Service's `onStartCommand` getting called repeatedly, indefinately

191 views Asked by At

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?

1

There are 1 answers

0
krtkush On

Turns out I was starting the foreground service twice -

ContextCompat.startForegroundService(this,
                    Intent(applicationContext, this::class.java))
                startForeground(OtherConstants.PODCAST_NOTIFICATION_ID, notification)