Restrict CommandButton.iconUri to content Uris
These Uris are not widely supported yet and were only meant to be used with content Uris. Restricting this more tightly allows controllers to use these Uris more easily as they have a stricter guarentee on what it's needed to load these Uris. Media session apps with different types of Uris can convert them by setting up a ContentProvider if needed. Issue: androidx/media#1783 PiperOrigin-RevId: 683539747
This commit is contained in:
parent
7c9fede3ad
commit
bd192c17ca
@ -105,6 +105,7 @@
|
|||||||
Browse actions of AAOS</a>.
|
Browse actions of AAOS</a>.
|
||||||
* Fix bug where a Media3 controller was sometimes unable to let a session
|
* Fix bug where a Media3 controller was sometimes unable to let a session
|
||||||
app start a foreground service after requesting `play()`.
|
app start a foreground service after requesting `play()`.
|
||||||
|
* Restrict `CommandButton.Builder.setIconUri` to only accept content Uris.
|
||||||
* UI:
|
* UI:
|
||||||
* Make the stretched/cropped video in
|
* Make the stretched/cropped video in
|
||||||
`PlayerView`-in-Compose-`AndroidView` workaround opt-in, due to issues
|
`PlayerView`-in-Compose-`AndroidView` workaround opt-in, due to issues
|
||||||
|
@ -20,6 +20,7 @@ import static androidx.media3.common.util.Assertions.checkNotNull;
|
|||||||
import static androidx.media3.common.util.Assertions.checkState;
|
import static androidx.media3.common.util.Assertions.checkState;
|
||||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||||
|
|
||||||
|
import android.content.ContentResolver;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
@ -424,8 +425,8 @@ public final class CommandButton {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* [will be deprecated] Use {@link #Builder(int)} instead to define the {@link Icon} for this
|
* [will be deprecated] Use {@link #Builder(int)} instead to define the {@link Icon} for this
|
||||||
* button. A separate resource id via {@link #setIconResId(int)} or {@link #setIconUri} is no
|
* button. A separate resource id via {@link #setIconResId(int)} is no longer required unless
|
||||||
* longer required unless for {@link #ICON_UNDEFINED}.
|
* for {@link #ICON_UNDEFINED}.
|
||||||
*/
|
*/
|
||||||
public Builder() {
|
public Builder() {
|
||||||
this(ICON_UNDEFINED);
|
this(ICON_UNDEFINED);
|
||||||
@ -519,11 +520,11 @@ public final class CommandButton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a {@link Uri} for the icon of this button.
|
* Sets a content {@link Uri} for the icon of this button.
|
||||||
*
|
*
|
||||||
* <p>Note that this {@link Uri} may be used when the predefined {@link Icon} is not available
|
* <p>Note that this {@link Uri} may be used when the predefined {@link Icon} is not available
|
||||||
* or set to {@link #ICON_UNDEFINED}. It can be used in addition or instead of {@link
|
* or set to {@link #ICON_UNDEFINED}. It can be used in addition to {@link #setCustomIconResId}
|
||||||
* #setCustomIconResId} for consumers that are capable of loading the {@link Uri}.
|
* for consumers that are capable of loading the content {@link Uri}.
|
||||||
*
|
*
|
||||||
* @param uri The uri to an icon.
|
* @param uri The uri to an icon.
|
||||||
* @return This builder for chaining.
|
* @return This builder for chaining.
|
||||||
@ -531,6 +532,9 @@ public final class CommandButton {
|
|||||||
@UnstableApi
|
@UnstableApi
|
||||||
@CanIgnoreReturnValue
|
@CanIgnoreReturnValue
|
||||||
public Builder setIconUri(Uri uri) {
|
public Builder setIconUri(Uri uri) {
|
||||||
|
checkArgument(
|
||||||
|
Objects.equal(uri.getScheme(), ContentResolver.SCHEME_CONTENT),
|
||||||
|
"Only content Uris are supported for CommandButton");
|
||||||
this.iconUri = uri;
|
this.iconUri = uri;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -606,11 +610,11 @@ public final class CommandButton {
|
|||||||
@DrawableRes public final int iconResId;
|
@DrawableRes public final int iconResId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link Uri} for the icon of the button that is used when the predefined {@link #icon} is
|
* The content {@link Uri} for the icon of the button that is used when the predefined {@link
|
||||||
* not available or set to {@link #ICON_UNDEFINED}. Can be {@code null}.
|
* #icon} is not available or set to {@link #ICON_UNDEFINED}. Can be {@code null}.
|
||||||
*
|
*
|
||||||
* <p>Note that this value can be used in addition or instead of {@link #iconResId} for consumers
|
* <p>Note that this value can be used in addition to {@link #iconResId} for consumers that are
|
||||||
* that are capable of loading the {@link Uri}.
|
* capable of loading the content {@link Uri}.
|
||||||
*/
|
*/
|
||||||
@UnstableApi @Nullable public final Uri iconUri;
|
@UnstableApi @Nullable public final Uri iconUri;
|
||||||
|
|
||||||
@ -809,7 +813,7 @@ public final class CommandButton {
|
|||||||
if (playerCommand != Player.COMMAND_INVALID) {
|
if (playerCommand != Player.COMMAND_INVALID) {
|
||||||
builder.setPlayerCommand(playerCommand);
|
builder.setPlayerCommand(playerCommand);
|
||||||
}
|
}
|
||||||
if (iconUri != null) {
|
if (iconUri != null && Objects.equal(iconUri.getScheme(), ContentResolver.SCHEME_CONTENT)) {
|
||||||
builder.setIconUri(iconUri);
|
builder.setIconUri(iconUri);
|
||||||
}
|
}
|
||||||
return builder
|
return builder
|
||||||
|
@ -364,7 +364,7 @@ public class CommandButtonTest {
|
|||||||
.setDisplayName("name")
|
.setDisplayName("name")
|
||||||
.setEnabled(true)
|
.setEnabled(true)
|
||||||
.setIconResId(R.drawable.media3_notification_small_icon)
|
.setIconResId(R.drawable.media3_notification_small_icon)
|
||||||
.setIconUri(Uri.parse("http://test.test"))
|
.setIconUri(Uri.parse("content://test"))
|
||||||
.setExtras(extras)
|
.setExtras(extras)
|
||||||
.setSessionCommand(new SessionCommand(SessionCommand.COMMAND_CODE_SESSION_SET_RATING))
|
.setSessionCommand(new SessionCommand(SessionCommand.COMMAND_CODE_SESSION_SET_RATING))
|
||||||
.build();
|
.build();
|
||||||
@ -373,7 +373,7 @@ public class CommandButtonTest {
|
|||||||
.setDisplayName("name")
|
.setDisplayName("name")
|
||||||
.setEnabled(true)
|
.setEnabled(true)
|
||||||
.setIconResId(R.drawable.media3_notification_small_icon)
|
.setIconResId(R.drawable.media3_notification_small_icon)
|
||||||
.setIconUri(Uri.parse("http://test.test"))
|
.setIconUri(Uri.parse("content://test"))
|
||||||
.setExtras(extras)
|
.setExtras(extras)
|
||||||
.setPlayerCommand(Player.COMMAND_GET_METADATA)
|
.setPlayerCommand(Player.COMMAND_GET_METADATA)
|
||||||
.build();
|
.build();
|
||||||
|
@ -145,7 +145,7 @@ public class MediaBrowserCompatWithMediaLibraryServiceTest
|
|||||||
.getString(
|
.getString(
|
||||||
androidx.media3.session.legacy.MediaConstants
|
androidx.media3.session.legacy.MediaConstants
|
||||||
.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ICON_URI))
|
.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ICON_URI))
|
||||||
.isEqualTo("http://www.example.com/icon/playlist_add");
|
.isEqualTo("content://playlist_add");
|
||||||
assertThat(
|
assertThat(
|
||||||
mediaItemCommandButtons
|
mediaItemCommandButtons
|
||||||
.get(0)
|
.get(0)
|
||||||
@ -174,7 +174,7 @@ public class MediaBrowserCompatWithMediaLibraryServiceTest
|
|||||||
.getString(
|
.getString(
|
||||||
androidx.media3.session.legacy.MediaConstants
|
androidx.media3.session.legacy.MediaConstants
|
||||||
.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ICON_URI))
|
.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ICON_URI))
|
||||||
.isEqualTo("http://www.example.com/icon/radio");
|
.isEqualTo("content://radio");
|
||||||
assertThat(
|
assertThat(
|
||||||
mediaItemCommandButtons
|
mediaItemCommandButtons
|
||||||
.get(1)
|
.get(1)
|
||||||
|
@ -142,14 +142,14 @@ public class MediaBrowserListenerWithMediaBrowserServiceCompatTest {
|
|||||||
CommandButton playlistAddButton =
|
CommandButton playlistAddButton =
|
||||||
new CommandButton.Builder()
|
new CommandButton.Builder()
|
||||||
.setDisplayName("Add to playlist")
|
.setDisplayName("Add to playlist")
|
||||||
.setIconUri(Uri.parse("https://www.example.com/icon/playlist_add"))
|
.setIconUri(Uri.parse("content://playlist_add"))
|
||||||
.setSessionCommand(
|
.setSessionCommand(
|
||||||
new SessionCommand(MediaBrowserConstants.COMMAND_PLAYLIST_ADD, Bundle.EMPTY))
|
new SessionCommand(MediaBrowserConstants.COMMAND_PLAYLIST_ADD, Bundle.EMPTY))
|
||||||
.build();
|
.build();
|
||||||
CommandButton radioButton =
|
CommandButton radioButton =
|
||||||
new CommandButton.Builder()
|
new CommandButton.Builder()
|
||||||
.setDisplayName("Radio station")
|
.setDisplayName("Radio station")
|
||||||
.setIconUri(Uri.parse("https://www.example.com/icon/radio"))
|
.setIconUri(Uri.parse("content://radio"))
|
||||||
.setSessionCommand(
|
.setSessionCommand(
|
||||||
new SessionCommand(MediaBrowserConstants.COMMAND_RADIO, Bundle.EMPTY))
|
new SessionCommand(MediaBrowserConstants.COMMAND_RADIO, Bundle.EMPTY))
|
||||||
.build();
|
.build();
|
||||||
@ -192,7 +192,7 @@ public class MediaBrowserListenerWithMediaBrowserServiceCompatTest {
|
|||||||
CommandButton playlistAddButton =
|
CommandButton playlistAddButton =
|
||||||
new CommandButton.Builder()
|
new CommandButton.Builder()
|
||||||
.setDisplayName("Add to playlist")
|
.setDisplayName("Add to playlist")
|
||||||
.setIconUri(Uri.parse("https://www.example.com/icon/playlist_add"))
|
.setIconUri(Uri.parse("content://playlist_add"))
|
||||||
.setSessionCommand(
|
.setSessionCommand(
|
||||||
new SessionCommand(MediaBrowserConstants.COMMAND_PLAYLIST_ADD, Bundle.EMPTY))
|
new SessionCommand(MediaBrowserConstants.COMMAND_PLAYLIST_ADD, Bundle.EMPTY))
|
||||||
.build();
|
.build();
|
||||||
|
@ -364,7 +364,7 @@ public class MockMediaBrowserServiceCompat extends MediaBrowserServiceCompat {
|
|||||||
"Add to playlist");
|
"Add to playlist");
|
||||||
playlistAddBrowseAction.putString(
|
playlistAddBrowseAction.putString(
|
||||||
androidx.media3.session.legacy.MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ICON_URI,
|
androidx.media3.session.legacy.MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ICON_URI,
|
||||||
"https://www.example.com/icon/playlist_add");
|
"content://playlist_add");
|
||||||
playlistAddBrowseAction.putBundle(
|
playlistAddBrowseAction.putBundle(
|
||||||
androidx.media3.session.legacy.MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_EXTRAS,
|
androidx.media3.session.legacy.MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_EXTRAS,
|
||||||
playlistAddExtras);
|
playlistAddExtras);
|
||||||
@ -379,7 +379,7 @@ public class MockMediaBrowserServiceCompat extends MediaBrowserServiceCompat {
|
|||||||
"Radio station");
|
"Radio station");
|
||||||
radioBrowseAction.putString(
|
radioBrowseAction.putString(
|
||||||
androidx.media3.session.legacy.MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ICON_URI,
|
androidx.media3.session.legacy.MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ICON_URI,
|
||||||
"https://www.example.com/icon/radio");
|
"content://radio");
|
||||||
radioBrowseAction.putBundle(
|
radioBrowseAction.putBundle(
|
||||||
androidx.media3.session.legacy.MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_EXTRAS,
|
androidx.media3.session.legacy.MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_EXTRAS,
|
||||||
radioExtras);
|
radioExtras);
|
||||||
|
@ -238,7 +238,7 @@ public class MockMediaLibraryService extends MediaLibraryService {
|
|||||||
ImmutableList.of(
|
ImmutableList.of(
|
||||||
new CommandButton.Builder(CommandButton.ICON_PLAYLIST_ADD)
|
new CommandButton.Builder(CommandButton.ICON_PLAYLIST_ADD)
|
||||||
.setDisplayName("Add to playlist")
|
.setDisplayName("Add to playlist")
|
||||||
.setIconUri(Uri.parse("http://www.example.com/icon/playlist_add"))
|
.setIconUri(Uri.parse("content://playlist_add"))
|
||||||
.setSessionCommand(
|
.setSessionCommand(
|
||||||
new SessionCommand(
|
new SessionCommand(
|
||||||
MediaBrowserConstants.COMMAND_PLAYLIST_ADD, Bundle.EMPTY))
|
MediaBrowserConstants.COMMAND_PLAYLIST_ADD, Bundle.EMPTY))
|
||||||
@ -246,7 +246,7 @@ public class MockMediaLibraryService extends MediaLibraryService {
|
|||||||
.build(),
|
.build(),
|
||||||
new CommandButton.Builder(CommandButton.ICON_RADIO)
|
new CommandButton.Builder(CommandButton.ICON_RADIO)
|
||||||
.setDisplayName("Radio station")
|
.setDisplayName("Radio station")
|
||||||
.setIconUri(Uri.parse("http://www.example.com/icon/radio"))
|
.setIconUri(Uri.parse("content://radio"))
|
||||||
.setSessionCommand(
|
.setSessionCommand(
|
||||||
new SessionCommand(MediaBrowserConstants.COMMAND_RADIO, Bundle.EMPTY))
|
new SessionCommand(MediaBrowserConstants.COMMAND_RADIO, Bundle.EMPTY))
|
||||||
.setExtras(radioExtras)
|
.setExtras(radioExtras)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user