Fix fullscreen player requiring two clicks to resume from paused state#4228
Fix fullscreen player requiring two clicks to resume from paused state#4228
Conversation
…tener identity in audio focus callbacks Co-authored-by: CarGuo <10770362+CarGuo@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Fixes a regression where resuming playback in fullscreen after pausing requires two clicks, caused by a previous (non-active) player instance receiving an audio-focus loss callback and pausing the new fullscreen listener.
Changes:
- Add an identity check (
listener == GSYVideoView.this) before pausing ononAudioFocusLoss()to ensure only the active listener reacts. - Add the same identity check for
onAudioFocusLossTransient()to prevent stale callbacks from pausing the fullscreen player. - Add inline comments explaining the fullscreen-switch audio focus edge case.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // 确保只有当前活跃的播放器才响应音频焦点变化 | ||
| // 防止全屏切换时,旧播放器的焦点丢失回调错误地暂停新的全屏播放器 | ||
| GSYMediaPlayerListener listener = getGSYVideoManager().listener(); | ||
| if (listener != null && getGSYVideoManager().isPlaying()) { | ||
| if (listener != null && listener == GSYVideoView.this && getGSYVideoManager().isPlaying()) { | ||
| listener.onVideoPause(); |
There was a problem hiding this comment.
The listener != null && listener == GSYVideoView.this check duplicates the existing isCurrentMediaListener() helper later in this class. Using the helper here would reduce duplication and keep the “current listener” definition consistent in one place.
| if (GSYVideoView.this.mReleaseWhenLossAudio) { | ||
| GSYVideoView.this.releaseVideos(); | ||
| } else { | ||
| // 确保只有当前活跃的播放器才响应音频焦点变化 | ||
| // 防止全屏切换时,旧播放器的焦点丢失回调错误地暂停新的全屏播放器 | ||
| GSYMediaPlayerListener listener = getGSYVideoManager().listener(); | ||
| if (listener != null && getGSYVideoManager().isPlaying()) { | ||
| if (listener != null && listener == GSYVideoView.this && getGSYVideoManager().isPlaying()) { |
There was a problem hiding this comment.
The comment says only the current active player responds to audio focus loss, but when mReleaseWhenLossAudio is true the code calls releaseVideos() without verifying this view is still the current GSYVideoManager listener. If an old (non-active) view instance still receives AUDIOFOCUS_LOSS, it could release the active playback. Consider guarding the release path with the same listener == this / isCurrentMediaListener() check (or adjust the comment to match behavior).
After pausing playback and entering fullscreen, the player required two clicks on the play button to resume — introduced in the "Request audio focus on resume from pause" change.
Root Cause
When the fullscreen player resumes from
CURRENT_STATE_PAUSE, it callsstart()thenrequestAudioFocus(). Since the original player still holds audio focus (not released on pause), Android firesAUDIOFOCUS_LOSS_TRANSIENTon the original player's manager. The callback then calledgetGSYVideoManager().listener().onVideoPause()— butlistener()returns the fullscreen player (now the active listener), immediately re-pausing it.Fix
Add a
listener == GSYVideoView.thisidentity check in bothonAudioFocusLoss()andonAudioFocusLossTransient()so a player only acts on focus loss when it is the current active listener:This preserves correct behavior for all other scenarios (external app interruptions, fullscreen player itself being interrupted) while preventing a stale player's focus-loss callback from pausing its successor.
Original prompt
🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.