Commit 4ce171a3 by tianyifeng Committed by microkatz

Load bitmaps for `MediaBrowserCompat`.

* Transforms the `ListenableFuture<LibraryResult<MediaItem>>` and `ListenableFuture<LibraryResult<List<MediaItem>>>` to `ListenableFuture<MediaBrowserCompat.MediaItem>` and `ListenableFuture<List<MediaBrowserCompat.MediaItem>>`, and the result will be sent out when `ListenableFuture` the `MediaBrowserCompat.MediaItem` (or the list of it) is fulfilled.
* Add `artworkData` to the tests in `MediaBrowserCompatWithMediaLibraryServiceTest`.

PiperOrigin-RevId: 489205547
parent 6e73fc54
...@@ -136,9 +136,9 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -136,9 +136,9 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
errorMessage, /* cause= */ null, PlaybackException.ERROR_CODE_REMOTE_ERROR); errorMessage, /* cause= */ null, PlaybackException.ERROR_CODE_REMOTE_ERROR);
} }
/** Converts a {@link MediaItem} to a {@link MediaBrowserCompat.MediaItem}. */ public static MediaBrowserCompat.MediaItem convertToBrowserItem(
public static MediaBrowserCompat.MediaItem convertToBrowserItem(MediaItem item) { MediaItem item, @Nullable Bitmap artworkBitmap) {
MediaDescriptionCompat description = convertToMediaDescriptionCompat(item); MediaDescriptionCompat description = convertToMediaDescriptionCompat(item, artworkBitmap);
MediaMetadata metadata = item.mediaMetadata; MediaMetadata metadata = item.mediaMetadata;
int flags = 0; int flags = 0;
if (metadata.folderType != null && metadata.folderType != MediaMetadata.FOLDER_TYPE_NONE) { if (metadata.folderType != null && metadata.folderType != MediaMetadata.FOLDER_TYPE_NONE) {
...@@ -150,15 +150,6 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -150,15 +150,6 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
return new MediaBrowserCompat.MediaItem(description, flags); return new MediaBrowserCompat.MediaItem(description, flags);
} }
/** Converts a list of {@link MediaItem} to a list of {@link MediaBrowserCompat.MediaItem}. */
public static List<MediaBrowserCompat.MediaItem> convertToBrowserItemList(List<MediaItem> items) {
List<MediaBrowserCompat.MediaItem> result = new ArrayList<>();
for (int i = 0; i < items.size(); i++) {
result.add(convertToBrowserItem(items.get(i)));
}
return result;
}
/** Converts a {@link MediaBrowserCompat.MediaItem} to a {@link MediaItem}. */ /** Converts a {@link MediaBrowserCompat.MediaItem} to a {@link MediaItem}. */
public static MediaItem convertToMediaItem(MediaBrowserCompat.MediaItem item) { public static MediaItem convertToMediaItem(MediaBrowserCompat.MediaItem item) {
return convertToMediaItem(item.getDescription(), item.isBrowsable(), item.isPlayable()); return convertToMediaItem(item.getDescription(), item.isBrowsable(), item.isPlayable());
...@@ -320,16 +311,32 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -320,16 +311,32 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
return result; return result;
} }
/** Converts a {@link MediaItem} to a {@link MediaDescriptionCompat}. */ /**
* Converts a {@link MediaItem} to a {@link MediaDescriptionCompat}.
*
* @deprecated Use {@link #convertToMediaDescriptionCompat(MediaItem, Bitmap)} instead.
*/
@Deprecated
public static MediaDescriptionCompat convertToMediaDescriptionCompat(MediaItem item) { public static MediaDescriptionCompat convertToMediaDescriptionCompat(MediaItem item) {
MediaMetadata metadata = item.mediaMetadata;
@Nullable Bitmap artworkBitmap = null;
if (metadata.artworkData != null) {
artworkBitmap =
BitmapFactory.decodeByteArray(metadata.artworkData, 0, metadata.artworkData.length);
}
return convertToMediaDescriptionCompat(item, artworkBitmap);
}
/** Converts a {@link MediaItem} to a {@link MediaDescriptionCompat} */
public static MediaDescriptionCompat convertToMediaDescriptionCompat(
MediaItem item, @Nullable Bitmap artworkBitmap) {
MediaDescriptionCompat.Builder builder = MediaDescriptionCompat.Builder builder =
new MediaDescriptionCompat.Builder() new MediaDescriptionCompat.Builder()
.setMediaId(item.mediaId.equals(MediaItem.DEFAULT_MEDIA_ID) ? null : item.mediaId); .setMediaId(item.mediaId.equals(MediaItem.DEFAULT_MEDIA_ID) ? null : item.mediaId);
MediaMetadata metadata = item.mediaMetadata; MediaMetadata metadata = item.mediaMetadata;
if (metadata.artworkData != null) { if (artworkBitmap != null) {
Bitmap artwork = builder.setIconBitmap(artworkBitmap);
BitmapFactory.decodeByteArray(metadata.artworkData, 0, metadata.artworkData.length);
builder.setIconBitmap(artwork);
} }
@Nullable Bundle extras = metadata.extras; @Nullable Bundle extras = metadata.extras;
if (metadata.folderType != null && metadata.folderType != MediaMetadata.FOLDER_TYPE_NONE) { if (metadata.folderType != null && metadata.folderType != MediaMetadata.FOLDER_TYPE_NONE) {
......
...@@ -129,6 +129,7 @@ public class MediaBrowserCompatWithMediaLibraryServiceTest ...@@ -129,6 +129,7 @@ public class MediaBrowserCompatWithMediaLibraryServiceTest
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue(); assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(itemRef.get().getMediaId()).isEqualTo(mediaId); assertThat(itemRef.get().getMediaId()).isEqualTo(mediaId);
assertThat(itemRef.get().isBrowsable()).isTrue(); assertThat(itemRef.get().isBrowsable()).isTrue();
assertThat(itemRef.get().getDescription().getIconBitmap()).isNotNull();
} }
@Test @Test
...@@ -151,6 +152,7 @@ public class MediaBrowserCompatWithMediaLibraryServiceTest ...@@ -151,6 +152,7 @@ public class MediaBrowserCompatWithMediaLibraryServiceTest
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue(); assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(itemRef.get().getMediaId()).isEqualTo(mediaId); assertThat(itemRef.get().getMediaId()).isEqualTo(mediaId);
assertThat(itemRef.get().isPlayable()).isTrue(); assertThat(itemRef.get().isPlayable()).isTrue();
assertThat(itemRef.get().getDescription().getIconBitmap()).isNotNull();
} }
@Test @Test
...@@ -181,6 +183,7 @@ public class MediaBrowserCompatWithMediaLibraryServiceTest ...@@ -181,6 +183,7 @@ public class MediaBrowserCompatWithMediaLibraryServiceTest
BundleSubject.assertThat(description.getExtras()) BundleSubject.assertThat(description.getExtras())
.string(METADATA_EXTRA_KEY) .string(METADATA_EXTRA_KEY)
.isEqualTo(METADATA_EXTRA_VALUE); .isEqualTo(METADATA_EXTRA_VALUE);
assertThat(description.getIconBitmap()).isNotNull();
} }
@Test @Test
...@@ -245,6 +248,7 @@ public class MediaBrowserCompatWithMediaLibraryServiceTest ...@@ -245,6 +248,7 @@ public class MediaBrowserCompatWithMediaLibraryServiceTest
EXTRAS_KEY_COMPLETION_STATUS, EXTRAS_KEY_COMPLETION_STATUS,
/* defaultValue= */ EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED + 1)) /* defaultValue= */ EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED + 1))
.isEqualTo(EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED); .isEqualTo(EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED);
assertThat(mediaItem.getDescription().getIconBitmap()).isNotNull();
} }
} }
...@@ -311,6 +315,7 @@ public class MediaBrowserCompatWithMediaLibraryServiceTest ...@@ -311,6 +315,7 @@ public class MediaBrowserCompatWithMediaLibraryServiceTest
int relativeIndex = originalIndex - fromIndex; int relativeIndex = originalIndex - fromIndex;
assertThat(children.get(relativeIndex).getMediaId()) assertThat(children.get(relativeIndex).getMediaId())
.isEqualTo(GET_CHILDREN_RESULT.get(originalIndex)); .isEqualTo(GET_CHILDREN_RESULT.get(originalIndex));
assertThat(children.get(relativeIndex).getDescription().getIconBitmap()).isNotNull();
} }
latch.countDown(); latch.countDown();
} }
......
...@@ -32,7 +32,6 @@ import android.support.v4.media.RatingCompat; ...@@ -32,7 +32,6 @@ import android.support.v4.media.RatingCompat;
import android.support.v4.media.session.MediaControllerCompat; import android.support.v4.media.session.MediaControllerCompat;
import android.support.v4.media.session.MediaSessionCompat; import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.PlaybackStateCompat; import android.support.v4.media.session.PlaybackStateCompat;
import android.text.TextUtils;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.media.AudioAttributesCompat; import androidx.media.AudioAttributesCompat;
import androidx.media3.common.AudioAttributes; import androidx.media3.common.AudioAttributes;
...@@ -72,23 +71,6 @@ public final class MediaUtilsTest { ...@@ -72,23 +71,6 @@ public final class MediaUtilsTest {
} }
@Test @Test
public void convertToBrowserItem() {
String mediaId = "testId";
CharSequence trackTitle = "testTitle";
MediaItem mediaItem =
new MediaItem.Builder()
.setMediaId(mediaId)
.setMediaMetadata(new MediaMetadata.Builder().setTitle(trackTitle).build())
.build();
MediaBrowserCompat.MediaItem browserItem = MediaUtils.convertToBrowserItem(mediaItem);
assertThat(browserItem.getDescription()).isNotNull();
assertThat(browserItem.getDescription().getMediaId()).isEqualTo(mediaId);
assertThat(TextUtils.equals(browserItem.getDescription().getTitle(), trackTitle)).isTrue();
}
@Test
public void convertToMediaItem_browserItemToMediaItem() { public void convertToMediaItem_browserItemToMediaItem() {
String mediaId = "testId"; String mediaId = "testId";
String title = "testTitle"; String title = "testTitle";
...@@ -116,18 +98,6 @@ public final class MediaUtilsTest { ...@@ -116,18 +98,6 @@ public final class MediaUtilsTest {
} }
@Test @Test
public void convertToBrowserItemList() {
int size = 3;
List<MediaItem> mediaItems = MediaTestUtils.createMediaItems(size);
List<MediaBrowserCompat.MediaItem> browserItems =
MediaUtils.convertToBrowserItemList(mediaItems);
assertThat(browserItems).hasSize(size);
for (int i = 0; i < size; ++i) {
assertThat(browserItems.get(i).getMediaId()).isEqualTo(mediaItems.get(i).mediaId);
}
}
@Test
public void convertBrowserItemListToMediaItemList() { public void convertBrowserItemListToMediaItemList() {
int size = 3; int size = 3;
List<MediaBrowserCompat.MediaItem> browserItems = MediaTestUtils.createBrowserItems(size); List<MediaBrowserCompat.MediaItem> browserItems = MediaTestUtils.createBrowserItems(size);
......
...@@ -51,6 +51,7 @@ import static androidx.media3.test.session.common.MediaBrowserConstants.SUBSCRIB ...@@ -51,6 +51,7 @@ import static androidx.media3.test.session.common.MediaBrowserConstants.SUBSCRIB
import static androidx.media3.test.session.common.MediaBrowserConstants.SUBSCRIBE_ID_NOTIFY_CHILDREN_CHANGED_TO_ONE; import static androidx.media3.test.session.common.MediaBrowserConstants.SUBSCRIBE_ID_NOTIFY_CHILDREN_CHANGED_TO_ONE;
import static androidx.media3.test.session.common.MediaBrowserConstants.SUBSCRIBE_ID_NOTIFY_CHILDREN_CHANGED_TO_ONE_WITH_NON_SUBSCRIBED_ID; import static androidx.media3.test.session.common.MediaBrowserConstants.SUBSCRIBE_ID_NOTIFY_CHILDREN_CHANGED_TO_ONE_WITH_NON_SUBSCRIBED_ID;
import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.junit.Assert.fail;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.app.Service; import android.app.Service;
...@@ -72,6 +73,7 @@ import androidx.media3.test.session.common.TestUtils; ...@@ -72,6 +73,7 @@ import androidx.media3.test.session.common.TestUtils;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
...@@ -92,6 +94,8 @@ public class MockMediaLibraryService extends MediaLibraryService { ...@@ -92,6 +94,8 @@ public class MockMediaLibraryService extends MediaLibraryService {
public static final String CONNECTION_HINTS_KEY_REMOVE_COMMAND_CODE_LIBRARY_SEARCH = public static final String CONNECTION_HINTS_KEY_REMOVE_COMMAND_CODE_LIBRARY_SEARCH =
"CONNECTION_HINTS_KEY_REMOVE_SEARCH_SESSION_COMMAND"; "CONNECTION_HINTS_KEY_REMOVE_SEARCH_SESSION_COMMAND";
private static final String TEST_IMAGE_PATH = "media/png/non-motion-photo-shortened.png";
public static final MediaItem ROOT_ITEM = public static final MediaItem ROOT_ITEM =
new MediaItem.Builder() new MediaItem.Builder()
.setMediaId(ROOT_ID) .setMediaId(ROOT_ID)
...@@ -115,6 +119,8 @@ public class MockMediaLibraryService extends MediaLibraryService { ...@@ -115,6 +119,8 @@ public class MockMediaLibraryService extends MediaLibraryService {
@Nullable @Nullable
private static LibraryParams expectedParams; private static LibraryParams expectedParams;
@Nullable private static byte[] testArtworkData;
MediaLibrarySession session; MediaLibrarySession session;
TestHandler handler; TestHandler handler;
HandlerThread handlerThread; HandlerThread handlerThread;
...@@ -238,7 +244,8 @@ public class MockMediaLibraryService extends MediaLibraryService { ...@@ -238,7 +244,8 @@ public class MockMediaLibraryService extends MediaLibraryService {
LibraryResult.ofItem(createBrowsableMediaItem(mediaId), /* params= */ null)); LibraryResult.ofItem(createBrowsableMediaItem(mediaId), /* params= */ null));
case MEDIA_ID_GET_PLAYABLE_ITEM: case MEDIA_ID_GET_PLAYABLE_ITEM:
return Futures.immediateFuture( return Futures.immediateFuture(
LibraryResult.ofItem(createPlayableMediaItem(mediaId), /* params= */ null)); LibraryResult.ofItem(
createPlayableMediaItemWithArtworkData(mediaId), /* params= */ null));
case MEDIA_ID_GET_ITEM_WITH_METADATA: case MEDIA_ID_GET_ITEM_WITH_METADATA:
return Futures.immediateFuture( return Futures.immediateFuture(
LibraryResult.ofItem(createMediaItemWithMetadata(mediaId), /* params= */ null)); LibraryResult.ofItem(createMediaItemWithMetadata(mediaId), /* params= */ null));
...@@ -445,20 +452,32 @@ public class MockMediaLibraryService extends MediaLibraryService { ...@@ -445,20 +452,32 @@ public class MockMediaLibraryService extends MediaLibraryService {
// Create a list of MediaItem from the list of media IDs. // Create a list of MediaItem from the list of media IDs.
List<MediaItem> result = new ArrayList<>(); List<MediaItem> result = new ArrayList<>();
for (int i = 0; i < paginatedMediaIdList.size(); i++) { for (int i = 0; i < paginatedMediaIdList.size(); i++) {
result.add(createPlayableMediaItem(paginatedMediaIdList.get(i))); result.add(createPlayableMediaItemWithArtworkData(paginatedMediaIdList.get(i)));
} }
return result; return result;
} }
private static MediaItem createBrowsableMediaItem(String mediaId) { private MediaItem createBrowsableMediaItem(String mediaId) {
MediaMetadata mediaMetadata = MediaMetadata mediaMetadata =
new MediaMetadata.Builder() new MediaMetadata.Builder()
.setFolderType(MediaMetadata.FOLDER_TYPE_MIXED) .setFolderType(MediaMetadata.FOLDER_TYPE_MIXED)
.setIsPlayable(false) .setIsPlayable(false)
.setArtworkData(getArtworkData(), MediaMetadata.PICTURE_TYPE_FRONT_COVER)
.build(); .build();
return new MediaItem.Builder().setMediaId(mediaId).setMediaMetadata(mediaMetadata).build(); return new MediaItem.Builder().setMediaId(mediaId).setMediaMetadata(mediaMetadata).build();
} }
private MediaItem createPlayableMediaItemWithArtworkData(String mediaId) {
MediaItem mediaItem = createPlayableMediaItem(mediaId);
MediaMetadata mediaMetadataWithArtwork =
mediaItem
.mediaMetadata
.buildUpon()
.setArtworkData(getArtworkData(), MediaMetadata.PICTURE_TYPE_FRONT_COVER)
.build();
return mediaItem.buildUpon().setMediaMetadata(mediaMetadataWithArtwork).build();
}
private static MediaItem createPlayableMediaItem(String mediaId) { private static MediaItem createPlayableMediaItem(String mediaId) {
Bundle extras = new Bundle(); Bundle extras = new Bundle();
extras.putInt(EXTRAS_KEY_COMPLETION_STATUS, EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED); extras.putInt(EXTRAS_KEY_COMPLETION_STATUS, EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED);
...@@ -471,15 +490,32 @@ public class MockMediaLibraryService extends MediaLibraryService { ...@@ -471,15 +490,32 @@ public class MockMediaLibraryService extends MediaLibraryService {
return new MediaItem.Builder().setMediaId(mediaId).setMediaMetadata(mediaMetadata).build(); return new MediaItem.Builder().setMediaId(mediaId).setMediaMetadata(mediaMetadata).build();
} }
private static MediaItem createMediaItemWithMetadata(String mediaId) { private MediaItem createMediaItemWithMetadata(String mediaId) {
MediaMetadata mediaMetadata = MediaTestUtils.createMediaMetadata(); MediaMetadata mediaMetadataWithArtwork =
MediaTestUtils.createMediaMetadata()
.buildUpon()
.setArtworkData(getArtworkData(), MediaMetadata.PICTURE_TYPE_FRONT_COVER)
.build();
return new MediaItem.Builder() return new MediaItem.Builder()
.setMediaId(mediaId) .setMediaId(mediaId)
.setRequestMetadata( .setRequestMetadata(
new MediaItem.RequestMetadata.Builder() new MediaItem.RequestMetadata.Builder()
.setMediaUri(CommonConstants.METADATA_MEDIA_URI) .setMediaUri(CommonConstants.METADATA_MEDIA_URI)
.build()) .build())
.setMediaMetadata(mediaMetadata) .setMediaMetadata(mediaMetadataWithArtwork)
.build(); .build();
} }
private byte[] getArtworkData() {
if (testArtworkData != null) {
return testArtworkData;
}
try {
testArtworkData =
TestUtils.getByteArrayForScaledBitmap(getApplicationContext(), TEST_IMAGE_PATH);
} catch (IOException e) {
fail(e.getMessage());
}
return testArtworkData;
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment