Add flag to `onPlaybackResumption` to indicate whether playback should be started or not.
Use case description
MediaLibrarySessionCallback's onPlaybackResumption is called from MediaSession.handleMediaControllerPlayRequest to handle incoming play requests from MediaControllers, or from MediaLibrarySession.getRecentMediaItemAtDeviceBootTime to populate the media notification at boot time. While the former should end up with playback (or else resulting in a ForegroundServiceDidNotStartInTimeException), the latter should never explicitly call playback to avoid playing content upon device reboot.
Although for simpler cases media3 can handle this situation internally, for more complex cases where playback can't be resolved by merely returning a list of MediaItems in onPlaybackResumption, it would be useful to have a way to determine within this function whether the call should result in playback or not.
Proposed solution
onPlaybackResumption may have an extra boolean parameter to indicate this situation, or the incoming controller info might contain an indication that the request is coming from MediaLibrary to populate the last media sesion within the OS.
Alternatives considered
I currently inspect the call stack to reach this conclusion but this is hacky and far from ideal.
Thanks for the suggestion!
for more complex cases where playback can't be resolved by merely returning a list of MediaItems in onPlaybackResumption
Not sure if that's already clear, but onPlaybackResumption returns a ListenableFuture. This means you can create for example a SettableFuture that can be resolve asynchronously, whenever you are ready. Does that already help with your integration. If not, it might be interesting to know how the logic differs assuming you have enough time to resolve the item that should be used for playback resumption.
Thanks for the suggestion!
for more complex cases where playback can't be resolved by merely returning a list of MediaItems in onPlaybackResumption
Not sure if that's already clear, but
onPlaybackResumptionreturns aListenableFuture. This means you can create for example aSettableFuturethat can be resolve asynchronously, whenever you are ready. Does that already help with your integration. If not, it might be interesting to know how the logic differs assuming you have enough time to resolve the item that should be used for playback resumption.
Yes I am aware but I dont have a straight pipeline where i can just retrieve items from an endpoint and transform them into MediaItems. I have multiple stacked calls dependant on each other, with custom DRM in between, expiring urls, etc. so although technically it would be possible to amend my current pipeline to adjust to just returning the items rather than directly sending them to the player, I'd rather keep things in a single place and just tell my pipeline "hey, just start playing the last song" than duplicating the track resolution (or amending my reactive streams) just for playback resumption. In other words I'd rather handle playback myself.
Yes, that makes sense. Sorry to keep asking, but I'm still curious about how you handle the difference. This may be relevant in case there is a good alternative approach already or at least for us to understand how you'd like to use the method.
Could you clarify exactly what you are returning from the method in both cases? Especially to support the "get the metadata after boot" case, I guess you still need to return something useful? Would a good pseudo code for your current logic be something like this?
onPlaybackResumption() {
if (getMetadataAfterBootCase()) {
return generatePlaceholderMediaItemForStoredMetadata();
} else /* actual resumption case */ {
triggerAppSpecificPlaybackLogicToStartLastSong();
return // error/empty list/placeholderMediaItem/something else? Please clarify :)
}
}
Something like
onPlaybackResumption() {
val isFromBoot = getMetadataAfterBootCase()
triggerAppSpecificPlaybackLogicToStartLastSong(triggerPlayback = isFromBoot);
return settableFuture that never gets set
}
}
Thanks, so just to clarify again - you don't intend to support the isFromBoot case at all? I was under the impression this works only when you return a successful future from this method.
Im not sure i can even support that with my current setup, but I haven been able to get the OS to call that method upon device restart...
Would the fact that my app creates a media session not already populate such notification anyway?
I have another usecase that needs pretty much the same information; I save the current shuffle order to disk so that when a user reopens the app and had shuffle enabled, the order still is the same. setShuffleOrder() requires the playlist to already be set (so that media item count is the same), and hence, restoring the shuffle order in onPlaybackResumption() is a weird awkward mess because I need to make sure the future callback (that sets the playlist) is done, which is easier to make assumptions about if I know it's going to be set at all.