Skip to content

ForegroundServiceDidNotStartInTimeException when playing from app widgets #2933

@mardous

Description

@mardous

Version

Media3 main branch

More version details

No response

Description of the bug

First, I'm sorry if this is something silly or has already been reported and fixed, but so far I've already reviewed all the related issues, and they appear to be caused by completely different situations, so they won't help resolve our problem. Furthermore, there's another one that might be more related, but it hasn't been active for a long time.

Said that, our app was recently migrated to Media3 from the old Media framework. One of its long-standing features has been the ability to resume playback from widgets on the home screen. This means that if the app is completely closed, pressing any button on the widget should cause the app to load the queue and all previous states and resume playback. This worked well until the migration to Media3. Now, even though the app starts playing, for some reason Media3 doesn't display the media notification, and the app stops after a few seconds. This bug has been reported by a large number of users recently, so we doubt it's specific to a particular Android version or manufacturer.

This is how our code looks:

MusicAppWidget:

private fun RemoteViews.setupButtons(context: Context) {
    val action = Intent(context, MainActivity::class.java)
        .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP)

    val pendingIntent = PendingIntent.getActivity(context, 0, action, PendingIntent.FLAG_IMMUTABLE)
    setOnClickPendingIntent(R.id.image, pendingIntent)
    setOnClickPendingIntent(R.id.media_titles, pendingIntent)

    setButtonAction(context, R.id.button_prev, PlaybackService.ACTION_PREVIOUS)
    setButtonAction(context, R.id.button_next, PlaybackService.ACTION_NEXT)
    setButtonAction(context, R.id.button_toggle_play_pause, PlaybackService.ACTION_TOGGLE_PAUSE)
}

private fun RemoteViews.setButtonAction(context: Context, buttonId: Int, action: String) {
    setOnClickPendingIntent(
        buttonId,
        PendingIntent.getForegroundService(
            context,
            0,
            Intent(context, PlaybackService::class.java).setAction(action),
            PendingIntent.FLAG_IMMUTABLE
        )
    )
}

PlaybackService:

override fun onCreate() {
    super.onCreate()
    // ...

    // Restore playback state (queue, shuffle mode, repeat mode, etc.)
    persistentStorage = PersistentStorage(this, serviceScope, player)
    persistentStorage.restoreState { items, shuffleOrder ->

        // Restoration finished
        player.setMediaItems(items.mediaItems, items.startIndex, items.startPositionMs)
        player.prepare()
        if (player.shuffleModeEnabled && shuffleOrder != null) {
            player.exoPlayer.shuffleOrder = shuffleOrder
        }

        // Process pending commands
        pendingStartCommands.forEach { command -> processCommand(command) }
        pendingStartCommands.clear()
    }

    // ...
}

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
    when (intent?.action) {
        ACTION_NEXT,
        ACTION_PREVIOUS,
        ACTION_TOGGLE_PAUSE -> {
            if (persistentStorage.restorationState.isRestored) {
                processCommand(intent)
            } else {
                pendingStartCommands.add(intent)
            }
            return START_STICKY
        }
    }
    return super.onStartCommand(intent, flags, startId)
}

private fun processCommand(command: Intent) {
    when (command.action) {
        ACTION_TOGGLE_PAUSE -> if (isPlaying) {
            player.pause()
        } else {
            player.play()
        }
        ACTION_PREVIOUS -> player.seekToPrevious()
        ACTION_NEXT -> player.seekToNext()
    }
}

Therefore, I'd like to know if Media3 isn't designed for this (resuming playback from home widgets) or if it's a bug in the framework itself. We've made every possible change and run every test, even with Glance, and nothing seems to work.

It's also important to mention that we didn't override any default logic for handling notifications, and all of this has been delegated to Media3 itself as the default behavior.

Devices that reproduce the issue

Any device on which the app is installed

Devices that do not reproduce the issue

No response

Reproducible in the demo app?

No (It doesn't appear to have widgets support)

Reproduction steps

  1. Close the app completely, with no notifications or anything else active.
  2. Add one of the widgets to the home screen.
  3. Tap any of the widget's control buttons.

Expected result

The app starts playing from its last state and displays the media notification.

Actual result

The app starts playing without showing a notification, so the system stops it after a few seconds.

Media

Not applicable

Bug Report

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions