mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Add MediaSession.Builder().setPeriodicPositionUpdateEnabled()
This allows to disable periodic position updates when building the session. #minor-release PiperOrigin-RevId: 572531837
This commit is contained in:
parent
164e658839
commit
4dc3db4da3
@ -518,6 +518,20 @@ public abstract class MediaLibraryService extends MediaSessionService {
|
|||||||
return super.setShowPlayButtonIfPlaybackIsSuppressed(showPlayButtonIfPlaybackIsSuppressed);
|
return super.setShowPlayButtonIfPlaybackIsSuppressed(showPlayButtonIfPlaybackIsSuppressed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether periodic position updates should be sent to controllers while playing. If
|
||||||
|
* false, no periodic position updates are sent to controllers.
|
||||||
|
*
|
||||||
|
* <p>The default is {@code true}.
|
||||||
|
*
|
||||||
|
* @param isEnabled Whether periodic position update is enabled.
|
||||||
|
*/
|
||||||
|
@UnstableApi
|
||||||
|
@Override
|
||||||
|
public Builder setPeriodicPositionUpdateEnabled(boolean isEnabled) {
|
||||||
|
return super.setPeriodicPositionUpdateEnabled(isEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds a {@link MediaLibrarySession}.
|
* Builds a {@link MediaLibrarySession}.
|
||||||
*
|
*
|
||||||
@ -539,7 +553,8 @@ public abstract class MediaLibraryService extends MediaSessionService {
|
|||||||
callback,
|
callback,
|
||||||
extras,
|
extras,
|
||||||
checkNotNull(bitmapLoader),
|
checkNotNull(bitmapLoader),
|
||||||
playIfSuppressed);
|
playIfSuppressed,
|
||||||
|
isPeriodicPositionUpdateEnabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -552,7 +567,8 @@ public abstract class MediaLibraryService extends MediaSessionService {
|
|||||||
MediaSession.Callback callback,
|
MediaSession.Callback callback,
|
||||||
Bundle tokenExtras,
|
Bundle tokenExtras,
|
||||||
BitmapLoader bitmapLoader,
|
BitmapLoader bitmapLoader,
|
||||||
boolean playIfSuppressed) {
|
boolean playIfSuppressed,
|
||||||
|
boolean isPeriodicPositionUpdateEnabled) {
|
||||||
super(
|
super(
|
||||||
context,
|
context,
|
||||||
id,
|
id,
|
||||||
@ -562,7 +578,8 @@ public abstract class MediaLibraryService extends MediaSessionService {
|
|||||||
callback,
|
callback,
|
||||||
tokenExtras,
|
tokenExtras,
|
||||||
bitmapLoader,
|
bitmapLoader,
|
||||||
playIfSuppressed);
|
playIfSuppressed,
|
||||||
|
isPeriodicPositionUpdateEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -575,7 +592,8 @@ public abstract class MediaLibraryService extends MediaSessionService {
|
|||||||
MediaSession.Callback callback,
|
MediaSession.Callback callback,
|
||||||
Bundle tokenExtras,
|
Bundle tokenExtras,
|
||||||
BitmapLoader bitmapLoader,
|
BitmapLoader bitmapLoader,
|
||||||
boolean playIfSuppressed) {
|
boolean playIfSuppressed,
|
||||||
|
boolean isPeriodicPositionUpdateEnabled) {
|
||||||
return new MediaLibrarySessionImpl(
|
return new MediaLibrarySessionImpl(
|
||||||
this,
|
this,
|
||||||
context,
|
context,
|
||||||
@ -586,7 +604,8 @@ public abstract class MediaLibraryService extends MediaSessionService {
|
|||||||
(Callback) callback,
|
(Callback) callback,
|
||||||
tokenExtras,
|
tokenExtras,
|
||||||
bitmapLoader,
|
bitmapLoader,
|
||||||
playIfSuppressed);
|
playIfSuppressed,
|
||||||
|
isPeriodicPositionUpdateEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -75,7 +75,8 @@ import java.util.concurrent.Future;
|
|||||||
MediaLibrarySession.Callback callback,
|
MediaLibrarySession.Callback callback,
|
||||||
Bundle tokenExtras,
|
Bundle tokenExtras,
|
||||||
BitmapLoader bitmapLoader,
|
BitmapLoader bitmapLoader,
|
||||||
boolean playIfSuppressed) {
|
boolean playIfSuppressed,
|
||||||
|
boolean isPeriodicPositionUpdateEnabled) {
|
||||||
super(
|
super(
|
||||||
instance,
|
instance,
|
||||||
context,
|
context,
|
||||||
@ -86,7 +87,8 @@ import java.util.concurrent.Future;
|
|||||||
callback,
|
callback,
|
||||||
tokenExtras,
|
tokenExtras,
|
||||||
bitmapLoader,
|
bitmapLoader,
|
||||||
playIfSuppressed);
|
playIfSuppressed,
|
||||||
|
isPeriodicPositionUpdateEnabled);
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
parentIdToSubscribedControllers = HashMultimap.create();
|
parentIdToSubscribedControllers = HashMultimap.create();
|
||||||
|
@ -376,6 +376,20 @@ public class MediaSession {
|
|||||||
return super.setCustomLayout(customLayout);
|
return super.setCustomLayout(customLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether periodic position updates should be sent to controllers while playing. If false,
|
||||||
|
* no periodic position updates are sent to controllers.
|
||||||
|
*
|
||||||
|
* <p>The default is {@code true}.
|
||||||
|
*
|
||||||
|
* @param isEnabled Whether periodic position update is enabled.
|
||||||
|
*/
|
||||||
|
@UnstableApi
|
||||||
|
@Override
|
||||||
|
public Builder setPeriodicPositionUpdateEnabled(boolean isEnabled) {
|
||||||
|
return super.setPeriodicPositionUpdateEnabled(isEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets whether a play button is shown if playback is {@linkplain
|
* Sets whether a play button is shown if playback is {@linkplain
|
||||||
* Player#getPlaybackSuppressionReason() suppressed}.
|
* Player#getPlaybackSuppressionReason() suppressed}.
|
||||||
@ -413,7 +427,8 @@ public class MediaSession {
|
|||||||
callback,
|
callback,
|
||||||
extras,
|
extras,
|
||||||
checkNotNull(bitmapLoader),
|
checkNotNull(bitmapLoader),
|
||||||
playIfSuppressed);
|
playIfSuppressed,
|
||||||
|
isPeriodicPositionUpdateEnabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -606,7 +621,8 @@ public class MediaSession {
|
|||||||
Callback callback,
|
Callback callback,
|
||||||
Bundle tokenExtras,
|
Bundle tokenExtras,
|
||||||
BitmapLoader bitmapLoader,
|
BitmapLoader bitmapLoader,
|
||||||
boolean playIfSuppressed) {
|
boolean playIfSuppressed,
|
||||||
|
boolean isPeriodicPositionUpdateEnabled) {
|
||||||
synchronized (STATIC_LOCK) {
|
synchronized (STATIC_LOCK) {
|
||||||
if (SESSION_ID_TO_SESSION_MAP.containsKey(id)) {
|
if (SESSION_ID_TO_SESSION_MAP.containsKey(id)) {
|
||||||
throw new IllegalStateException("Session ID must be unique. ID=" + id);
|
throw new IllegalStateException("Session ID must be unique. ID=" + id);
|
||||||
@ -623,7 +639,8 @@ public class MediaSession {
|
|||||||
callback,
|
callback,
|
||||||
tokenExtras,
|
tokenExtras,
|
||||||
bitmapLoader,
|
bitmapLoader,
|
||||||
playIfSuppressed);
|
playIfSuppressed,
|
||||||
|
isPeriodicPositionUpdateEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ MediaSessionImpl createImpl(
|
/* package */ MediaSessionImpl createImpl(
|
||||||
@ -635,7 +652,8 @@ public class MediaSession {
|
|||||||
Callback callback,
|
Callback callback,
|
||||||
Bundle tokenExtras,
|
Bundle tokenExtras,
|
||||||
BitmapLoader bitmapLoader,
|
BitmapLoader bitmapLoader,
|
||||||
boolean playIfSuppressed) {
|
boolean playIfSuppressed,
|
||||||
|
boolean isPeriodicPositionUpdateEnabled) {
|
||||||
return new MediaSessionImpl(
|
return new MediaSessionImpl(
|
||||||
this,
|
this,
|
||||||
context,
|
context,
|
||||||
@ -646,7 +664,8 @@ public class MediaSession {
|
|||||||
callback,
|
callback,
|
||||||
tokenExtras,
|
tokenExtras,
|
||||||
bitmapLoader,
|
bitmapLoader,
|
||||||
playIfSuppressed);
|
playIfSuppressed,
|
||||||
|
isPeriodicPositionUpdateEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ MediaSessionImpl getImpl() {
|
/* package */ MediaSessionImpl getImpl() {
|
||||||
@ -1798,8 +1817,8 @@ public class MediaSession {
|
|||||||
/* package */ Bundle extras;
|
/* package */ Bundle extras;
|
||||||
/* package */ @MonotonicNonNull BitmapLoader bitmapLoader;
|
/* package */ @MonotonicNonNull BitmapLoader bitmapLoader;
|
||||||
/* package */ boolean playIfSuppressed;
|
/* package */ boolean playIfSuppressed;
|
||||||
|
|
||||||
/* package */ ImmutableList<CommandButton> customLayout;
|
/* package */ ImmutableList<CommandButton> customLayout;
|
||||||
|
/* package */ boolean isPeriodicPositionUpdateEnabled;
|
||||||
|
|
||||||
public BuilderBase(Context context, Player player, CallbackT callback) {
|
public BuilderBase(Context context, Player player, CallbackT callback) {
|
||||||
this.context = checkNotNull(context);
|
this.context = checkNotNull(context);
|
||||||
@ -1810,6 +1829,7 @@ public class MediaSession {
|
|||||||
extras = Bundle.EMPTY;
|
extras = Bundle.EMPTY;
|
||||||
customLayout = ImmutableList.of();
|
customLayout = ImmutableList.of();
|
||||||
playIfSuppressed = true;
|
playIfSuppressed = true;
|
||||||
|
isPeriodicPositionUpdateEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@ -1855,6 +1875,12 @@ public class MediaSession {
|
|||||||
return (BuilderT) this;
|
return (BuilderT) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public BuilderT setPeriodicPositionUpdateEnabled(boolean isPeriodicPositionUpdateEnabled) {
|
||||||
|
this.isPeriodicPositionUpdateEnabled = isPeriodicPositionUpdateEnabled;
|
||||||
|
return (BuilderT) this;
|
||||||
|
}
|
||||||
|
|
||||||
public abstract SessionT build();
|
public abstract SessionT build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,6 +117,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
private final Runnable periodicSessionPositionInfoUpdateRunnable;
|
private final Runnable periodicSessionPositionInfoUpdateRunnable;
|
||||||
private final Handler mainHandler;
|
private final Handler mainHandler;
|
||||||
private final boolean playIfSuppressed;
|
private final boolean playIfSuppressed;
|
||||||
|
private final boolean isPeriodicPositionUpdateEnabled;
|
||||||
|
|
||||||
private PlayerInfo playerInfo;
|
private PlayerInfo playerInfo;
|
||||||
private PlayerWrapper playerWrapper;
|
private PlayerWrapper playerWrapper;
|
||||||
@ -148,7 +149,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
MediaSession.Callback callback,
|
MediaSession.Callback callback,
|
||||||
Bundle tokenExtras,
|
Bundle tokenExtras,
|
||||||
BitmapLoader bitmapLoader,
|
BitmapLoader bitmapLoader,
|
||||||
boolean playIfSuppressed) {
|
boolean playIfSuppressed,
|
||||||
|
boolean isPeriodicPositionUpdateEnabled) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
|
|
||||||
@ -166,6 +168,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
this.bitmapLoader = bitmapLoader;
|
this.bitmapLoader = bitmapLoader;
|
||||||
this.playIfSuppressed = playIfSuppressed;
|
this.playIfSuppressed = playIfSuppressed;
|
||||||
|
this.isPeriodicPositionUpdateEnabled = isPeriodicPositionUpdateEnabled;
|
||||||
|
|
||||||
playerInfo = PlayerInfo.DEFAULT;
|
playerInfo = PlayerInfo.DEFAULT;
|
||||||
onPlayerInfoChangedHandler = new PlayerInfoChangedHandler(player.getApplicationLooper());
|
onPlayerInfoChangedHandler = new PlayerInfoChangedHandler(player.getApplicationLooper());
|
||||||
@ -1053,7 +1056,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
|
|
||||||
private void schedulePeriodicSessionPositionInfoChanges() {
|
private void schedulePeriodicSessionPositionInfoChanges() {
|
||||||
applicationHandler.removeCallbacks(periodicSessionPositionInfoUpdateRunnable);
|
applicationHandler.removeCallbacks(periodicSessionPositionInfoUpdateRunnable);
|
||||||
if (sessionPositionUpdateDelayMs > 0
|
if (isPeriodicPositionUpdateEnabled
|
||||||
|
&& sessionPositionUpdateDelayMs > 0
|
||||||
&& (playerWrapper.isPlaying() || playerWrapper.isLoading())) {
|
&& (playerWrapper.isPlaying() || playerWrapper.isLoading())) {
|
||||||
applicationHandler.postDelayed(
|
applicationHandler.postDelayed(
|
||||||
periodicSessionPositionInfoUpdateRunnable, sessionPositionUpdateDelayMs);
|
periodicSessionPositionInfoUpdateRunnable, sessionPositionUpdateDelayMs);
|
||||||
|
@ -33,6 +33,7 @@ import android.support.v4.media.session.MediaSessionCompat;
|
|||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import androidx.media.MediaSessionManager;
|
import androidx.media.MediaSessionManager;
|
||||||
import androidx.media3.common.MediaLibraryInfo;
|
import androidx.media3.common.MediaLibraryInfo;
|
||||||
|
import androidx.media3.common.Player;
|
||||||
import androidx.media3.common.util.Log;
|
import androidx.media3.common.util.Log;
|
||||||
import androidx.media3.common.util.Util;
|
import androidx.media3.common.util.Util;
|
||||||
import androidx.media3.test.session.common.HandlerThreadTestRule;
|
import androidx.media3.test.session.common.HandlerThreadTestRule;
|
||||||
@ -41,6 +42,8 @@ import androidx.media3.test.session.common.TestHandler;
|
|||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
import androidx.test.filters.LargeTest;
|
import androidx.test.filters.LargeTest;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
@ -433,4 +436,62 @@ public class MediaSessionTest {
|
|||||||
// version of remote controller.
|
// version of remote controller.
|
||||||
assertThat(controllerVersionRef.get()).isEqualTo(MediaLibraryInfo.VERSION_INT);
|
assertThat(controllerVersionRef.get()).isEqualTo(MediaLibraryInfo.VERSION_INT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setPeriodicPositionUpdateEnabled_periodicUpdatesEnabled_bufferedPositionMsUpdated()
|
||||||
|
throws Exception {
|
||||||
|
player.playWhenReady = true;
|
||||||
|
player.playbackState = Player.STATE_READY;
|
||||||
|
MediaSession session =
|
||||||
|
sessionTestRule.ensureReleaseAfterTest(
|
||||||
|
new MediaSession.Builder(context, player)
|
||||||
|
.setPeriodicPositionUpdateEnabled(true)
|
||||||
|
.setId(
|
||||||
|
"setPeriodicPositionUpdateEnabled_periodicUpdatesEnabled_bufferedPositionMsUpdated")
|
||||||
|
.build());
|
||||||
|
threadTestRule.getHandler().postAndSync(() -> session.setSessionPositionUpdateDelayMs(10L));
|
||||||
|
MediaController controller =
|
||||||
|
new MediaController.Builder(ApplicationProvider.getApplicationContext(), session.getToken())
|
||||||
|
.buildAsync()
|
||||||
|
.get();
|
||||||
|
List<Long> bufferedPositionsMs = new ArrayList<>();
|
||||||
|
TestHandler testHandler = new TestHandler(controller.getApplicationLooper());
|
||||||
|
|
||||||
|
for (long bufferedPositionMs = 0; bufferedPositionMs < 5000; bufferedPositionMs += 1000) {
|
||||||
|
player.bufferedPosition = bufferedPositionMs;
|
||||||
|
Thread.sleep(50L);
|
||||||
|
bufferedPositionsMs.add(testHandler.postAndSync(controller::getBufferedPosition));
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(bufferedPositionsMs).containsExactly(0L, 1000L, 2000L, 3000L, 4000L).inOrder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setPeriodicPositionUpdateEnabled_periodicUpdatesDisabled_bufferedPositionMsUnchanged()
|
||||||
|
throws Exception {
|
||||||
|
player.playWhenReady = true;
|
||||||
|
player.playbackState = Player.STATE_READY;
|
||||||
|
MediaSession session =
|
||||||
|
sessionTestRule.ensureReleaseAfterTest(
|
||||||
|
new MediaSession.Builder(context, player)
|
||||||
|
.setPeriodicPositionUpdateEnabled(false)
|
||||||
|
.setId(
|
||||||
|
"setPeriodicPositionUpdateEnabled_periodicUpdatesDisabled_bufferedPositionMsUnchanged")
|
||||||
|
.build());
|
||||||
|
threadTestRule.getHandler().postAndSync(() -> session.setSessionPositionUpdateDelayMs(10L));
|
||||||
|
MediaController controller =
|
||||||
|
new MediaController.Builder(ApplicationProvider.getApplicationContext(), session.getToken())
|
||||||
|
.buildAsync()
|
||||||
|
.get();
|
||||||
|
List<Long> bufferedPositionsMs = new ArrayList<>();
|
||||||
|
TestHandler testHandler = new TestHandler(controller.getApplicationLooper());
|
||||||
|
|
||||||
|
for (long bufferedPositionMs = 0; bufferedPositionMs < 5000; bufferedPositionMs += 1000) {
|
||||||
|
player.bufferedPosition = bufferedPositionMs;
|
||||||
|
Thread.sleep(50L);
|
||||||
|
bufferedPositionsMs.add(testHandler.postAndSync(controller::getBufferedPosition));
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(bufferedPositionsMs).containsExactly(0L, 0L, 0L, 0L, 0L).inOrder();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user