mirror of
https://github.com/samsonjs/media.git
synced 2026-04-05 11:15:46 +00:00
Clarify doc of components which only allow a main thread player.
ExoPlayer can be run on a background thread, but some components (UI and IMA) only support players on the main thread. This adds some documentation and assertions for that. To simplify assertions, this also moves the getApplicationLooper method from ExoPlayer to Player. Issue:#4439 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=213280359
This commit is contained in:
parent
c18ee3f96d
commit
585806de24
11 changed files with 65 additions and 21 deletions
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package com.google.android.exoplayer2.ext.cast;
|
||||
|
||||
import android.os.Looper;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
|
|
@ -298,6 +299,11 @@ public final class CastPlayer implements Player {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Looper getApplicationLooper() {
|
||||
return Looper.getMainLooper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(EventListener listener) {
|
||||
listeners.add(listener);
|
||||
|
|
|
|||
|
|
@ -30,7 +30,9 @@ To play ads alongside a single-window content `MediaSource`, prepare the player
|
|||
with an `AdsMediaSource` constructed using an `ImaAdsLoader`, the content
|
||||
`MediaSource` and an overlay `ViewGroup` on top of the player. Pass an ad tag
|
||||
URI from your ad campaign when creating the `ImaAdsLoader`. The IMA
|
||||
documentation includes some [sample ad tags][] for testing.
|
||||
documentation includes some [sample ad tags][] for testing. Note that the IMA
|
||||
extension only supports players which are accessed on the application's main
|
||||
thread.
|
||||
|
||||
Resuming the player after entering the background requires some special handling
|
||||
when playing ads. The player and its media source are released on entering the
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ package com.google.android.exoplayer2.ext.ima;
|
|||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.Looper;
|
||||
import android.os.SystemClock;
|
||||
import android.support.annotation.IntDef;
|
||||
import android.support.annotation.Nullable;
|
||||
|
|
@ -478,6 +479,7 @@ public final class ImaAdsLoader
|
|||
|
||||
@Override
|
||||
public void attachPlayer(ExoPlayer player, EventListener eventListener, ViewGroup adUiViewGroup) {
|
||||
Assertions.checkArgument(player.getApplicationLooper() == Looper.getMainLooper());
|
||||
this.player = player;
|
||||
this.eventListener = eventListener;
|
||||
lastVolumePercentage = 0;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import android.graphics.Bitmap;
|
|||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.ResultReceiver;
|
||||
import android.os.SystemClock;
|
||||
import android.support.annotation.NonNull;
|
||||
|
|
@ -36,6 +37,7 @@ import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
|
|||
import com.google.android.exoplayer2.PlaybackParameters;
|
||||
import com.google.android.exoplayer2.Player;
|
||||
import com.google.android.exoplayer2.Timeline;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
import com.google.android.exoplayer2.util.ErrorMessageProvider;
|
||||
import com.google.android.exoplayer2.util.RepeatModeUtil;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
|
|
@ -367,8 +369,7 @@ public final class MediaSessionConnector {
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates an instance. Must be called on the same thread that is used to construct the player
|
||||
* instances passed to {@link #setPlayer(Player, PlaybackPreparer, CustomActionProvider...)}.
|
||||
* Creates an instance.
|
||||
*
|
||||
* @param mediaSession The {@link MediaSessionCompat} to connect to.
|
||||
* @param playbackController A {@link PlaybackController} for handling playback actions, or {@code
|
||||
|
|
@ -400,15 +401,17 @@ public final class MediaSessionConnector {
|
|||
* <p>The order in which any {@link CustomActionProvider}s are passed determines the order of the
|
||||
* actions published with the playback state of the session.
|
||||
*
|
||||
* @param player The player to be connected to the {@code MediaSession}.
|
||||
* @param player The player to be connected to the {@code MediaSession}, or {@link null} to
|
||||
* disconnect the current player.
|
||||
* @param playbackPreparer An optional {@link PlaybackPreparer} for preparing the player.
|
||||
* @param customActionProviders Optional {@link CustomActionProvider}s to publish and handle
|
||||
* custom actions.
|
||||
*/
|
||||
public void setPlayer(
|
||||
Player player,
|
||||
@Nullable Player player,
|
||||
@Nullable PlaybackPreparer playbackPreparer,
|
||||
CustomActionProvider... customActionProviders) {
|
||||
Assertions.checkArgument(player == null || player.getApplicationLooper() == Looper.myLooper());
|
||||
if (this.player != null) {
|
||||
this.player.removeListener(exoPlayerEventListener);
|
||||
mediaSession.setCallback(null);
|
||||
|
|
|
|||
|
|
@ -89,10 +89,15 @@ import com.google.android.exoplayer2.video.MediaCodecVideoRenderer;
|
|||
* model">
|
||||
*
|
||||
* <ul>
|
||||
* <li>ExoPlayer instances must be accessed from the thread associated with {@link
|
||||
* #getApplicationLooper()}. This Looper can be specified when creating the player, or this is
|
||||
* the Looper of the thread the player is created on, or the Looper of the application's main
|
||||
* thread if the player is created on a thread without Looper.
|
||||
* <li>ExoPlayer instances must be accessed from a single application thread. For the vast
|
||||
* majority of cases this should be the application's main thread. Using the application's
|
||||
* main thread is also a requirement when using ExoPlayer's UI components or the IMA
|
||||
* extension. The thread on which an ExoPlayer instance must be accessed can be explicitly
|
||||
* specified by passing a `Looper` when creating the player. If no `Looper` is specified, then
|
||||
* the `Looper` of the thread that the player is created on is used, or if that thread does
|
||||
* not have a `Looper`, the `Looper` of the application's main thread is used. In all cases
|
||||
* the `Looper` of the thread from which the player must be accessed can be queried using
|
||||
* {@link #getApplicationLooper()}.
|
||||
* <li>Registered listeners are called on the thread associated with {@link
|
||||
* #getApplicationLooper()}. Note that this means registered listeners are called on the same
|
||||
* thread which must be used to access the player.
|
||||
|
|
@ -182,12 +187,6 @@ public interface ExoPlayer extends Player {
|
|||
/** Returns the {@link Looper} associated with the playback thread. */
|
||||
Looper getPlaybackLooper();
|
||||
|
||||
/**
|
||||
* Returns the {@link Looper} associated with the application thread that's used to access the
|
||||
* player and on which player events are received.
|
||||
*/
|
||||
Looper getApplicationLooper();
|
||||
|
||||
/**
|
||||
* Retries a failed or stopped playback. Does nothing if the player has been reset, or if playback
|
||||
* has not failed or been stopped.
|
||||
|
|
|
|||
|
|
@ -529,6 +529,12 @@ public interface Player {
|
|||
@Nullable
|
||||
TextComponent getTextComponent();
|
||||
|
||||
/**
|
||||
* Returns the {@link Looper} associated with the application thread that's used to access the
|
||||
* player and on which player events are received.
|
||||
*/
|
||||
Looper getApplicationLooper();
|
||||
|
||||
/**
|
||||
* Register a listener to receive events from the player. The listener's methods will be called on
|
||||
* the thread that was used to construct the player. However, if the thread used to construct the
|
||||
|
|
|
|||
|
|
@ -88,7 +88,9 @@ public interface AdsLoader {
|
|||
* Attaches a player that will play ads loaded using this instance. Called on the main thread by
|
||||
* {@link AdsMediaSource}.
|
||||
*
|
||||
* @param player The player instance that will play the loaded ads.
|
||||
* @param player The player instance that will play the loaded ads. Only players which are
|
||||
* accessed on the main thread are supported ({@code player.getApplicationLooper() ==
|
||||
* Looper.getMainLooper()}).
|
||||
* @param eventListener Listener for ads loader events.
|
||||
* @param adUiViewGroup A {@link ViewGroup} on top of the player that will show any ad UI.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -16,11 +16,13 @@
|
|||
package com.google.android.exoplayer2.ui;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Looper;
|
||||
import android.widget.TextView;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
import com.google.android.exoplayer2.Player;
|
||||
import com.google.android.exoplayer2.SimpleExoPlayer;
|
||||
import com.google.android.exoplayer2.decoder.DecoderCounters;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
|
|
@ -37,10 +39,13 @@ public class DebugTextViewHelper implements Player.EventListener, Runnable {
|
|||
private boolean started;
|
||||
|
||||
/**
|
||||
* @param player The {@link SimpleExoPlayer} from which debug information should be obtained.
|
||||
* @param player The {@link SimpleExoPlayer} from which debug information should be obtained. Only
|
||||
* players which are accessed on the main thread are supported ({@code
|
||||
* player.getApplicationLooper() == Looper.getMainLooper()}).
|
||||
* @param textView The {@link TextView} that should be updated to display the information.
|
||||
*/
|
||||
public DebugTextViewHelper(SimpleExoPlayer player, TextView textView) {
|
||||
Assertions.checkArgument(player.getApplicationLooper() == Looper.getMainLooper());
|
||||
this.player = player;
|
||||
this.textView = textView;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import android.content.Context;
|
|||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Looper;
|
||||
import android.os.SystemClock;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.AttributeSet;
|
||||
|
|
@ -362,9 +363,14 @@ public class PlayerControlView extends FrameLayout {
|
|||
/**
|
||||
* Sets the {@link Player} to control.
|
||||
*
|
||||
* @param player The {@link Player} to control.
|
||||
* @param player The {@link Player} to control, or {@code null} to detach the current player. Only
|
||||
* players which are accessed on the main thread are supported ({@code
|
||||
* player.getApplicationLooper() == Looper.getMainLooper()}).
|
||||
*/
|
||||
public void setPlayer(Player player) {
|
||||
public void setPlayer(@Nullable Player player) {
|
||||
Assertions.checkState(Looper.myLooper() == Looper.getMainLooper());
|
||||
Assertions.checkArgument(
|
||||
player == null || player.getApplicationLooper() == Looper.getMainLooper());
|
||||
if (this.player == player) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -433,8 +433,15 @@ public class PlayerNotificationManager {
|
|||
*
|
||||
* <p>If the player is released it must be removed from the manager by calling {@code
|
||||
* setPlayer(null)}. This will cancel the notification.
|
||||
*
|
||||
* @param player The {@link Player} to use, or {@code null} to remove the current player. Only
|
||||
* players which are accessed on the main thread are supported ({@code
|
||||
* player.getApplicationLooper() == Looper.getMainLooper()}).
|
||||
*/
|
||||
public final void setPlayer(@Nullable Player player) {
|
||||
Assertions.checkState(Looper.myLooper() == Looper.getMainLooper());
|
||||
Assertions.checkArgument(
|
||||
player == null || player.getApplicationLooper() == Looper.getMainLooper());
|
||||
if (this.player == player) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import android.graphics.Matrix;
|
|||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Looper;
|
||||
import android.support.annotation.IntDef;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
|
@ -499,9 +500,14 @@ public class PlayerView extends FrameLayout {
|
|||
* calling {@code setPlayer(null)} to detach it from the old one. This ordering is significantly
|
||||
* more efficient and may allow for more seamless transitions.
|
||||
*
|
||||
* @param player The {@link Player} to use.
|
||||
* @param player The {@link Player} to use, or {@code null} to detach the current player. Only
|
||||
* players which are accessed on the main thread are supported ({@code
|
||||
* player.getApplicationLooper() == Looper.getMainLooper()}).
|
||||
*/
|
||||
public void setPlayer(Player player) {
|
||||
public void setPlayer(@Nullable Player player) {
|
||||
Assertions.checkState(Looper.myLooper() == Looper.getMainLooper());
|
||||
Assertions.checkArgument(
|
||||
player == null || player.getApplicationLooper() == Looper.getMainLooper());
|
||||
if (this.player == player) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue