/**
  * Returns an object representation of the value for the key
  *
  * @param key one of the keys supported in {@link #putObject(int, Object)}
  * @param defaultValue the value returned if the key is not present
  * @return the object for the key, as a {@link Long}, {@link Bitmap}, {@link String}, or {@link
  *     Rating} depending on the key value, or the supplied default value if the key is not present
  * @throws IllegalArgumentException
  */
 public synchronized Object getObject(int key, Object defaultValue)
     throws IllegalArgumentException {
   switch (METADATA_KEYS_TYPE.get(key, METADATA_TYPE_INVALID)) {
     case METADATA_TYPE_LONG:
       if (mEditorMetadata.containsKey(String.valueOf(key))) {
         return mEditorMetadata.getLong(String.valueOf(key));
       } else {
         return defaultValue;
       }
     case METADATA_TYPE_STRING:
       if (mEditorMetadata.containsKey(String.valueOf(key))) {
         return mEditorMetadata.getString(String.valueOf(key));
       } else {
         return defaultValue;
       }
     case METADATA_TYPE_RATING:
       if (mEditorMetadata.containsKey(String.valueOf(key))) {
         return mEditorMetadata.getParcelable(String.valueOf(key));
       } else {
         return defaultValue;
       }
     case METADATA_TYPE_BITMAP:
       // only one key for Bitmap supported, value is not stored in mEditorMetadata Bundle
       if (key == BITMAP_KEY_ARTWORK) {
         return (mEditorArtwork != null ? mEditorArtwork : defaultValue);
       } // else: fall through to invalid key handling
     default:
       throw (new IllegalArgumentException("Invalid key " + key));
   }
 }
 /**
  * Adds information stored as an instance. Note that none of the information added after {@link
  * #apply()} has been called will be available to consumers of metadata stored by the
  * MediaMetadataEditor.
  *
  * @param key the identifier of a the metadata field to set. Valid keys for a:
  *     <ul>
  *       <li>{@link Bitmap} object are {@link #BITMAP_KEY_ARTWORK},
  *       <li>{@link String} object are the same as for {@link #putString(int, String)}
  *       <li>{@link Long} object are the same as for {@link #putLong(int, long)}
  *       <li>{@link Rating} object are {@link #RATING_KEY_BY_OTHERS} and {@link
  *           #RATING_KEY_BY_USER}.
  *     </ul>
  *
  * @param value the metadata to add.
  * @return Returns a reference to the same MediaMetadataEditor object, so you can chain put calls
  *     together.
  * @throws IllegalArgumentException
  */
 public synchronized MediaMetadataEditor putObject(int key, Object value)
     throws IllegalArgumentException {
   if (mApplied) {
     Log.e(TAG, "Can't edit a previously applied MediaMetadataEditor");
     return this;
   }
   switch (METADATA_KEYS_TYPE.get(key, METADATA_TYPE_INVALID)) {
     case METADATA_TYPE_LONG:
       if (value instanceof Long) {
         return putLong(key, ((Long) value).longValue());
       } else {
         throw (new IllegalArgumentException("Not a non-null Long for key " + key));
       }
     case METADATA_TYPE_STRING:
       if ((value == null) || (value instanceof String)) {
         return putString(key, (String) value);
       } else {
         throw (new IllegalArgumentException("Not a String for key " + key));
       }
     case METADATA_TYPE_RATING:
       mEditorMetadata.putParcelable(String.valueOf(key), (Parcelable) value);
       mMetadataChanged = true;
       break;
     case METADATA_TYPE_BITMAP:
       if ((value == null) || (value instanceof Bitmap)) {
         return putBitmap(key, (Bitmap) value);
       } else {
         throw (new IllegalArgumentException("Not a Bitmap for key " + key));
       }
     default:
       throw (new IllegalArgumentException("Invalid key " + key));
   }
   return this;
 }
 /**
  * Returns the {@link String} value for the key.
  *
  * @param key one of the keys supported in {@link #putString(int, String)}
  * @param defaultValue the value returned if the key is not present
  * @return the {@link String} value for the key, or the supplied default value if the key is not
  *     present
  * @throws IllegalArgumentException
  */
 public synchronized String getString(int key, String defaultValue)
     throws IllegalArgumentException {
   if (METADATA_KEYS_TYPE.get(key, METADATA_TYPE_INVALID) != METADATA_TYPE_STRING) {
     throw (new IllegalArgumentException("Invalid type 'String' for key " + key));
   }
   return mEditorMetadata.getString(String.valueOf(key), defaultValue);
 }
 /**
  * Adds numerical information. Note that none of the information added after {@link #apply()} has
  * been called will be available to consumers of metadata stored by the MediaMetadataEditor.
  *
  * @param key the identifier of a the metadata field to set. Valid values are {@link
  *     android.media.MediaMetadataRetriever#METADATA_KEY_CD_TRACK_NUMBER}, {@link
  *     android.media.MediaMetadataRetriever#METADATA_KEY_DISC_NUMBER}, {@link
  *     android.media.MediaMetadataRetriever#METADATA_KEY_DURATION} (with a value expressed in
  *     milliseconds), {@link android.media.MediaMetadataRetriever#METADATA_KEY_YEAR}.
  * @param value The long value for the given key
  * @return Returns a reference to the same MediaMetadataEditor object, so you can chain put calls
  *     together.
  * @throws IllegalArgumentException
  */
 public synchronized MediaMetadataEditor putLong(int key, long value)
     throws IllegalArgumentException {
   if (mApplied) {
     Log.e(TAG, "Can't edit a previously applied MediaMetadataEditor");
     return this;
   }
   if (METADATA_KEYS_TYPE.get(key, METADATA_TYPE_INVALID) != METADATA_TYPE_LONG) {
     throw (new IllegalArgumentException("Invalid type 'long' for key " + key));
   }
   mEditorMetadata.putLong(String.valueOf(key), value);
   mMetadataChanged = true;
   return this;
 }