Commit 46c5f030 by samrobinson Committed by Oliver Woodman

Add an artwork field to MediaMetadata

#minor-release

PiperOrigin-RevId: 373410795
parent cccb4006
...@@ -25,6 +25,7 @@ import com.google.common.base.Objects; ...@@ -25,6 +25,7 @@ import com.google.common.base.Objects;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.List; import java.util.List;
/** /**
...@@ -46,6 +47,8 @@ public final class MediaMetadata implements Bundleable { ...@@ -46,6 +47,8 @@ public final class MediaMetadata implements Bundleable {
@Nullable private Uri mediaUri; @Nullable private Uri mediaUri;
@Nullable private Rating userRating; @Nullable private Rating userRating;
@Nullable private Rating overallRating; @Nullable private Rating overallRating;
@Nullable private byte[] artworkData;
@Nullable private Uri artworkUri;
public Builder() {} public Builder() {}
...@@ -60,6 +63,8 @@ public final class MediaMetadata implements Bundleable { ...@@ -60,6 +63,8 @@ public final class MediaMetadata implements Bundleable {
this.mediaUri = mediaMetadata.mediaUri; this.mediaUri = mediaMetadata.mediaUri;
this.userRating = mediaMetadata.userRating; this.userRating = mediaMetadata.userRating;
this.overallRating = mediaMetadata.overallRating; this.overallRating = mediaMetadata.overallRating;
this.artworkData = mediaMetadata.artworkData;
this.artworkUri = mediaMetadata.artworkUri;
} }
/** Sets the title. */ /** Sets the title. */
...@@ -126,6 +131,18 @@ public final class MediaMetadata implements Bundleable { ...@@ -126,6 +131,18 @@ public final class MediaMetadata implements Bundleable {
return this; 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}. * Sets all fields supported by the {@link Metadata.Entry entries} within the {@link Metadata}.
* *
...@@ -197,6 +214,10 @@ public final class MediaMetadata implements Bundleable { ...@@ -197,6 +214,10 @@ public final class MediaMetadata implements Bundleable {
@Nullable public final Rating userRating; @Nullable public final Rating userRating;
/** Optional overall {@link Rating}. */ /** Optional overall {@link Rating}. */
@Nullable public final Rating overallRating; @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) { private MediaMetadata(Builder builder) {
this.title = builder.title; this.title = builder.title;
...@@ -209,6 +230,8 @@ public final class MediaMetadata implements Bundleable { ...@@ -209,6 +230,8 @@ public final class MediaMetadata implements Bundleable {
this.mediaUri = builder.mediaUri; this.mediaUri = builder.mediaUri;
this.userRating = builder.userRating; this.userRating = builder.userRating;
this.overallRating = builder.overallRating; this.overallRating = builder.overallRating;
this.artworkData = builder.artworkData;
this.artworkUri = builder.artworkUri;
} }
/** Returns a new {@link Builder} instance with the current {@link MediaMetadata} fields. */ /** Returns a new {@link Builder} instance with the current {@link MediaMetadata} fields. */
...@@ -234,7 +257,9 @@ public final class MediaMetadata implements Bundleable { ...@@ -234,7 +257,9 @@ public final class MediaMetadata implements Bundleable {
&& Util.areEqual(description, that.description) && Util.areEqual(description, that.description)
&& Util.areEqual(mediaUri, that.mediaUri) && Util.areEqual(mediaUri, that.mediaUri)
&& Util.areEqual(userRating, that.userRating) && 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 @Override
...@@ -249,7 +274,9 @@ public final class MediaMetadata implements Bundleable { ...@@ -249,7 +274,9 @@ public final class MediaMetadata implements Bundleable {
description, description,
mediaUri, mediaUri,
userRating, userRating,
overallRating); overallRating,
Arrays.hashCode(artworkData),
artworkUri);
} }
// Bundleable implementation. // Bundleable implementation.
...@@ -267,6 +294,8 @@ public final class MediaMetadata implements Bundleable { ...@@ -267,6 +294,8 @@ public final class MediaMetadata implements Bundleable {
FIELD_MEDIA_URI, FIELD_MEDIA_URI,
FIELD_USER_RATING, FIELD_USER_RATING,
FIELD_OVERALL_RATING, FIELD_OVERALL_RATING,
FIELD_ARTWORK_DATA,
FIELD_ARTWORK_URI
}) })
private @interface FieldNumber {} private @interface FieldNumber {}
...@@ -280,6 +309,8 @@ public final class MediaMetadata implements Bundleable { ...@@ -280,6 +309,8 @@ public final class MediaMetadata implements Bundleable {
private static final int FIELD_MEDIA_URI = 7; private static final int FIELD_MEDIA_URI = 7;
private static final int FIELD_USER_RATING = 8; private static final int FIELD_USER_RATING = 8;
private static final int FIELD_OVERALL_RATING = 9; 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 @Override
public Bundle toBundle() { public Bundle toBundle() {
...@@ -292,6 +323,8 @@ public final class MediaMetadata implements Bundleable { ...@@ -292,6 +323,8 @@ public final class MediaMetadata implements Bundleable {
bundle.putCharSequence(keyForField(FIELD_SUBTITLE), subtitle); bundle.putCharSequence(keyForField(FIELD_SUBTITLE), subtitle);
bundle.putCharSequence(keyForField(FIELD_DESCRIPTION), description); bundle.putCharSequence(keyForField(FIELD_DESCRIPTION), description);
bundle.putParcelable(keyForField(FIELD_MEDIA_URI), mediaUri); bundle.putParcelable(keyForField(FIELD_MEDIA_URI), mediaUri);
bundle.putByteArray(keyForField(FIELD_ARTWORK_DATA), artworkData);
bundle.putParcelable(keyForField(FIELD_ARTWORK_URI), artworkUri);
if (userRating != null) { if (userRating != null) {
bundle.putBundle(keyForField(FIELD_USER_RATING), userRating.toBundle()); bundle.putBundle(keyForField(FIELD_USER_RATING), userRating.toBundle());
...@@ -316,7 +349,9 @@ public final class MediaMetadata implements Bundleable { ...@@ -316,7 +349,9 @@ public final class MediaMetadata implements Bundleable {
.setDisplayTitle(bundle.getCharSequence(keyForField(FIELD_DISPLAY_TITLE))) .setDisplayTitle(bundle.getCharSequence(keyForField(FIELD_DISPLAY_TITLE)))
.setSubtitle(bundle.getCharSequence(keyForField(FIELD_SUBTITLE))) .setSubtitle(bundle.getCharSequence(keyForField(FIELD_SUBTITLE)))
.setDescription(bundle.getCharSequence(keyForField(FIELD_DESCRIPTION))) .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))) { if (bundle.containsKey(keyForField(FIELD_USER_RATING))) {
@Nullable Bundle fieldBundle = bundle.getBundle(keyForField(FIELD_USER_RATING)); @Nullable Bundle fieldBundle = bundle.getBundle(keyForField(FIELD_USER_RATING));
...@@ -327,7 +362,7 @@ public final class MediaMetadata implements Bundleable { ...@@ -327,7 +362,7 @@ public final class MediaMetadata implements Bundleable {
if (bundle.containsKey(keyForField(FIELD_OVERALL_RATING))) { if (bundle.containsKey(keyForField(FIELD_OVERALL_RATING))) {
@Nullable Bundle fieldBundle = bundle.getBundle(keyForField(FIELD_OVERALL_RATING)); @Nullable Bundle fieldBundle = bundle.getBundle(keyForField(FIELD_OVERALL_RATING));
if (fieldBundle != null) { if (fieldBundle != null) {
builder.setUserRating(Rating.CREATOR.fromBundle(fieldBundle)); builder.setOverallRating(Rating.CREATOR.fromBundle(fieldBundle));
} }
} }
......
...@@ -20,6 +20,7 @@ import static com.google.android.exoplayer2.util.Util.castNonNull; ...@@ -20,6 +20,7 @@ import static com.google.android.exoplayer2.util.Util.castNonNull;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.MediaMetadata;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import java.util.Arrays; import java.util.Arrays;
...@@ -51,6 +52,11 @@ public final class ApicFrame extends Id3Frame { ...@@ -51,6 +52,11 @@ public final class ApicFrame extends Id3Frame {
} }
@Override @Override
public void populateMediaMetadata(MediaMetadata.Builder builder) {
builder.setArtworkData(pictureData);
}
@Override
public boolean equals(@Nullable Object obj) { public boolean equals(@Nullable Object obj) {
if (this == obj) { if (this == obj) {
return true; return true;
......
...@@ -17,9 +17,13 @@ package com.google.android.exoplayer2; ...@@ -17,9 +17,13 @@ package com.google.android.exoplayer2;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import android.net.Uri;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.metadata.Metadata; 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.metadata.id3.TextInformationFrame;
import com.google.android.exoplayer2.util.MimeTypes;
import java.util.Arrays;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
...@@ -32,6 +36,17 @@ public class MediaMetadataTest { ...@@ -32,6 +36,17 @@ public class MediaMetadataTest {
MediaMetadata mediaMetadata = new MediaMetadata.Builder().build(); MediaMetadata mediaMetadata = new MediaMetadata.Builder().build();
assertThat(mediaMetadata.title).isNull(); 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 @Test
...@@ -44,14 +59,39 @@ public class MediaMetadataTest { ...@@ -44,14 +59,39 @@ public class MediaMetadataTest {
} }
@Test @Test
public void builderSetArtworkData_setsArtworkData() {
byte[] bytes = new byte[] {35, 12, 6, 77};
MediaMetadata mediaMetadata = new MediaMetadata.Builder().setArtworkData(bytes).build();
assertThat(Arrays.equals(mediaMetadata.artworkData, bytes)).isTrue();
}
@Test
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() { public void roundTripViaBundle_yieldsEqualInstance() {
MediaMetadata mediaMetadata = new MediaMetadata.Builder().setTitle("title").build(); 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();
assertThat(MediaMetadata.CREATOR.fromBundle(mediaMetadata.toBundle())).isEqualTo(mediaMetadata); MediaMetadata fromBundle = MediaMetadata.CREATOR.fromBundle(mediaMetadata.toBundle());
assertThat(fromBundle).isEqualTo(mediaMetadata);
} }
@Test @Test
public void builderPopulatedFromMetadataEntry_setsTitleCorrectly() { public void builderPopulatedFromTextInformationFrameEntry_setsTitle() {
String title = "the title"; String title = "the title";
Metadata.Entry entry = Metadata.Entry entry =
new TextInformationFrame(/* id= */ "TT2", /* description= */ null, /* value= */ title); new TextInformationFrame(/* id= */ "TT2", /* description= */ null, /* value= */ title);
...@@ -60,4 +100,21 @@ public class MediaMetadataTest { ...@@ -60,4 +100,21 @@ public class MediaMetadataTest {
entry.populateMediaMetadata(builder); entry.populateMediaMetadata(builder);
assertThat(builder.build().title.toString()).isEqualTo(title); 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);
}
} }
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