From 9e238eb6d365e76b20e39147aeae5091ea4451ee Mon Sep 17 00:00:00 2001 From: bachinger Date: Tue, 3 Dec 2019 16:05:27 +0000 Subject: [PATCH] MediaSessionConnector: Support ACTION_SET_CAPTIONING_ENABLED PiperOrigin-RevId: 283546707 --- RELEASENOTES.md | 2 + .../mediasession/MediaSessionConnector.java | 54 +++++++++++++++++-- 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index d0ae1a3b5a..1911d32cdd 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -131,6 +131,8 @@ of the extension after this change, following the instructions in the extension's readme. * Opus extension: Update to use NDK r20. +* MediaSession extension: Make media session connector dispatch + `ACTION_SET_CAPTIONING_ENABLED`. * GVR extension: This extension is now deprecated. * Demo apps (TODO: update links to point to r2.11.0 tag): * Add [SurfaceControl demo app](https://github.com/google/ExoPlayer/tree/dev-v2/demos/surface) diff --git a/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.java b/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.java index 84d5fea0c7..5382e286a1 100644 --- a/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.java +++ b/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.java @@ -339,6 +339,21 @@ public final class MediaSessionConnector { void onSetRating(Player player, RatingCompat rating, Bundle extras); } + /** Handles requests for enabling or disabling captions. */ + public interface CaptionCallback extends CommandReceiver { + + /** See {@link MediaSessionCompat.Callback#onSetCaptioningEnabled(boolean)}. */ + void onSetCaptioningEnabled(Player player, boolean enabled); + + /** + * Returns whether the media currently being played has captions. + * + *

This method is called each time the media session playback state needs to be updated and + * published upon a player state change. + */ + boolean hasCaptions(Player player); + } + /** Handles a media button event. */ public interface MediaButtonEventHandler { /** @@ -420,6 +435,7 @@ public final class MediaSessionConnector { @Nullable private QueueNavigator queueNavigator; @Nullable private QueueEditor queueEditor; @Nullable private RatingCallback ratingCallback; + @Nullable private CaptionCallback captionCallback; @Nullable private MediaButtonEventHandler mediaButtonEventHandler; private long enabledPlaybackActions; @@ -606,7 +622,7 @@ public final class MediaSessionConnector { * * @param ratingCallback The rating callback. */ - public void setRatingCallback(RatingCallback ratingCallback) { + public void setRatingCallback(@Nullable RatingCallback ratingCallback) { if (this.ratingCallback != ratingCallback) { unregisterCommandReceiver(this.ratingCallback); this.ratingCallback = ratingCallback; @@ -614,6 +630,19 @@ public final class MediaSessionConnector { } } + /** + * Sets the {@link CaptionCallback} to handle requests to enable or disable captions. + * + * @param captionCallback The caption callback. + */ + public void setCaptionCallback(@Nullable CaptionCallback captionCallback) { + if (this.captionCallback != captionCallback) { + unregisterCommandReceiver(this.captionCallback); + this.captionCallback = captionCallback; + registerCommandReceiver(this.captionCallback); + } + } + /** * Sets a custom error on the session. * @@ -843,12 +872,14 @@ public final class MediaSessionConnector { boolean enableRewind = false; boolean enableFastForward = false; boolean enableSetRating = false; + boolean enableSetCaptioningEnabled = false; Timeline timeline = player.getCurrentTimeline(); if (!timeline.isEmpty() && !player.isPlayingAd()) { enableSeeking = player.isCurrentWindowSeekable(); enableRewind = enableSeeking && rewindMs > 0; enableFastForward = enableSeeking && fastForwardMs > 0; - enableSetRating = true; + enableSetRating = ratingCallback != null; + enableSetCaptioningEnabled = captionCallback != null && captionCallback.hasCaptions(player); } long playbackActions = BASE_PLAYBACK_ACTIONS; @@ -868,9 +899,12 @@ public final class MediaSessionConnector { actions |= (QueueNavigator.ACTIONS & queueNavigator.getSupportedQueueNavigatorActions(player)); } - if (ratingCallback != null && enableSetRating) { + if (enableSetRating) { actions |= PlaybackStateCompat.ACTION_SET_RATING; } + if (enableSetCaptioningEnabled) { + actions |= PlaybackStateCompat.ACTION_SET_CAPTIONING_ENABLED; + } return actions; } @@ -901,6 +935,13 @@ public final class MediaSessionConnector { return player != null && ratingCallback != null; } + @EnsuresNonNullIf( + result = true, + expression = {"player", "captionCallback"}) + private boolean canDispatchSetCaptioningEnabled() { + return player != null && captionCallback != null; + } + @EnsuresNonNullIf( result = true, expression = {"player", "queueEditor"}) @@ -1353,6 +1394,13 @@ public final class MediaSessionConnector { } } + @Override + public void onSetCaptioningEnabled(boolean enabled) { + if (canDispatchSetCaptioningEnabled()) { + captionCallback.onSetCaptioningEnabled(player, enabled); + } + } + @Override public boolean onMediaButtonEvent(Intent mediaButtonEvent) { boolean isHandled =