google / ExoPlayer

This project is deprecated and stale. The latest ExoPlayer code is available in https://github.com/androidx/media
https://developer.android.com/media/media3/exoplayer
Apache License 2.0
21.7k stars 6.02k forks source link

[Cast extension] Support casting while in background #7296

Open stefan-zh opened 4 years ago

stefan-zh commented 4 years ago

[REQUIRED] Searched documentation and issues

https://github.com/google/ExoPlayer/issues/5801

[REQUIRED] Question

I am using ExoPlayer and its Cast extension to play media content on a Chromecast receiver. Using Google's tutorial on how to enable an application for Cast, I found out that when an application goes into the background or is closed completely the remote receiver can continue playback.

The CastPlayer supports a release() method that we need to use when we clean up resources. I use it in onPause/onStop. However, calling this method stops the remote player. I think this behavior is undesired - if we go into lock screen, the remote player should continue.

A solution would be to not call release(). Then when I disconnect from the Cast receiver on my phone from the notifications or lock screen, the remote player stops, and CastPlayer continues from my phone playing sound. I imagine this is due to not releasing the CastPlayer. Then I restart the phone to clean up the dangling resources.

I looked up the issue above and the OP says that they found what to do and the issue can be closed. It remains unclear what was done or what the ExoPlayer developers would suggest as a workaround.

A full bug report captured from the device

[none]

Link to test content

[none]

AquilesCanta commented 4 years ago

When the decision to close the connection on release was made, I think we were following Cast's framework best practices. I'll revisit this decision and reach back with either a change or an explanation. What I can tell you is that the current CastPlayer implementation would not gracefully pick up the receiver app's state when transitioning back to foreground, which we need to fix before your desired usecase is supported.

PiotrMuciek commented 4 years ago

Any updates on this issue? I have similar problem while using ExoPlayer Cast extension. Playback on cast receiver should continue when sender app goes to background. If i release CastPlayer in onStop method playback on Cast receiver app stops. It is not a desired situation and it does not follow best practices .

An easy solution would be to modify release() method of CastPlayer and remove invocation of sessionManager.endCurrentSession(false);

AquilesCanta commented 4 years ago

Sorry for the delay on this, I haven't been able to invest time in the cast extension lately, unfortunately.

The issue here is that the activity has ownership of the CastPlayer instance. In order for the ownership model to work well, my advise is that you move away from what the demo app is doing and use a foreground service instead. So, when the cast session starts, you can transition to a Service-owned CastPlayer, which lives when the activity goes to the background. The UAMP project does something like this (although also ExoPlayer lives in the Service, perhaps not exactly what you want). I think we could use this Service model in the cast demo app, as an enhancement. I don't think I agree with the idea of having a Cast session which has no Player owner.

Stonos commented 4 years ago

I'm also facing the same issue, and I agree with @Muman that the easiest solution seems to be the removal of the call to endCurrentSession when calling CastPlayer.release().

Is there any reason to keep the same instance of CastPlayer? Why not release the CastPlayer when the app goes in the background, and create a new CastPlayer instance when it comes to the foreground?

Using a foreground service to keep the CastPlayer instance alive seems to have several disadvantages:

adrientetar commented 3 years ago

@AquilesCanta, I have a media view where you can swipe between different media files in a folder (video, photo, music), the current release() implementation force closing the session when the user swipes to a different file and the previous fragment is destroyed. Can we add a boolean parameter closeSession (default to true) in the release method?

AquilesCanta commented 3 years ago

implementation force closing the session when the user swipes to a different file and the previous fragment is destroyed

I would advise against the fragment owning the cast player. You might still want the fragment to use ExoPlayer and have ExoPlayer be released when swiping away from the fragment. But in your case, perhaps the CastPlayer should be owned by something that outlives the fragment (the activity? A service?).

I don't think we will go ahead with the change of not closing the cast connection on release until we manage to make CastPlayer be able to pick up its state from an ongoing cast session (in other words, CastPlayer is released without closing the session, and then a new CastPlayer is created which picks us its player state from the existing session).

Stonos commented 3 years ago

I'm using my own version of CastPlayer where I have removed the call to endCurrentSession when calling release and restoring the session seems to be working mostly* fine (i.e. the PlayerView shows correctly the position/duration of the media that's being cast). Is there anything else that needs to be done?

*Sometimes I have to pause and & unpause the video in order for the position/duration to become populated, but it works fine afterwards.

AquilesCanta commented 3 years ago

We need to rebuild the timeline and any other state that may be missing. Of course, we need to have the position/duration work correctly too.