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