• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package android.media;
17 
18 import android.annotation.NonNull;
19 import android.annotation.Nullable;
20 import android.content.ContentProviderClient;
21 import android.content.ContentResolver;
22 import android.graphics.Bitmap;
23 import android.graphics.BitmapFactory;
24 import android.media.browse.MediaBrowser;
25 import android.media.session.MediaController;
26 import android.net.Uri;
27 import android.os.Bundle;
28 import android.os.CancellationSignal;
29 import android.os.OperationCanceledException;
30 import android.os.Parcel;
31 import android.os.Parcelable;
32 import android.text.TextUtils;
33 import android.util.ArrayMap;
34 import android.util.Log;
35 import android.util.Size;
36 import android.util.SparseArray;
37 
38 import java.util.Set;
39 
40 /**
41  * Contains metadata about an item, such as the title, artist, etc.
42  */
43 public final class MediaMetadata implements Parcelable {
44     private static final String TAG = "MediaMetadata";
45 
46     /**
47      * The title of the media.
48      */
49     public static final String METADATA_KEY_TITLE = "android.media.metadata.TITLE";
50 
51     /**
52      * The artist of the media.
53      */
54     public static final String METADATA_KEY_ARTIST = "android.media.metadata.ARTIST";
55 
56     /**
57      * The duration of the media in ms. A negative duration indicates that the
58      * duration is unknown (or infinite).
59      */
60     public static final String METADATA_KEY_DURATION = "android.media.metadata.DURATION";
61 
62     /**
63      * The album title for the media.
64      */
65     public static final String METADATA_KEY_ALBUM = "android.media.metadata.ALBUM";
66 
67     /**
68      * The author of the media.
69      */
70     public static final String METADATA_KEY_AUTHOR = "android.media.metadata.AUTHOR";
71 
72     /**
73      * The writer of the media.
74      */
75     public static final String METADATA_KEY_WRITER = "android.media.metadata.WRITER";
76 
77     /**
78      * The composer of the media.
79      */
80     public static final String METADATA_KEY_COMPOSER = "android.media.metadata.COMPOSER";
81 
82     /**
83      * The compilation status of the media.
84      */
85     public static final String METADATA_KEY_COMPILATION = "android.media.metadata.COMPILATION";
86 
87     /**
88      * The date the media was created or published. The format is unspecified
89      * but RFC 3339 is recommended.
90      */
91     public static final String METADATA_KEY_DATE = "android.media.metadata.DATE";
92 
93     /**
94      * The year the media was created or published as a long.
95      */
96     public static final String METADATA_KEY_YEAR = "android.media.metadata.YEAR";
97 
98     /**
99      * The genre of the media.
100      */
101     public static final String METADATA_KEY_GENRE = "android.media.metadata.GENRE";
102 
103     /**
104      * The track number for the media.
105      */
106     public static final String METADATA_KEY_TRACK_NUMBER = "android.media.metadata.TRACK_NUMBER";
107 
108     /**
109      * The number of tracks in the media's original source.
110      */
111     public static final String METADATA_KEY_NUM_TRACKS = "android.media.metadata.NUM_TRACKS";
112 
113     /**
114      * The disc number for the media's original source.
115      */
116     public static final String METADATA_KEY_DISC_NUMBER = "android.media.metadata.DISC_NUMBER";
117 
118     /**
119      * The artist for the album of the media's original source.
120      */
121     public static final String METADATA_KEY_ALBUM_ARTIST = "android.media.metadata.ALBUM_ARTIST";
122 
123     /**
124      * The artwork for the media as a {@link Bitmap}.
125      */
126     public static final String METADATA_KEY_ART = "android.media.metadata.ART";
127 
128     /**
129      * The artwork for the media as a Uri formatted String. The artwork can be
130      * loaded using a combination of {@link ContentResolver#openInputStream} and
131      * {@link BitmapFactory#decodeStream}.
132      */
133     public static final String METADATA_KEY_ART_URI = "android.media.metadata.ART_URI";
134 
135     /**
136      * The artwork for the album of the media's original source as a
137      * {@link Bitmap}.
138      */
139     public static final String METADATA_KEY_ALBUM_ART = "android.media.metadata.ALBUM_ART";
140 
141     /**
142      * The artwork for the album of the media's original source as a Uri
143      * formatted String. The artwork can be loaded using a combination of
144      * {@link ContentResolver#openInputStream} and
145      * {@link BitmapFactory#decodeStream}.
146      */
147     public static final String METADATA_KEY_ALBUM_ART_URI = "android.media.metadata.ALBUM_ART_URI";
148 
149     /**
150      * The user's rating for the media.
151      *
152      * @see Rating
153      */
154     public static final String METADATA_KEY_USER_RATING = "android.media.metadata.USER_RATING";
155 
156     /**
157      * The overall rating for the media.
158      *
159      * @see Rating
160      */
161     public static final String METADATA_KEY_RATING = "android.media.metadata.RATING";
162 
163     /**
164      * A title that is suitable for display to the user. This will generally be
165      * the same as {@link #METADATA_KEY_TITLE} but may differ for some formats.
166      * When displaying media described by this metadata this should be preferred
167      * if present.
168      */
169     public static final String METADATA_KEY_DISPLAY_TITLE = "android.media.metadata.DISPLAY_TITLE";
170 
171     /**
172      * A subtitle that is suitable for display to the user. When displaying a
173      * second line for media described by this metadata this should be preferred
174      * to other fields if present.
175      */
176     public static final String METADATA_KEY_DISPLAY_SUBTITLE
177             = "android.media.metadata.DISPLAY_SUBTITLE";
178 
179     /**
180      * A description that is suitable for display to the user. When displaying
181      * more information for media described by this metadata this should be
182      * preferred to other fields if present.
183      */
184     public static final String METADATA_KEY_DISPLAY_DESCRIPTION
185             = "android.media.metadata.DISPLAY_DESCRIPTION";
186 
187     /**
188      * An icon or thumbnail that is suitable for display to the user. When
189      * displaying an icon for media described by this metadata this should be
190      * preferred to other fields if present. This must be a {@link Bitmap}.
191      */
192     public static final String METADATA_KEY_DISPLAY_ICON
193             = "android.media.metadata.DISPLAY_ICON";
194 
195     /**
196      * A Uri formatted String for an icon or thumbnail that is suitable for
197      * display to the user. When displaying more information for media described
198      * by this metadata the display description should be preferred to other
199      * fields when present. The icon can be loaded using a combination of
200      * {@link ContentResolver#openInputStream} and
201      * {@link BitmapFactory#decodeStream}.
202      */
203     public static final String METADATA_KEY_DISPLAY_ICON_URI
204             = "android.media.metadata.DISPLAY_ICON_URI";
205 
206     /**
207      * A String key for identifying the content. This value is specific to the
208      * service providing the content. If used, this should be a persistent
209      * unique key for the underlying content. It may be used with
210      * {@link MediaController.TransportControls#playFromMediaId(String, Bundle)}
211      * to initiate playback when provided by a {@link MediaBrowser} connected to
212      * the same app.
213      */
214     public static final String METADATA_KEY_MEDIA_ID = "android.media.metadata.MEDIA_ID";
215 
216     private static final String[] PREFERRED_DESCRIPTION_ORDER = {
217             METADATA_KEY_TITLE,
218             METADATA_KEY_ARTIST,
219             METADATA_KEY_ALBUM,
220             METADATA_KEY_ALBUM_ARTIST,
221             METADATA_KEY_WRITER,
222             METADATA_KEY_AUTHOR,
223             METADATA_KEY_COMPOSER
224     };
225 
226     private static final String[] PREFERRED_BITMAP_ORDER = {
227             METADATA_KEY_DISPLAY_ICON,
228             METADATA_KEY_ART,
229             METADATA_KEY_ALBUM_ART
230     };
231 
232     private static final String[] PREFERRED_URI_ORDER = {
233             METADATA_KEY_DISPLAY_ICON_URI,
234             METADATA_KEY_ART_URI,
235             METADATA_KEY_ALBUM_ART_URI
236     };
237 
238     private static final int METADATA_TYPE_INVALID = -1;
239     private static final int METADATA_TYPE_LONG = 0;
240     private static final int METADATA_TYPE_TEXT = 1;
241     private static final int METADATA_TYPE_BITMAP = 2;
242     private static final int METADATA_TYPE_RATING = 3;
243     private static final ArrayMap<String, Integer> METADATA_KEYS_TYPE;
244 
245     static {
246         METADATA_KEYS_TYPE = new ArrayMap<String, Integer>();
METADATA_KEYS_TYPE.put(METADATA_KEY_TITLE, METADATA_TYPE_TEXT)247         METADATA_KEYS_TYPE.put(METADATA_KEY_TITLE, METADATA_TYPE_TEXT);
METADATA_KEYS_TYPE.put(METADATA_KEY_ARTIST, METADATA_TYPE_TEXT)248         METADATA_KEYS_TYPE.put(METADATA_KEY_ARTIST, METADATA_TYPE_TEXT);
METADATA_KEYS_TYPE.put(METADATA_KEY_DURATION, METADATA_TYPE_LONG)249         METADATA_KEYS_TYPE.put(METADATA_KEY_DURATION, METADATA_TYPE_LONG);
METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM, METADATA_TYPE_TEXT)250         METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM, METADATA_TYPE_TEXT);
METADATA_KEYS_TYPE.put(METADATA_KEY_AUTHOR, METADATA_TYPE_TEXT)251         METADATA_KEYS_TYPE.put(METADATA_KEY_AUTHOR, METADATA_TYPE_TEXT);
METADATA_KEYS_TYPE.put(METADATA_KEY_WRITER, METADATA_TYPE_TEXT)252         METADATA_KEYS_TYPE.put(METADATA_KEY_WRITER, METADATA_TYPE_TEXT);
METADATA_KEYS_TYPE.put(METADATA_KEY_COMPOSER, METADATA_TYPE_TEXT)253         METADATA_KEYS_TYPE.put(METADATA_KEY_COMPOSER, METADATA_TYPE_TEXT);
METADATA_KEYS_TYPE.put(METADATA_KEY_COMPILATION, METADATA_TYPE_TEXT)254         METADATA_KEYS_TYPE.put(METADATA_KEY_COMPILATION, METADATA_TYPE_TEXT);
METADATA_KEYS_TYPE.put(METADATA_KEY_DATE, METADATA_TYPE_TEXT)255         METADATA_KEYS_TYPE.put(METADATA_KEY_DATE, METADATA_TYPE_TEXT);
METADATA_KEYS_TYPE.put(METADATA_KEY_YEAR, METADATA_TYPE_LONG)256         METADATA_KEYS_TYPE.put(METADATA_KEY_YEAR, METADATA_TYPE_LONG);
METADATA_KEYS_TYPE.put(METADATA_KEY_GENRE, METADATA_TYPE_TEXT)257         METADATA_KEYS_TYPE.put(METADATA_KEY_GENRE, METADATA_TYPE_TEXT);
METADATA_KEYS_TYPE.put(METADATA_KEY_TRACK_NUMBER, METADATA_TYPE_LONG)258         METADATA_KEYS_TYPE.put(METADATA_KEY_TRACK_NUMBER, METADATA_TYPE_LONG);
METADATA_KEYS_TYPE.put(METADATA_KEY_NUM_TRACKS, METADATA_TYPE_LONG)259         METADATA_KEYS_TYPE.put(METADATA_KEY_NUM_TRACKS, METADATA_TYPE_LONG);
METADATA_KEYS_TYPE.put(METADATA_KEY_DISC_NUMBER, METADATA_TYPE_LONG)260         METADATA_KEYS_TYPE.put(METADATA_KEY_DISC_NUMBER, METADATA_TYPE_LONG);
METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM_ARTIST, METADATA_TYPE_TEXT)261         METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM_ARTIST, METADATA_TYPE_TEXT);
METADATA_KEYS_TYPE.put(METADATA_KEY_ART, METADATA_TYPE_BITMAP)262         METADATA_KEYS_TYPE.put(METADATA_KEY_ART, METADATA_TYPE_BITMAP);
METADATA_KEYS_TYPE.put(METADATA_KEY_ART_URI, METADATA_TYPE_TEXT)263         METADATA_KEYS_TYPE.put(METADATA_KEY_ART_URI, METADATA_TYPE_TEXT);
METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM_ART, METADATA_TYPE_BITMAP)264         METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM_ART, METADATA_TYPE_BITMAP);
METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM_ART_URI, METADATA_TYPE_TEXT)265         METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM_ART_URI, METADATA_TYPE_TEXT);
METADATA_KEYS_TYPE.put(METADATA_KEY_USER_RATING, METADATA_TYPE_RATING)266         METADATA_KEYS_TYPE.put(METADATA_KEY_USER_RATING, METADATA_TYPE_RATING);
METADATA_KEYS_TYPE.put(METADATA_KEY_RATING, METADATA_TYPE_RATING)267         METADATA_KEYS_TYPE.put(METADATA_KEY_RATING, METADATA_TYPE_RATING);
METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_TITLE, METADATA_TYPE_TEXT)268         METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_TITLE, METADATA_TYPE_TEXT);
METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_SUBTITLE, METADATA_TYPE_TEXT)269         METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_SUBTITLE, METADATA_TYPE_TEXT);
METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_DESCRIPTION, METADATA_TYPE_TEXT)270         METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_DESCRIPTION, METADATA_TYPE_TEXT);
METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_ICON, METADATA_TYPE_BITMAP)271         METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_ICON, METADATA_TYPE_BITMAP);
METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_ICON_URI, METADATA_TYPE_TEXT)272         METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_ICON_URI, METADATA_TYPE_TEXT);
273     }
274 
275     private static final SparseArray<String> EDITOR_KEY_MAPPING;
276 
277     static {
278         EDITOR_KEY_MAPPING = new SparseArray<String>();
EDITOR_KEY_MAPPING.put(MediaMetadataEditor.BITMAP_KEY_ARTWORK, METADATA_KEY_ART)279         EDITOR_KEY_MAPPING.put(MediaMetadataEditor.BITMAP_KEY_ARTWORK, METADATA_KEY_ART);
EDITOR_KEY_MAPPING.put(MediaMetadataEditor.RATING_KEY_BY_OTHERS, METADATA_KEY_RATING)280         EDITOR_KEY_MAPPING.put(MediaMetadataEditor.RATING_KEY_BY_OTHERS, METADATA_KEY_RATING);
EDITOR_KEY_MAPPING.put(MediaMetadataEditor.RATING_KEY_BY_USER, METADATA_KEY_USER_RATING)281         EDITOR_KEY_MAPPING.put(MediaMetadataEditor.RATING_KEY_BY_USER, METADATA_KEY_USER_RATING);
EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_ALBUM, METADATA_KEY_ALBUM)282         EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_ALBUM, METADATA_KEY_ALBUM);
EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST, METADATA_KEY_ALBUM_ARTIST)283         EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST,
284                 METADATA_KEY_ALBUM_ARTIST);
EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_ARTIST, METADATA_KEY_ARTIST)285         EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_ARTIST, METADATA_KEY_ARTIST);
EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_AUTHOR, METADATA_KEY_AUTHOR)286         EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_AUTHOR, METADATA_KEY_AUTHOR);
EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER, METADATA_KEY_TRACK_NUMBER)287         EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER,
288                 METADATA_KEY_TRACK_NUMBER);
EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_COMPOSER, METADATA_KEY_COMPOSER)289         EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_COMPOSER, METADATA_KEY_COMPOSER);
EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_COMPILATION, METADATA_KEY_COMPILATION)290         EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_COMPILATION,
291                 METADATA_KEY_COMPILATION);
EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_DATE, METADATA_KEY_DATE)292         EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_DATE, METADATA_KEY_DATE);
EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_DISC_NUMBER, METADATA_KEY_DISC_NUMBER)293         EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_DISC_NUMBER,
294                 METADATA_KEY_DISC_NUMBER);
EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_DURATION, METADATA_KEY_DURATION)295         EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_DURATION, METADATA_KEY_DURATION);
EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_GENRE, METADATA_KEY_GENRE)296         EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_GENRE, METADATA_KEY_GENRE);
EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS, METADATA_KEY_NUM_TRACKS)297         EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS,
298                 METADATA_KEY_NUM_TRACKS);
EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_TITLE, METADATA_KEY_TITLE)299         EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_TITLE, METADATA_KEY_TITLE);
EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_WRITER, METADATA_KEY_WRITER)300         EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_WRITER, METADATA_KEY_WRITER);
EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_YEAR, METADATA_KEY_YEAR)301         EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_YEAR, METADATA_KEY_YEAR);
302     }
303 
304     private final Bundle mBundle;
305     private MediaDescription mDescription;
306 
MediaMetadata(Bundle bundle)307     private MediaMetadata(Bundle bundle) {
308         mBundle = new Bundle(bundle);
309     }
310 
MediaMetadata(Parcel in)311     private MediaMetadata(Parcel in) {
312         mBundle = in.readBundle();
313     }
314 
315     /**
316      * Returns true if the given key is contained in the metadata
317      *
318      * @param key a String key
319      * @return true if the key exists in this metadata, false otherwise
320      */
containsKey(String key)321     public boolean containsKey(String key) {
322         return mBundle.containsKey(key);
323     }
324 
325     /**
326      * Returns the value associated with the given key, or null if no mapping of
327      * the desired type exists for the given key or a null value is explicitly
328      * associated with the key.
329      *
330      * @param key The key the value is stored under
331      * @return a CharSequence value, or null
332      */
getText(String key)333     public CharSequence getText(String key) {
334         return mBundle.getCharSequence(key);
335     }
336 
337     /**
338      * Returns the text value associated with the given key as a String, or null
339      * if no mapping of the desired type exists for the given key or a null
340      * value is explicitly associated with the key. This is equivalent to
341      * calling {@link #getText getText().toString()} if the value is not null.
342      *
343      * @param key The key the value is stored under
344      * @return a String value, or null
345      */
getString(String key)346     public String getString(String key) {
347         CharSequence text = getText(key);
348         if (text != null) {
349             return text.toString();
350         }
351         return null;
352     }
353 
354     /**
355      * Returns the value associated with the given key, or 0L if no long exists
356      * for the given key.
357      *
358      * @param key The key the value is stored under
359      * @return a long value
360      */
getLong(String key)361     public long getLong(String key) {
362         return mBundle.getLong(key, 0);
363     }
364 
365     /**
366      * Returns a {@link Rating} for the given key or null if no rating exists
367      * for the given key.
368      *
369      * @param key The key the value is stored under
370      * @return A {@link Rating} or null
371      */
getRating(String key)372     public Rating getRating(String key) {
373         Rating rating = null;
374         try {
375             rating = mBundle.getParcelable(key);
376         } catch (Exception e) {
377             // ignore, value was not a bitmap
378             Log.w(TAG, "Failed to retrieve a key as Rating.", e);
379         }
380         return rating;
381     }
382 
383     /**
384      * Returns a {@link Bitmap} for the given key or null if no bitmap exists
385      * for the given key.
386      *
387      * @param key The key the value is stored under
388      * @return A {@link Bitmap} or null
389      */
getBitmap(String key)390     public Bitmap getBitmap(String key) {
391         Bitmap bmp = null;
392         try {
393             bmp = mBundle.getParcelable(key);
394         } catch (Exception e) {
395             // ignore, value was not a bitmap
396             Log.w(TAG, "Failed to retrieve a key as Bitmap.", e);
397         }
398         return bmp;
399     }
400 
401     @Override
describeContents()402     public int describeContents() {
403         return 0;
404     }
405 
406     @Override
writeToParcel(Parcel dest, int flags)407     public void writeToParcel(Parcel dest, int flags) {
408         dest.writeBundle(mBundle);
409     }
410 
411     /**
412      * Returns the number of fields in this metadata.
413      *
414      * @return The number of fields in the metadata.
415      */
size()416     public int size() {
417         return mBundle.size();
418     }
419 
420     /**
421      * Returns a Set containing the Strings used as keys in this metadata.
422      *
423      * @return a Set of String keys
424      */
keySet()425     public Set<String> keySet() {
426         return mBundle.keySet();
427     }
428 
429     /**
430      * Returns a simple description of this metadata for display purposes.
431      *
432      * @return A simple description of this metadata.
433      */
getDescription()434     public @NonNull MediaDescription getDescription() {
435         if (mDescription != null) {
436             return mDescription;
437         }
438 
439         String mediaId = getString(METADATA_KEY_MEDIA_ID);
440 
441         CharSequence[] text = new CharSequence[3];
442         Bitmap icon = null;
443         Uri iconUri = null;
444 
445         // First handle the case where display data is set already
446         CharSequence displayText = getText(METADATA_KEY_DISPLAY_TITLE);
447         if (!TextUtils.isEmpty(displayText)) {
448             // If they have a display title use only display data, otherwise use
449             // our best bets
450             text[0] = displayText;
451             text[1] = getText(METADATA_KEY_DISPLAY_SUBTITLE);
452             text[2] = getText(METADATA_KEY_DISPLAY_DESCRIPTION);
453         } else {
454             // Use whatever fields we can
455             int textIndex = 0;
456             int keyIndex = 0;
457             while (textIndex < text.length && keyIndex < PREFERRED_DESCRIPTION_ORDER.length) {
458                 CharSequence next = getText(PREFERRED_DESCRIPTION_ORDER[keyIndex++]);
459                 if (!TextUtils.isEmpty(next)) {
460                     // Fill in the next empty bit of text
461                     text[textIndex++] = next;
462                 }
463             }
464         }
465 
466         // Get the best art bitmap we can find
467         for (int i = 0; i < PREFERRED_BITMAP_ORDER.length; i++) {
468             Bitmap next = getBitmap(PREFERRED_BITMAP_ORDER[i]);
469             if (next != null) {
470                 icon = next;
471                 break;
472             }
473         }
474 
475         // Get the best Uri we can find
476         for (int i = 0; i < PREFERRED_URI_ORDER.length; i++) {
477             String next = getString(PREFERRED_URI_ORDER[i]);
478             if (!TextUtils.isEmpty(next)) {
479                 iconUri = Uri.parse(next);
480                 break;
481             }
482         }
483 
484         MediaDescription.Builder bob = new MediaDescription.Builder();
485         bob.setMediaId(mediaId);
486         bob.setTitle(text[0]);
487         bob.setSubtitle(text[1]);
488         bob.setDescription(text[2]);
489         bob.setIconBitmap(icon);
490         bob.setIconUri(iconUri);
491         mDescription = bob.build();
492 
493         return mDescription;
494     }
495 
496     /**
497      * Helper for getting the String key used by {@link MediaMetadata} from the
498      * integer key that {@link MediaMetadataEditor} uses.
499      *
500      * @param editorKey The key used by the editor
501      * @return The key used by this class or null if no mapping exists
502      * @hide
503      */
getKeyFromMetadataEditorKey(int editorKey)504     public static String getKeyFromMetadataEditorKey(int editorKey) {
505         return EDITOR_KEY_MAPPING.get(editorKey, null);
506     }
507 
508     public static final Parcelable.Creator<MediaMetadata> CREATOR =
509             new Parcelable.Creator<MediaMetadata>() {
510                 @Override
511                 public MediaMetadata createFromParcel(Parcel in) {
512                     return new MediaMetadata(in);
513                 }
514 
515                 @Override
516                 public MediaMetadata[] newArray(int size) {
517                     return new MediaMetadata[size];
518                 }
519             };
520 
521     /**
522      * Use to build MediaMetadata objects. The system defined metadata keys must
523      * use the appropriate data type.
524      */
525     public static final class Builder {
526         private final Bundle mBundle;
527 
528         /**
529          * Create an empty Builder. Any field that should be included in the
530          * {@link MediaMetadata} must be added.
531          */
Builder()532         public Builder() {
533             mBundle = new Bundle();
534         }
535 
536         /**
537          * Create a Builder using a {@link MediaMetadata} instance to set the
538          * initial values. All fields in the source metadata will be included in
539          * the new metadata. Fields can be overwritten by adding the same key.
540          *
541          * @param source
542          */
Builder(MediaMetadata source)543         public Builder(MediaMetadata source) {
544             mBundle = new Bundle(source.mBundle);
545         }
546 
547         /**
548          * Put a CharSequence value into the metadata. Custom keys may be used,
549          * but if the METADATA_KEYs defined in this class are used they may only
550          * be one of the following:
551          * <ul>
552          * <li>{@link #METADATA_KEY_TITLE}</li>
553          * <li>{@link #METADATA_KEY_ARTIST}</li>
554          * <li>{@link #METADATA_KEY_ALBUM}</li>
555          * <li>{@link #METADATA_KEY_AUTHOR}</li>
556          * <li>{@link #METADATA_KEY_WRITER}</li>
557          * <li>{@link #METADATA_KEY_COMPOSER}</li>
558          * <li>{@link #METADATA_KEY_DATE}</li>
559          * <li>{@link #METADATA_KEY_GENRE}</li>
560          * <li>{@link #METADATA_KEY_ALBUM_ARTIST}</li>
561          * <li>{@link #METADATA_KEY_ART_URI}</li>
562          * <li>{@link #METADATA_KEY_ALBUM_ART_URI}</li>
563          * <li>{@link #METADATA_KEY_DISPLAY_TITLE}</li>
564          * <li>{@link #METADATA_KEY_DISPLAY_SUBTITLE}</li>
565          * <li>{@link #METADATA_KEY_DISPLAY_DESCRIPTION}</li>
566          * <li>{@link #METADATA_KEY_DISPLAY_ICON_URI}</li>
567          * </ul>
568          *
569          * @param key The key for referencing this value
570          * @param value The CharSequence value to store
571          * @return The Builder to allow chaining
572          */
putText(String key, CharSequence value)573         public Builder putText(String key, CharSequence value) {
574             if (METADATA_KEYS_TYPE.containsKey(key)) {
575                 if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_TEXT) {
576                     throw new IllegalArgumentException("The " + key
577                             + " key cannot be used to put a CharSequence");
578                 }
579             }
580             mBundle.putCharSequence(key, value);
581             return this;
582         }
583 
584         /**
585          * Put a String value into the metadata. Custom keys may be used, but if
586          * the METADATA_KEYs defined in this class are used they may only be one
587          * of the following:
588          * <ul>
589          * <li>{@link #METADATA_KEY_TITLE}</li>
590          * <li>{@link #METADATA_KEY_ARTIST}</li>
591          * <li>{@link #METADATA_KEY_ALBUM}</li>
592          * <li>{@link #METADATA_KEY_AUTHOR}</li>
593          * <li>{@link #METADATA_KEY_WRITER}</li>
594          * <li>{@link #METADATA_KEY_COMPOSER}</li>
595          * <li>{@link #METADATA_KEY_DATE}</li>
596          * <li>{@link #METADATA_KEY_GENRE}</li>
597          * <li>{@link #METADATA_KEY_ALBUM_ARTIST}</li>
598          * <li>{@link #METADATA_KEY_ART_URI}</li>
599          * <li>{@link #METADATA_KEY_ALBUM_ART_URI}</li>
600          * <li>{@link #METADATA_KEY_DISPLAY_TITLE}</li>
601          * <li>{@link #METADATA_KEY_DISPLAY_SUBTITLE}</li>
602          * <li>{@link #METADATA_KEY_DISPLAY_DESCRIPTION}</li>
603          * <li>{@link #METADATA_KEY_DISPLAY_ICON_URI}</li>
604          * </ul>
605          *
606          * @param key The key for referencing this value
607          * @param value The String value to store
608          * @return The Builder to allow chaining
609          */
putString(String key, String value)610         public Builder putString(String key, String value) {
611             if (METADATA_KEYS_TYPE.containsKey(key)) {
612                 if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_TEXT) {
613                     throw new IllegalArgumentException("The " + key
614                             + " key cannot be used to put a String");
615                 }
616             }
617             mBundle.putCharSequence(key, value);
618             return this;
619         }
620 
621         /**
622          * Put a long value into the metadata. Custom keys may be used, but if
623          * the METADATA_KEYs defined in this class are used they may only be one
624          * of the following:
625          * <ul>
626          * <li>{@link #METADATA_KEY_DURATION}</li>
627          * <li>{@link #METADATA_KEY_TRACK_NUMBER}</li>
628          * <li>{@link #METADATA_KEY_NUM_TRACKS}</li>
629          * <li>{@link #METADATA_KEY_DISC_NUMBER}</li>
630          * <li>{@link #METADATA_KEY_YEAR}</li>
631          * </ul>
632          *
633          * @param key The key for referencing this value
634          * @param value The long value to store
635          * @return The Builder to allow chaining
636          */
putLong(String key, long value)637         public Builder putLong(String key, long value) {
638             if (METADATA_KEYS_TYPE.containsKey(key)) {
639                 if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_LONG) {
640                     throw new IllegalArgumentException("The " + key
641                             + " key cannot be used to put a long");
642                 }
643             }
644             mBundle.putLong(key, value);
645             return this;
646         }
647 
648         /**
649          * Put a {@link Rating} into the metadata. Custom keys may be used, but
650          * if the METADATA_KEYs defined in this class are used they may only be
651          * one of the following:
652          * <ul>
653          * <li>{@link #METADATA_KEY_RATING}</li>
654          * <li>{@link #METADATA_KEY_USER_RATING}</li>
655          * </ul>
656          *
657          * @param key The key for referencing this value
658          * @param value The Rating value to store
659          * @return The Builder to allow chaining
660          */
putRating(String key, Rating value)661         public Builder putRating(String key, Rating value) {
662             if (METADATA_KEYS_TYPE.containsKey(key)) {
663                 if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_RATING) {
664                     throw new IllegalArgumentException("The " + key
665                             + " key cannot be used to put a Rating");
666                 }
667             }
668             mBundle.putParcelable(key, value);
669             return this;
670         }
671 
672         /**
673          * Put a {@link Bitmap} into the metadata. Custom keys may be used, but
674          * if the METADATA_KEYs defined in this class are used they may only be
675          * one of the following:
676          * <ul>
677          * <li>{@link #METADATA_KEY_ART}</li>
678          * <li>{@link #METADATA_KEY_ALBUM_ART}</li>
679          * <li>{@link #METADATA_KEY_DISPLAY_ICON}</li>
680          * </ul>
681          *
682          * @param key The key for referencing this value
683          * @param value The Bitmap to store
684          * @return The Builder to allow chaining
685          */
putBitmap(String key, Bitmap value)686         public Builder putBitmap(String key, Bitmap value) {
687             if (METADATA_KEYS_TYPE.containsKey(key)) {
688                 if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_BITMAP) {
689                     throw new IllegalArgumentException("The " + key
690                             + " key cannot be used to put a Bitmap");
691                 }
692             }
693             mBundle.putParcelable(key, value);
694             return this;
695         }
696 
697         /**
698          * Creates a {@link MediaMetadata} instance with the specified fields.
699          *
700          * @return The new MediaMetadata instance
701          */
build()702         public MediaMetadata build() {
703             return new MediaMetadata(mBundle);
704         }
705     }
706 }
707