MediaMetadataCompat.java revision ee9a9d6bf32f08c3e396ae8108311a99e1adb0b5
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 */ 16package android.support.v4.media; 17 18import android.graphics.Bitmap; 19import android.net.Uri; 20import android.os.Build; 21import android.os.Bundle; 22import android.os.Parcel; 23import android.os.Parcelable; 24import android.support.annotation.StringDef; 25import android.support.v4.util.ArrayMap; 26import android.support.v4.media.MediaBrowserCompat; 27import android.support.v4.media.session.MediaControllerCompat; 28import android.text.TextUtils; 29import android.util.Log; 30 31import java.lang.annotation.Retention; 32import java.lang.annotation.RetentionPolicy; 33import java.util.Set; 34 35/** 36 * Contains metadata about an item, such as the title, artist, etc. 37 */ 38public final class MediaMetadataCompat implements Parcelable { 39 private static final String TAG = "MediaMetadata"; 40 41 /** 42 * The title of the media. 43 */ 44 public static final String METADATA_KEY_TITLE = "android.media.metadata.TITLE"; 45 46 /** 47 * The artist of the media. 48 */ 49 public static final String METADATA_KEY_ARTIST = "android.media.metadata.ARTIST"; 50 51 /** 52 * The duration of the media in ms. A negative duration indicates that the 53 * duration is unknown (or infinite). 54 */ 55 public static final String METADATA_KEY_DURATION = "android.media.metadata.DURATION"; 56 57 /** 58 * The album title for the media. 59 */ 60 public static final String METADATA_KEY_ALBUM = "android.media.metadata.ALBUM"; 61 62 /** 63 * The author of the media. 64 */ 65 public static final String METADATA_KEY_AUTHOR = "android.media.metadata.AUTHOR"; 66 67 /** 68 * The writer of the media. 69 */ 70 public static final String METADATA_KEY_WRITER = "android.media.metadata.WRITER"; 71 72 /** 73 * The composer of the media. 74 */ 75 public static final String METADATA_KEY_COMPOSER = "android.media.metadata.COMPOSER"; 76 77 /** 78 * The compilation status of the media. 79 */ 80 public static final String METADATA_KEY_COMPILATION = "android.media.metadata.COMPILATION"; 81 82 /** 83 * The date the media was created or published. The format is unspecified 84 * but RFC 3339 is recommended. 85 */ 86 public static final String METADATA_KEY_DATE = "android.media.metadata.DATE"; 87 88 /** 89 * The year the media was created or published as a long. 90 */ 91 public static final String METADATA_KEY_YEAR = "android.media.metadata.YEAR"; 92 93 /** 94 * The genre of the media. 95 */ 96 public static final String METADATA_KEY_GENRE = "android.media.metadata.GENRE"; 97 98 /** 99 * The track number for the media. 100 */ 101 public static final String METADATA_KEY_TRACK_NUMBER = "android.media.metadata.TRACK_NUMBER"; 102 103 /** 104 * The number of tracks in the media's original source. 105 */ 106 public static final String METADATA_KEY_NUM_TRACKS = "android.media.metadata.NUM_TRACKS"; 107 108 /** 109 * The disc number for the media's original source. 110 */ 111 public static final String METADATA_KEY_DISC_NUMBER = "android.media.metadata.DISC_NUMBER"; 112 113 /** 114 * The artist for the album of the media's original source. 115 */ 116 public static final String METADATA_KEY_ALBUM_ARTIST = "android.media.metadata.ALBUM_ARTIST"; 117 118 /** 119 * The artwork for the media as a {@link Bitmap}. 120 */ 121 public static final String METADATA_KEY_ART = "android.media.metadata.ART"; 122 123 /** 124 * The artwork for the media as a Uri style String. 125 */ 126 public static final String METADATA_KEY_ART_URI = "android.media.metadata.ART_URI"; 127 128 /** 129 * The artwork for the album of the media's original source as a 130 * {@link Bitmap}. 131 */ 132 public static final String METADATA_KEY_ALBUM_ART = "android.media.metadata.ALBUM_ART"; 133 134 /** 135 * The artwork for the album of the media's original source as a Uri style 136 * String. 137 */ 138 public static final String METADATA_KEY_ALBUM_ART_URI = "android.media.metadata.ALBUM_ART_URI"; 139 140 /** 141 * The user's rating for the media. 142 * 143 * @see RatingCompat 144 */ 145 public static final String METADATA_KEY_USER_RATING = "android.media.metadata.USER_RATING"; 146 147 /** 148 * The overall rating for the media. 149 * 150 * @see RatingCompat 151 */ 152 public static final String METADATA_KEY_RATING = "android.media.metadata.RATING"; 153 154 /** 155 * A title that is suitable for display to the user. This will generally be 156 * the same as {@link #METADATA_KEY_TITLE} but may differ for some formats. 157 * When displaying media described by this metadata this should be preferred 158 * if present. 159 */ 160 public static final String METADATA_KEY_DISPLAY_TITLE = "android.media.metadata.DISPLAY_TITLE"; 161 162 /** 163 * A subtitle that is suitable for display to the user. When displaying a 164 * second line for media described by this metadata this should be preferred 165 * to other fields if present. 166 */ 167 public static final String METADATA_KEY_DISPLAY_SUBTITLE 168 = "android.media.metadata.DISPLAY_SUBTITLE"; 169 170 /** 171 * A description that is suitable for display to the user. When displaying 172 * more information for media described by this metadata this should be 173 * preferred to other fields if present. 174 */ 175 public static final String METADATA_KEY_DISPLAY_DESCRIPTION 176 = "android.media.metadata.DISPLAY_DESCRIPTION"; 177 178 /** 179 * An icon or thumbnail that is suitable for display to the user. When 180 * displaying an icon for media described by this metadata this should be 181 * preferred to other fields if present. This must be a {@link Bitmap}. 182 */ 183 public static final String METADATA_KEY_DISPLAY_ICON 184 = "android.media.metadata.DISPLAY_ICON"; 185 186 /** 187 * An icon or thumbnail that is suitable for display to the user. When 188 * displaying more information for media described by this metadata the 189 * display description should be preferred to other fields when present. 190 * This must be a Uri style String. 191 */ 192 public static final String METADATA_KEY_DISPLAY_ICON_URI 193 = "android.media.metadata.DISPLAY_ICON_URI"; 194 195 /** 196 * A String key for identifying the content. This value is specific to the 197 * service providing the content. If used, this should be a persistent 198 * unique key for the underlying content. 199 */ 200 public static final String METADATA_KEY_MEDIA_ID = "android.media.metadata.MEDIA_ID"; 201 202 /** 203 * A Uri formatted String representing the content. This value is specific to the 204 * service providing the content. It may be used with 205 * {@link MediaControllerCompat.TransportControls#playFromUri(Uri, Bundle)} 206 * to initiate playback when provided by a {@link MediaBrowserCompat} connected to 207 * the same app. 208 */ 209 public static final String METADATA_KEY_MEDIA_URI = "android.media.metadata.MEDIA_URI"; 210 211 /** 212 * The bluetooth folder type of the media specified in the section 6.10.2.2 of the Bluetooth 213 * AVRCP 1.5. It should be one of the following: 214 * <ul> 215 * <li>{@link MediaDescriptionCompat#BT_FOLDER_TYPE_MIXED}</li> 216 * <li>{@link MediaDescriptionCompat#BT_FOLDER_TYPE_TITLES}</li> 217 * <li>{@link MediaDescriptionCompat#BT_FOLDER_TYPE_ALBUMS}</li> 218 * <li>{@link MediaDescriptionCompat#BT_FOLDER_TYPE_ARTISTS}</li> 219 * <li>{@link MediaDescriptionCompat#BT_FOLDER_TYPE_GENRES}</li> 220 * <li>{@link MediaDescriptionCompat#BT_FOLDER_TYPE_PLAYLISTS}</li> 221 * <li>{@link MediaDescriptionCompat#BT_FOLDER_TYPE_YEARS}</li> 222 * </ul> 223 */ 224 public static final String METADATA_KEY_BT_FOLDER_TYPE 225 = "android.media.metadata.BT_FOLDER_TYPE"; 226 227 /** 228 * @hide 229 */ 230 @StringDef({METADATA_KEY_TITLE, METADATA_KEY_ARTIST, METADATA_KEY_ALBUM, METADATA_KEY_AUTHOR, 231 METADATA_KEY_WRITER, METADATA_KEY_COMPOSER, METADATA_KEY_COMPILATION, 232 METADATA_KEY_DATE, METADATA_KEY_GENRE, METADATA_KEY_ALBUM_ARTIST, METADATA_KEY_ART_URI, 233 METADATA_KEY_ALBUM_ART_URI, METADATA_KEY_DISPLAY_TITLE, METADATA_KEY_DISPLAY_SUBTITLE, 234 METADATA_KEY_DISPLAY_DESCRIPTION, METADATA_KEY_DISPLAY_ICON_URI, 235 METADATA_KEY_MEDIA_ID, METADATA_KEY_MEDIA_URI}) 236 @Retention(RetentionPolicy.SOURCE) 237 public @interface TextKey {} 238 239 /** 240 * @hide 241 */ 242 @StringDef({METADATA_KEY_DURATION, METADATA_KEY_YEAR, METADATA_KEY_TRACK_NUMBER, 243 METADATA_KEY_NUM_TRACKS, METADATA_KEY_DISC_NUMBER, METADATA_KEY_BT_FOLDER_TYPE}) 244 @Retention(RetentionPolicy.SOURCE) 245 public @interface LongKey {} 246 247 /** 248 * @hide 249 */ 250 @StringDef({METADATA_KEY_ART, METADATA_KEY_ALBUM_ART, METADATA_KEY_DISPLAY_ICON}) 251 @Retention(RetentionPolicy.SOURCE) 252 public @interface BitmapKey {} 253 254 /** 255 * @hide 256 */ 257 @StringDef({METADATA_KEY_USER_RATING, METADATA_KEY_RATING}) 258 @Retention(RetentionPolicy.SOURCE) 259 public @interface RatingKey {} 260 261 private static final int METADATA_TYPE_LONG = 0; 262 private static final int METADATA_TYPE_TEXT = 1; 263 private static final int METADATA_TYPE_BITMAP = 2; 264 private static final int METADATA_TYPE_RATING = 3; 265 private static final ArrayMap<String, Integer> METADATA_KEYS_TYPE; 266 267 static { 268 METADATA_KEYS_TYPE = new ArrayMap<String, Integer>(); 269 METADATA_KEYS_TYPE.put(METADATA_KEY_TITLE, METADATA_TYPE_TEXT); 270 METADATA_KEYS_TYPE.put(METADATA_KEY_ARTIST, METADATA_TYPE_TEXT); 271 METADATA_KEYS_TYPE.put(METADATA_KEY_DURATION, METADATA_TYPE_LONG); 272 METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM, METADATA_TYPE_TEXT); 273 METADATA_KEYS_TYPE.put(METADATA_KEY_AUTHOR, METADATA_TYPE_TEXT); 274 METADATA_KEYS_TYPE.put(METADATA_KEY_WRITER, METADATA_TYPE_TEXT); 275 METADATA_KEYS_TYPE.put(METADATA_KEY_COMPOSER, METADATA_TYPE_TEXT); 276 METADATA_KEYS_TYPE.put(METADATA_KEY_COMPILATION, METADATA_TYPE_TEXT); 277 METADATA_KEYS_TYPE.put(METADATA_KEY_DATE, METADATA_TYPE_TEXT); 278 METADATA_KEYS_TYPE.put(METADATA_KEY_YEAR, METADATA_TYPE_LONG); 279 METADATA_KEYS_TYPE.put(METADATA_KEY_GENRE, METADATA_TYPE_TEXT); 280 METADATA_KEYS_TYPE.put(METADATA_KEY_TRACK_NUMBER, METADATA_TYPE_LONG); 281 METADATA_KEYS_TYPE.put(METADATA_KEY_NUM_TRACKS, METADATA_TYPE_LONG); 282 METADATA_KEYS_TYPE.put(METADATA_KEY_DISC_NUMBER, METADATA_TYPE_LONG); 283 METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM_ARTIST, METADATA_TYPE_TEXT); 284 METADATA_KEYS_TYPE.put(METADATA_KEY_ART, METADATA_TYPE_BITMAP); 285 METADATA_KEYS_TYPE.put(METADATA_KEY_ART_URI, METADATA_TYPE_TEXT); 286 METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM_ART, METADATA_TYPE_BITMAP); 287 METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM_ART_URI, METADATA_TYPE_TEXT); 288 METADATA_KEYS_TYPE.put(METADATA_KEY_USER_RATING, METADATA_TYPE_RATING); 289 METADATA_KEYS_TYPE.put(METADATA_KEY_RATING, METADATA_TYPE_RATING); 290 METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_TITLE, METADATA_TYPE_TEXT); 291 METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_SUBTITLE, METADATA_TYPE_TEXT); 292 METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_DESCRIPTION, METADATA_TYPE_TEXT); 293 METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_ICON, METADATA_TYPE_BITMAP); 294 METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_ICON_URI, METADATA_TYPE_TEXT); 295 METADATA_KEYS_TYPE.put(METADATA_KEY_MEDIA_ID, METADATA_TYPE_TEXT); 296 METADATA_KEYS_TYPE.put(METADATA_KEY_BT_FOLDER_TYPE, METADATA_TYPE_LONG); 297 METADATA_KEYS_TYPE.put(METADATA_KEY_MEDIA_URI, METADATA_TYPE_TEXT); 298 } 299 300 private static final @TextKey String[] PREFERRED_DESCRIPTION_ORDER = { 301 METADATA_KEY_TITLE, 302 METADATA_KEY_ARTIST, 303 METADATA_KEY_ALBUM, 304 METADATA_KEY_ALBUM_ARTIST, 305 METADATA_KEY_WRITER, 306 METADATA_KEY_AUTHOR, 307 METADATA_KEY_COMPOSER 308 }; 309 310 private static final @BitmapKey String[] PREFERRED_BITMAP_ORDER = { 311 METADATA_KEY_DISPLAY_ICON, 312 METADATA_KEY_ART, 313 METADATA_KEY_ALBUM_ART 314 }; 315 316 private static final @TextKey String[] PREFERRED_URI_ORDER = { 317 METADATA_KEY_DISPLAY_ICON_URI, 318 METADATA_KEY_ART_URI, 319 METADATA_KEY_ALBUM_ART_URI 320 }; 321 322 private final Bundle mBundle; 323 private Object mMetadataObj; 324 private MediaDescriptionCompat mDescription; 325 326 private MediaMetadataCompat(Bundle bundle) { 327 mBundle = new Bundle(bundle); 328 } 329 330 private MediaMetadataCompat(Parcel in) { 331 mBundle = in.readBundle(); 332 } 333 334 /** 335 * Returns true if the given key is contained in the metadata 336 * 337 * @param key a String key 338 * @return true if the key exists in this metadata, false otherwise 339 */ 340 public boolean containsKey(String key) { 341 return mBundle.containsKey(key); 342 } 343 344 /** 345 * Returns the value associated with the given key, or null if no mapping of 346 * the desired type exists for the given key or a null value is explicitly 347 * associated with the key. 348 * 349 * @param key The key the value is stored under 350 * @return a CharSequence value, or null 351 */ 352 public CharSequence getText(@TextKey String key) { 353 return mBundle.getCharSequence(key); 354 } 355 356 /** 357 * Returns the value associated with the given key, or null if no mapping of 358 * the desired type exists for the given key or a null value is explicitly 359 * associated with the key. 360 * 361 * @param key The key the value is stored under 362 * @return a String value, or null 363 */ 364 public String getString(@TextKey String key) { 365 CharSequence text = mBundle.getCharSequence(key); 366 if (text != null) { 367 return text.toString(); 368 } 369 return null; 370 } 371 372 /** 373 * Returns the value associated with the given key, or 0L if no long exists 374 * for the given key. 375 * 376 * @param key The key the value is stored under 377 * @return a long value 378 */ 379 public long getLong(@LongKey String key) { 380 return mBundle.getLong(key, 0); 381 } 382 383 /** 384 * Return a {@link RatingCompat} for the given key or null if no rating exists for 385 * the given key. 386 * 387 * @param key The key the value is stored under 388 * @return A {@link RatingCompat} or null 389 */ 390 public RatingCompat getRating(@RatingKey String key) { 391 RatingCompat rating = null; 392 try { 393 if (Build.VERSION.SDK_INT >= 19) { 394 // On platform version 19 or higher, mBundle stores a Rating object. Convert it to 395 // RatingCompat. 396 rating = RatingCompat.fromRating(mBundle.getParcelable(key)); 397 } else { 398 rating = mBundle.getParcelable(key); 399 } 400 } catch (Exception e) { 401 // ignore, value was not a bitmap 402 Log.w(TAG, "Failed to retrieve a key as Rating.", e); 403 } 404 return rating; 405 } 406 407 /** 408 * Return a {@link Bitmap} for the given key or null if no bitmap exists for 409 * the given key. 410 * 411 * @param key The key the value is stored under 412 * @return A {@link Bitmap} or null 413 */ 414 public Bitmap getBitmap(@BitmapKey String key) { 415 Bitmap bmp = null; 416 try { 417 bmp = mBundle.getParcelable(key); 418 } catch (Exception e) { 419 // ignore, value was not a bitmap 420 Log.w(TAG, "Failed to retrieve a key as Bitmap.", e); 421 } 422 return bmp; 423 } 424 425 /** 426 * Returns a simple description of this metadata for display purposes. 427 * 428 * @return A simple description of this metadata. 429 */ 430 public MediaDescriptionCompat getDescription() { 431 if (mDescription != null) { 432 return mDescription; 433 } 434 435 String mediaId = getString(METADATA_KEY_MEDIA_ID); 436 437 CharSequence[] text = new CharSequence[3]; 438 Bitmap icon = null; 439 Uri iconUri = null; 440 441 // First handle the case where display data is set already 442 CharSequence displayText = getText(METADATA_KEY_DISPLAY_TITLE); 443 if (!TextUtils.isEmpty(displayText)) { 444 // If they have a display title use only display data, otherwise use 445 // our best bets 446 text[0] = displayText; 447 text[1] = getText(METADATA_KEY_DISPLAY_SUBTITLE); 448 text[2] = getText(METADATA_KEY_DISPLAY_DESCRIPTION); 449 } else { 450 // Use whatever fields we can 451 int textIndex = 0; 452 int keyIndex = 0; 453 while (textIndex < text.length && keyIndex < PREFERRED_DESCRIPTION_ORDER.length) { 454 CharSequence next = getText(PREFERRED_DESCRIPTION_ORDER[keyIndex++]); 455 if (!TextUtils.isEmpty(next)) { 456 // Fill in the next empty bit of text 457 text[textIndex++] = next; 458 } 459 } 460 } 461 462 // Get the best art bitmap we can find 463 for (int i = 0; i < PREFERRED_BITMAP_ORDER.length; i++) { 464 Bitmap next = getBitmap(PREFERRED_BITMAP_ORDER[i]); 465 if (next != null) { 466 icon = next; 467 break; 468 } 469 } 470 471 // Get the best Uri we can find 472 for (int i = 0; i < PREFERRED_URI_ORDER.length; i++) { 473 String next = getString(PREFERRED_URI_ORDER[i]); 474 if (!TextUtils.isEmpty(next)) { 475 iconUri = Uri.parse(next); 476 break; 477 } 478 } 479 480 Uri mediaUri = null; 481 String mediaUriStr = getString(METADATA_KEY_MEDIA_URI); 482 if (!TextUtils.isEmpty(mediaUriStr)) { 483 mediaUri = Uri.parse(mediaUriStr); 484 } 485 486 MediaDescriptionCompat.Builder bob = new MediaDescriptionCompat.Builder(); 487 bob.setMediaId(mediaId); 488 bob.setTitle(text[0]); 489 bob.setSubtitle(text[1]); 490 bob.setDescription(text[2]); 491 bob.setIconBitmap(icon); 492 bob.setIconUri(iconUri); 493 bob.setMediaUri(mediaUri); 494 if (mBundle.containsKey(METADATA_KEY_BT_FOLDER_TYPE)) { 495 Bundle bundle = new Bundle(); 496 bundle.putLong(MediaDescriptionCompat.EXTRA_BT_FOLDER_TYPE, 497 getLong(METADATA_KEY_BT_FOLDER_TYPE)); 498 bob.setExtras(bundle); 499 } 500 mDescription = bob.build(); 501 502 return mDescription; 503 } 504 505 @Override 506 public int describeContents() { 507 return 0; 508 } 509 510 @Override 511 public void writeToParcel(Parcel dest, int flags) { 512 dest.writeBundle(mBundle); 513 } 514 515 /** 516 * Get the number of fields in this metadata. 517 * 518 * @return The number of fields in the metadata. 519 */ 520 public int size() { 521 return mBundle.size(); 522 } 523 524 /** 525 * Returns a Set containing the Strings used as keys in this metadata. 526 * 527 * @return a Set of String keys 528 */ 529 public Set<String> keySet() { 530 return mBundle.keySet(); 531 } 532 533 /** 534 * Gets the bundle backing the metadata object. This is available to support 535 * backwards compatibility. Apps should not modify the bundle directly. 536 * 537 * @return The Bundle backing this metadata. 538 */ 539 public Bundle getBundle() { 540 return mBundle; 541 } 542 543 /** 544 * Creates an instance from a framework {@link android.media.MediaMetadata} 545 * object. 546 * <p> 547 * This method is only supported on 548 * {@link android.os.Build.VERSION_CODES#LOLLIPOP} and later. 549 * </p> 550 * 551 * @param metadataObj A {@link android.media.MediaMetadata} object, or null 552 * if none. 553 * @return An equivalent {@link MediaMetadataCompat} object, or null if 554 * none. 555 */ 556 public static MediaMetadataCompat fromMediaMetadata(Object metadataObj) { 557 if (metadataObj == null || Build.VERSION.SDK_INT < 21) { 558 return null; 559 } 560 561 Parcel p = Parcel.obtain(); 562 MediaMetadataCompatApi21.writeToParcel(metadataObj, p, 0); 563 p.setDataPosition(0); 564 MediaMetadataCompat metadata = MediaMetadataCompat.CREATOR.createFromParcel(p); 565 p.recycle(); 566 metadata.mMetadataObj = metadataObj; 567 return metadata; 568 } 569 570 /** 571 * Gets the underlying framework {@link android.media.MediaMetadata} object. 572 * <p> 573 * This method is only supported on 574 * {@link android.os.Build.VERSION_CODES#LOLLIPOP} and later. 575 * </p> 576 * 577 * @return An equivalent {@link android.media.MediaMetadata} object, or null 578 * if none. 579 */ 580 public Object getMediaMetadata() { 581 if (mMetadataObj != null || Build.VERSION.SDK_INT < 21) { 582 return mMetadataObj; 583 } 584 585 Parcel p = Parcel.obtain(); 586 writeToParcel(p, 0); 587 p.setDataPosition(0); 588 mMetadataObj = MediaMetadataCompatApi21.createFromParcel(p); 589 p.recycle(); 590 return mMetadataObj; 591 } 592 593 public static final Parcelable.Creator<MediaMetadataCompat> CREATOR = 594 new Parcelable.Creator<MediaMetadataCompat>() { 595 @Override 596 public MediaMetadataCompat createFromParcel(Parcel in) { 597 return new MediaMetadataCompat(in); 598 } 599 600 @Override 601 public MediaMetadataCompat[] newArray(int size) { 602 return new MediaMetadataCompat[size]; 603 } 604 }; 605 606 /** 607 * Use to build MediaMetadata objects. The system defined metadata keys must 608 * use the appropriate data type. 609 */ 610 public static final class Builder { 611 private final Bundle mBundle; 612 613 /** 614 * Create an empty Builder. Any field that should be included in the 615 * {@link MediaMetadataCompat} must be added. 616 */ 617 public Builder() { 618 mBundle = new Bundle(); 619 } 620 621 /** 622 * Create a Builder using a {@link MediaMetadataCompat} instance to set the 623 * initial values. All fields in the source metadata will be included in 624 * the new metadata. Fields can be overwritten by adding the same key. 625 * 626 * @param source 627 */ 628 public Builder(MediaMetadataCompat source) { 629 mBundle = new Bundle(source.mBundle); 630 } 631 632 /** 633 * Put a CharSequence value into the metadata. Custom keys may be used, 634 * but if the METADATA_KEYs defined in this class are used they may only 635 * be one of the following: 636 * <ul> 637 * <li>{@link #METADATA_KEY_TITLE}</li> 638 * <li>{@link #METADATA_KEY_ARTIST}</li> 639 * <li>{@link #METADATA_KEY_ALBUM}</li> 640 * <li>{@link #METADATA_KEY_AUTHOR}</li> 641 * <li>{@link #METADATA_KEY_WRITER}</li> 642 * <li>{@link #METADATA_KEY_COMPOSER}</li> 643 * <li>{@link #METADATA_KEY_DATE}</li> 644 * <li>{@link #METADATA_KEY_GENRE}</li> 645 * <li>{@link #METADATA_KEY_ALBUM_ARTIST}</li> 646 * <li>{@link #METADATA_KEY_ART_URI}</li> 647 * <li>{@link #METADATA_KEY_ALBUM_ART_URI}</li> 648 * <li>{@link #METADATA_KEY_DISPLAY_TITLE}</li> 649 * <li>{@link #METADATA_KEY_DISPLAY_SUBTITLE}</li> 650 * <li>{@link #METADATA_KEY_DISPLAY_DESCRIPTION}</li> 651 * <li>{@link #METADATA_KEY_DISPLAY_ICON_URI}</li> 652 * </ul> 653 * 654 * @param key The key for referencing this value 655 * @param value The CharSequence value to store 656 * @return The Builder to allow chaining 657 */ 658 public Builder putText(@TextKey String key, CharSequence value) { 659 if (METADATA_KEYS_TYPE.containsKey(key)) { 660 if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_TEXT) { 661 throw new IllegalArgumentException("The " + key 662 + " key cannot be used to put a CharSequence"); 663 } 664 } 665 mBundle.putCharSequence(key, value); 666 return this; 667 } 668 669 /** 670 * Put a String value into the metadata. Custom keys may be used, but if 671 * the METADATA_KEYs defined in this class are used they may only be one 672 * of the following: 673 * <ul> 674 * <li>{@link #METADATA_KEY_TITLE}</li> 675 * <li>{@link #METADATA_KEY_ARTIST}</li> 676 * <li>{@link #METADATA_KEY_ALBUM}</li> 677 * <li>{@link #METADATA_KEY_AUTHOR}</li> 678 * <li>{@link #METADATA_KEY_WRITER}</li> 679 * <li>{@link #METADATA_KEY_COMPOSER}</li> 680 * <li>{@link #METADATA_KEY_DATE}</li> 681 * <li>{@link #METADATA_KEY_GENRE}</li> 682 * <li>{@link #METADATA_KEY_ALBUM_ARTIST}</li> 683 * <li>{@link #METADATA_KEY_ART_URI}</li> 684 * <li>{@link #METADATA_KEY_ALBUM_ART_URI}</li> 685 * <li>{@link #METADATA_KEY_DISPLAY_TITLE}</li> 686 * <li>{@link #METADATA_KEY_DISPLAY_SUBTITLE}</li> 687 * <li>{@link #METADATA_KEY_DISPLAY_DESCRIPTION}</li> 688 * <li>{@link #METADATA_KEY_DISPLAY_ICON_URI}</li> 689 * </ul> 690 * 691 * @param key The key for referencing this value 692 * @param value The String value to store 693 * @return The Builder to allow chaining 694 */ 695 public Builder putString(@TextKey String key, String value) { 696 if (METADATA_KEYS_TYPE.containsKey(key)) { 697 if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_TEXT) { 698 throw new IllegalArgumentException("The " + key 699 + " key cannot be used to put a String"); 700 } 701 } 702 mBundle.putCharSequence(key, value); 703 return this; 704 } 705 706 /** 707 * Put a long value into the metadata. Custom keys may be used, but if 708 * the METADATA_KEYs defined in this class are used they may only be one 709 * of the following: 710 * <ul> 711 * <li>{@link #METADATA_KEY_DURATION}</li> 712 * <li>{@link #METADATA_KEY_TRACK_NUMBER}</li> 713 * <li>{@link #METADATA_KEY_NUM_TRACKS}</li> 714 * <li>{@link #METADATA_KEY_DISC_NUMBER}</li> 715 * <li>{@link #METADATA_KEY_YEAR}</li> 716 * </ul> 717 * 718 * @param key The key for referencing this value 719 * @param value The String value to store 720 * @return The Builder to allow chaining 721 */ 722 public Builder putLong(@LongKey String key, long value) { 723 if (METADATA_KEYS_TYPE.containsKey(key)) { 724 if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_LONG) { 725 throw new IllegalArgumentException("The " + key 726 + " key cannot be used to put a long"); 727 } 728 } 729 mBundle.putLong(key, value); 730 return this; 731 } 732 733 /** 734 * Put a {@link RatingCompat} into the metadata. Custom keys may be used, but 735 * if the METADATA_KEYs defined in this class are used they may only be 736 * one of the following: 737 * <ul> 738 * <li>{@link #METADATA_KEY_RATING}</li> 739 * <li>{@link #METADATA_KEY_USER_RATING}</li> 740 * </ul> 741 * 742 * @param key The key for referencing this value 743 * @param value The String value to store 744 * @return The Builder to allow chaining 745 */ 746 public Builder putRating(@RatingKey String key, RatingCompat value) { 747 if (METADATA_KEYS_TYPE.containsKey(key)) { 748 if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_RATING) { 749 throw new IllegalArgumentException("The " + key 750 + " key cannot be used to put a Rating"); 751 } 752 } 753 if (Build.VERSION.SDK_INT >= 19) { 754 // On platform version 19 or higher, use Rating instead of RatingCompat so mBundle 755 // can be unmarshalled. 756 mBundle.putParcelable(key, (Parcelable) value.getRating()); 757 } else { 758 mBundle.putParcelable(key, value); 759 } 760 return this; 761 } 762 763 /** 764 * Put a {@link Bitmap} into the metadata. Custom keys may be used, but 765 * if the METADATA_KEYs defined in this class are used they may only be 766 * one of the following: 767 * <ul> 768 * <li>{@link #METADATA_KEY_ART}</li> 769 * <li>{@link #METADATA_KEY_ALBUM_ART}</li> 770 * <li>{@link #METADATA_KEY_DISPLAY_ICON}</li> 771 * </ul> 772 * 773 * @param key The key for referencing this value 774 * @param value The Bitmap to store 775 * @return The Builder to allow chaining 776 */ 777 public Builder putBitmap(@BitmapKey String key, Bitmap value) { 778 if (METADATA_KEYS_TYPE.containsKey(key)) { 779 if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_BITMAP) { 780 throw new IllegalArgumentException("The " + key 781 + " key cannot be used to put a Bitmap"); 782 } 783 } 784 mBundle.putParcelable(key, value); 785 return this; 786 } 787 788 /** 789 * Creates a {@link MediaMetadataCompat} instance with the specified fields. 790 * 791 * @return The new MediaMetadata instance 792 */ 793 public MediaMetadataCompat build() { 794 return new MediaMetadataCompat(mBundle); 795 } 796 } 797 798} 799