Add an artwork field to MediaMetadata

#minor-release

PiperOrigin-RevId: 373410795
This commit is contained in:
samrobinson 2021-05-12 19:15:44 +01:00 committed by Oliver Woodman
parent 795594f862
commit 6bba218e72
3 changed files with 106 additions and 8 deletions

View File

@ -25,6 +25,7 @@ import com.google.common.base.Objects;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.List;
/**
@ -46,6 +47,8 @@ public final class MediaMetadata implements Bundleable {
@Nullable private Uri mediaUri;
@Nullable private Rating userRating;
@Nullable private Rating overallRating;
@Nullable private byte[] artworkData;
@Nullable private Uri artworkUri;
public Builder() {}
@ -60,6 +63,8 @@ public final class MediaMetadata implements Bundleable {
this.mediaUri = mediaMetadata.mediaUri;
this.userRating = mediaMetadata.userRating;
this.overallRating = mediaMetadata.overallRating;
this.artworkData = mediaMetadata.artworkData;
this.artworkUri = mediaMetadata.artworkUri;
}
/** Sets the title. */
@ -126,6 +131,18 @@ public final class MediaMetadata implements Bundleable {
return this;
}
/** Sets the artwork data as a compressed byte array. */
public Builder setArtworkData(@Nullable byte[] artworkData) {
this.artworkData = artworkData == null ? null : artworkData.clone();
return this;
}
/** Sets the artwork {@link Uri}. */
public Builder setArtworkUri(@Nullable Uri artworkUri) {
this.artworkUri = artworkUri;
return this;
}
/**
* Sets all fields supported by the {@link Metadata.Entry entries} within the {@link Metadata}.
*
@ -197,6 +214,10 @@ public final class MediaMetadata implements Bundleable {
@Nullable public final Rating userRating;
/** Optional overall {@link Rating}. */
@Nullable public final Rating overallRating;
/** Optional artwork data as a compressed byte array. */
@Nullable public final byte[] artworkData;
/** Optional artwork {@link Uri}. */
@Nullable public final Uri artworkUri;
private MediaMetadata(Builder builder) {
this.title = builder.title;
@ -209,6 +230,8 @@ public final class MediaMetadata implements Bundleable {
this.mediaUri = builder.mediaUri;
this.userRating = builder.userRating;
this.overallRating = builder.overallRating;
this.artworkData = builder.artworkData;
this.artworkUri = builder.artworkUri;
}
/** Returns a new {@link Builder} instance with the current {@link MediaMetadata} fields. */
@ -234,7 +257,9 @@ public final class MediaMetadata implements Bundleable {
&& Util.areEqual(description, that.description)
&& Util.areEqual(mediaUri, that.mediaUri)
&& Util.areEqual(userRating, that.userRating)
&& Util.areEqual(overallRating, that.overallRating);
&& Util.areEqual(overallRating, that.overallRating)
&& Arrays.equals(artworkData, that.artworkData)
&& Util.areEqual(artworkUri, that.artworkUri);
}
@Override
@ -249,7 +274,9 @@ public final class MediaMetadata implements Bundleable {
description,
mediaUri,
userRating,
overallRating);
overallRating,
Arrays.hashCode(artworkData),
artworkUri);
}
// Bundleable implementation.
@ -267,6 +294,8 @@ public final class MediaMetadata implements Bundleable {
FIELD_MEDIA_URI,
FIELD_USER_RATING,
FIELD_OVERALL_RATING,
FIELD_ARTWORK_DATA,
FIELD_ARTWORK_URI
})
private @interface FieldNumber {}
@ -280,6 +309,8 @@ public final class MediaMetadata implements Bundleable {
private static final int FIELD_MEDIA_URI = 7;
private static final int FIELD_USER_RATING = 8;
private static final int FIELD_OVERALL_RATING = 9;
private static final int FIELD_ARTWORK_DATA = 10;
private static final int FIELD_ARTWORK_URI = 11;
@Override
public Bundle toBundle() {
@ -292,6 +323,8 @@ public final class MediaMetadata implements Bundleable {
bundle.putCharSequence(keyForField(FIELD_SUBTITLE), subtitle);
bundle.putCharSequence(keyForField(FIELD_DESCRIPTION), description);
bundle.putParcelable(keyForField(FIELD_MEDIA_URI), mediaUri);
bundle.putByteArray(keyForField(FIELD_ARTWORK_DATA), artworkData);
bundle.putParcelable(keyForField(FIELD_ARTWORK_URI), artworkUri);
if (userRating != null) {
bundle.putBundle(keyForField(FIELD_USER_RATING), userRating.toBundle());
@ -316,7 +349,9 @@ public final class MediaMetadata implements Bundleable {
.setDisplayTitle(bundle.getCharSequence(keyForField(FIELD_DISPLAY_TITLE)))
.setSubtitle(bundle.getCharSequence(keyForField(FIELD_SUBTITLE)))
.setDescription(bundle.getCharSequence(keyForField(FIELD_DESCRIPTION)))
.setMediaUri(bundle.getParcelable(keyForField(FIELD_MEDIA_URI)));
.setMediaUri(bundle.getParcelable(keyForField(FIELD_MEDIA_URI)))
.setArtworkData(bundle.getByteArray(keyForField(FIELD_ARTWORK_DATA)))
.setArtworkUri(bundle.getParcelable(keyForField(FIELD_ARTWORK_URI)));
if (bundle.containsKey(keyForField(FIELD_USER_RATING))) {
@Nullable Bundle fieldBundle = bundle.getBundle(keyForField(FIELD_USER_RATING));
@ -327,7 +362,7 @@ public final class MediaMetadata implements Bundleable {
if (bundle.containsKey(keyForField(FIELD_OVERALL_RATING))) {
@Nullable Bundle fieldBundle = bundle.getBundle(keyForField(FIELD_OVERALL_RATING));
if (fieldBundle != null) {
builder.setUserRating(Rating.CREATOR.fromBundle(fieldBundle));
builder.setOverallRating(Rating.CREATOR.fromBundle(fieldBundle));
}
}

View File

@ -20,6 +20,7 @@ import static com.google.android.exoplayer2.util.Util.castNonNull;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.MediaMetadata;
import com.google.android.exoplayer2.util.Util;
import java.util.Arrays;
@ -50,6 +51,11 @@ public final class ApicFrame extends Id3Frame {
pictureData = castNonNull(in.createByteArray());
}
@Override
public void populateMediaMetadata(MediaMetadata.Builder builder) {
builder.setArtworkData(pictureData);
}
@Override
public boolean equals(@Nullable Object obj) {
if (this == obj) {

View File

@ -17,9 +17,13 @@ package com.google.android.exoplayer2;
import static com.google.common.truth.Truth.assertThat;
import android.net.Uri;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.metadata.id3.ApicFrame;
import com.google.android.exoplayer2.metadata.id3.TextInformationFrame;
import com.google.android.exoplayer2.util.MimeTypes;
import java.util.Arrays;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -32,6 +36,17 @@ public class MediaMetadataTest {
MediaMetadata mediaMetadata = new MediaMetadata.Builder().build();
assertThat(mediaMetadata.title).isNull();
assertThat(mediaMetadata.artist).isNull();
assertThat(mediaMetadata.albumTitle).isNull();
assertThat(mediaMetadata.albumArtist).isNull();
assertThat(mediaMetadata.displayTitle).isNull();
assertThat(mediaMetadata.subtitle).isNull();
assertThat(mediaMetadata.description).isNull();
assertThat(mediaMetadata.mediaUri).isNull();
assertThat(mediaMetadata.userRating).isNull();
assertThat(mediaMetadata.overallRating).isNull();
assertThat(mediaMetadata.artworkData).isNull();
assertThat(mediaMetadata.artworkUri).isNull();
}
@Test
@ -44,14 +59,39 @@ public class MediaMetadataTest {
}
@Test
public void roundTripViaBundle_yieldsEqualInstance() {
MediaMetadata mediaMetadata = new MediaMetadata.Builder().setTitle("title").build();
public void builderSetArtworkData_setsArtworkData() {
byte[] bytes = new byte[] {35, 12, 6, 77};
MediaMetadata mediaMetadata = new MediaMetadata.Builder().setArtworkData(bytes).build();
assertThat(MediaMetadata.CREATOR.fromBundle(mediaMetadata.toBundle())).isEqualTo(mediaMetadata);
assertThat(Arrays.equals(mediaMetadata.artworkData, bytes)).isTrue();
}
@Test
public void builderPopulatedFromMetadataEntry_setsTitleCorrectly() {
public void builderSetArworkUri_setsArtworkUri() {
Uri uri = Uri.parse("https://www.google.com");
MediaMetadata mediaMetadata = new MediaMetadata.Builder().setArtworkUri(uri).build();
assertThat(mediaMetadata.artworkUri).isEqualTo(uri);
}
@Test
public void roundTripViaBundle_yieldsEqualInstance() {
MediaMetadata mediaMetadata =
new MediaMetadata.Builder()
.setTitle("title")
.setAlbumArtist("the artist")
.setMediaUri(Uri.parse("https://www.google.com"))
.setUserRating(new HeartRating(false))
.setOverallRating(new PercentageRating(87.4f))
.setArtworkData(new byte[] {-88, 12, 3, 2, 124, -54, -33, 69})
.build();
MediaMetadata fromBundle = MediaMetadata.CREATOR.fromBundle(mediaMetadata.toBundle());
assertThat(fromBundle).isEqualTo(mediaMetadata);
}
@Test
public void builderPopulatedFromTextInformationFrameEntry_setsTitle() {
String title = "the title";
Metadata.Entry entry =
new TextInformationFrame(/* id= */ "TT2", /* description= */ null, /* value= */ title);
@ -60,4 +100,21 @@ public class MediaMetadataTest {
entry.populateMediaMetadata(builder);
assertThat(builder.build().title.toString()).isEqualTo(title);
}
@Test
public void builderPopulatedFromApicFrameEntry_setsArtwork() {
byte[] pictureData = new byte[] {-12, 52, 33, 85, 34, 22, 1, -55};
Metadata.Entry entry =
new ApicFrame(
/* mimeType= */ MimeTypes.BASE_TYPE_IMAGE,
/* description= */ "an image",
/* pictureType= */ 0x03,
pictureData);
MediaMetadata.Builder builder = MediaMetadata.EMPTY.buildUpon();
entry.populateMediaMetadata(builder);
MediaMetadata mediaMetadata = builder.build();
assertThat(mediaMetadata.artworkData).isEqualTo(pictureData);
}
}