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