blob: 8512dbe8d224237b23ae24855d0fad7c067bf67b [file] [log] [blame]
RoboErik8ae0f342014-02-24 18:02:08 -08001/*
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 */
RoboErik42ea7ee2014-05-16 16:27:35 -070016package android.media;
RoboErik8ae0f342014-02-24 18:02:08 -080017
RoboErik75847b92014-07-29 13:10:17 -070018import android.annotation.NonNull;
Insun Kang7c090d52016-02-29 10:51:24 +090019import android.annotation.StringDef;
Mathew Inwood31a792a2018-08-17 08:54:26 +010020import android.annotation.UnsupportedAppUsage;
RoboErik3625bf72014-08-27 16:03:19 -070021import android.content.ContentResolver;
RoboErik8ae0f342014-02-24 18:02:08 -080022import android.graphics.Bitmap;
RoboErik3625bf72014-08-27 16:03:19 -070023import android.graphics.BitmapFactory;
24import android.media.browse.MediaBrowser;
25import android.media.session.MediaController;
RoboErik75847b92014-07-29 13:10:17 -070026import android.net.Uri;
RoboErik8ae0f342014-02-24 18:02:08 -080027import android.os.Bundle;
28import android.os.Parcel;
29import android.os.Parcelable;
RoboErik75847b92014-07-29 13:10:17 -070030import android.text.TextUtils;
RoboErik8ae0f342014-02-24 18:02:08 -080031import android.util.ArrayMap;
32import android.util.Log;
RoboErikf1372422014-04-23 14:38:17 -070033import android.util.SparseArray;
RoboErik8ae0f342014-02-24 18:02:08 -080034
Insun Kang7c090d52016-02-29 10:51:24 +090035import java.lang.annotation.Retention;
36import java.lang.annotation.RetentionPolicy;
Ajay Panicker6e1d2302017-11-09 10:16:35 -080037import java.util.Objects;
Hyundo Moon3e8c1c92019-01-11 16:40:52 +090038import java.util.Set;
RoboErik79fa4632014-05-27 16:49:09 -070039
RoboErik8ae0f342014-02-24 18:02:08 -080040/**
41 * Contains metadata about an item, such as the title, artist, etc.
42 */
43public final class MediaMetadata implements Parcelable {
44 private static final String TAG = "MediaMetadata";
45
46 /**
Insun Kang7c090d52016-02-29 10:51:24 +090047 * @hide
48 */
Jeff Sharkey5db9a912017-12-08 17:32:32 -070049 @StringDef(prefix = { "METADATA_KEY_" }, value = {
50 METADATA_KEY_TITLE,
51 METADATA_KEY_ARTIST,
52 METADATA_KEY_ALBUM,
53 METADATA_KEY_AUTHOR,
54 METADATA_KEY_WRITER,
55 METADATA_KEY_COMPOSER,
56 METADATA_KEY_COMPILATION,
57 METADATA_KEY_DATE,
58 METADATA_KEY_GENRE,
59 METADATA_KEY_ALBUM_ARTIST,
60 METADATA_KEY_ART_URI,
61 METADATA_KEY_ALBUM_ART_URI,
62 METADATA_KEY_DISPLAY_TITLE,
63 METADATA_KEY_DISPLAY_SUBTITLE,
64 METADATA_KEY_DISPLAY_DESCRIPTION,
65 METADATA_KEY_DISPLAY_ICON_URI,
66 METADATA_KEY_MEDIA_ID,
67 METADATA_KEY_MEDIA_URI,
68 })
Insun Kang7c090d52016-02-29 10:51:24 +090069 @Retention(RetentionPolicy.SOURCE)
70 public @interface TextKey {}
71
72 /**
73 * @hide
74 */
Jeff Sharkey5db9a912017-12-08 17:32:32 -070075 @StringDef(prefix = { "METADATA_KEY_" }, value = {
76 METADATA_KEY_DURATION,
77 METADATA_KEY_YEAR,
78 METADATA_KEY_TRACK_NUMBER,
79 METADATA_KEY_NUM_TRACKS,
80 METADATA_KEY_DISC_NUMBER,
81 METADATA_KEY_BT_FOLDER_TYPE,
82 })
Insun Kang7c090d52016-02-29 10:51:24 +090083 @Retention(RetentionPolicy.SOURCE)
84 public @interface LongKey {}
85
86 /**
87 * @hide
88 */
Jeff Sharkey5db9a912017-12-08 17:32:32 -070089 @StringDef(prefix = { "METADATA_KEY_" }, value = {
90 METADATA_KEY_ART,
91 METADATA_KEY_ALBUM_ART,
92 METADATA_KEY_DISPLAY_ICON,
93 })
Insun Kang7c090d52016-02-29 10:51:24 +090094 @Retention(RetentionPolicy.SOURCE)
95 public @interface BitmapKey {}
96
97 /**
98 * @hide
99 */
Jeff Sharkey5db9a912017-12-08 17:32:32 -0700100 @StringDef(prefix = { "METADATA_KEY_" }, value = {
101 METADATA_KEY_USER_RATING,
102 METADATA_KEY_RATING,
103 })
Insun Kang7c090d52016-02-29 10:51:24 +0900104 @Retention(RetentionPolicy.SOURCE)
105 public @interface RatingKey {}
106
107 /**
RoboErik8ae0f342014-02-24 18:02:08 -0800108 * The title of the media.
109 */
110 public static final String METADATA_KEY_TITLE = "android.media.metadata.TITLE";
111
112 /**
113 * The artist of the media.
114 */
115 public static final String METADATA_KEY_ARTIST = "android.media.metadata.ARTIST";
116
117 /**
RoboErikf1372422014-04-23 14:38:17 -0700118 * The duration of the media in ms. A negative duration indicates that the
119 * duration is unknown (or infinite).
RoboErik8ae0f342014-02-24 18:02:08 -0800120 */
121 public static final String METADATA_KEY_DURATION = "android.media.metadata.DURATION";
122
123 /**
124 * The album title for the media.
125 */
126 public static final String METADATA_KEY_ALBUM = "android.media.metadata.ALBUM";
127
128 /**
129 * The author of the media.
130 */
131 public static final String METADATA_KEY_AUTHOR = "android.media.metadata.AUTHOR";
132
133 /**
134 * The writer of the media.
135 */
136 public static final String METADATA_KEY_WRITER = "android.media.metadata.WRITER";
137
138 /**
139 * The composer of the media.
140 */
141 public static final String METADATA_KEY_COMPOSER = "android.media.metadata.COMPOSER";
142
143 /**
RoboErikf1372422014-04-23 14:38:17 -0700144 * The compilation status of the media.
145 */
146 public static final String METADATA_KEY_COMPILATION = "android.media.metadata.COMPILATION";
147
148 /**
RoboErikb214efb2014-07-24 13:20:30 -0700149 * The date the media was created or published. The format is unspecified
150 * but RFC 3339 is recommended.
RoboErik8ae0f342014-02-24 18:02:08 -0800151 */
152 public static final String METADATA_KEY_DATE = "android.media.metadata.DATE";
153
154 /**
RoboErikf1372422014-04-23 14:38:17 -0700155 * The year the media was created or published as a long.
RoboErik8ae0f342014-02-24 18:02:08 -0800156 */
157 public static final String METADATA_KEY_YEAR = "android.media.metadata.YEAR";
158
159 /**
160 * The genre of the media.
161 */
162 public static final String METADATA_KEY_GENRE = "android.media.metadata.GENRE";
163
164 /**
165 * The track number for the media.
166 */
167 public static final String METADATA_KEY_TRACK_NUMBER = "android.media.metadata.TRACK_NUMBER";
168
169 /**
170 * The number of tracks in the media's original source.
171 */
172 public static final String METADATA_KEY_NUM_TRACKS = "android.media.metadata.NUM_TRACKS";
173
174 /**
175 * The disc number for the media's original source.
176 */
177 public static final String METADATA_KEY_DISC_NUMBER = "android.media.metadata.DISC_NUMBER";
178
179 /**
180 * The artist for the album of the media's original source.
181 */
182 public static final String METADATA_KEY_ALBUM_ARTIST = "android.media.metadata.ALBUM_ARTIST";
183
184 /**
185 * The artwork for the media as a {@link Bitmap}.
RoboErika13846d2014-11-06 10:55:06 -0800186 * <p>
187 * The artwork should be relatively small and may be scaled down by the
188 * system if it is too large. For higher resolution artwork
189 * {@link #METADATA_KEY_ART_URI} should be used instead.
RoboErik8ae0f342014-02-24 18:02:08 -0800190 */
191 public static final String METADATA_KEY_ART = "android.media.metadata.ART";
192
193 /**
RoboErik3625bf72014-08-27 16:03:19 -0700194 * The artwork for the media as a Uri formatted String. The artwork can be
195 * loaded using a combination of {@link ContentResolver#openInputStream} and
196 * {@link BitmapFactory#decodeStream}.
RoboErika13846d2014-11-06 10:55:06 -0800197 * <p>
198 * For the best results, Uris should use the content:// style and support
199 * {@link ContentResolver#EXTRA_SIZE} for retrieving scaled artwork through
200 * {@link ContentResolver#openTypedAssetFileDescriptor(Uri, String, Bundle)}.
RoboErik8ae0f342014-02-24 18:02:08 -0800201 */
202 public static final String METADATA_KEY_ART_URI = "android.media.metadata.ART_URI";
203
204 /**
205 * The artwork for the album of the media's original source as a
206 * {@link Bitmap}.
RoboErika13846d2014-11-06 10:55:06 -0800207 * <p>
208 * The artwork should be relatively small and may be scaled down by the
209 * system if it is too large. For higher resolution artwork
210 * {@link #METADATA_KEY_ALBUM_ART_URI} should be used instead.
RoboErik8ae0f342014-02-24 18:02:08 -0800211 */
212 public static final String METADATA_KEY_ALBUM_ART = "android.media.metadata.ALBUM_ART";
213
214 /**
RoboErik3625bf72014-08-27 16:03:19 -0700215 * The artwork for the album of the media's original source as a Uri
216 * formatted String. The artwork can be loaded using a combination of
217 * {@link ContentResolver#openInputStream} and
218 * {@link BitmapFactory#decodeStream}.
RoboErika13846d2014-11-06 10:55:06 -0800219 * <p>
220 * For the best results, Uris should use the content:// style and support
221 * {@link ContentResolver#EXTRA_SIZE} for retrieving scaled artwork through
222 * {@link ContentResolver#openTypedAssetFileDescriptor(Uri, String, Bundle)}.
RoboErik8ae0f342014-02-24 18:02:08 -0800223 */
224 public static final String METADATA_KEY_ALBUM_ART_URI = "android.media.metadata.ALBUM_ART_URI";
225
226 /**
227 * The user's rating for the media.
228 *
229 * @see Rating
230 */
231 public static final String METADATA_KEY_USER_RATING = "android.media.metadata.USER_RATING";
232
233 /**
234 * The overall rating for the media.
235 *
236 * @see Rating
237 */
238 public static final String METADATA_KEY_RATING = "android.media.metadata.RATING";
239
RoboErik75847b92014-07-29 13:10:17 -0700240 /**
241 * A title that is suitable for display to the user. This will generally be
242 * the same as {@link #METADATA_KEY_TITLE} but may differ for some formats.
243 * When displaying media described by this metadata this should be preferred
244 * if present.
245 */
246 public static final String METADATA_KEY_DISPLAY_TITLE = "android.media.metadata.DISPLAY_TITLE";
247
248 /**
249 * A subtitle that is suitable for display to the user. When displaying a
250 * second line for media described by this metadata this should be preferred
251 * to other fields if present.
252 */
Sungsoo Limbb3b4012019-01-23 13:17:53 +0900253 public static final String METADATA_KEY_DISPLAY_SUBTITLE =
254 "android.media.metadata.DISPLAY_SUBTITLE";
RoboErik75847b92014-07-29 13:10:17 -0700255
256 /**
257 * A description that is suitable for display to the user. When displaying
258 * more information for media described by this metadata this should be
259 * preferred to other fields if present.
260 */
Sungsoo Limbb3b4012019-01-23 13:17:53 +0900261 public static final String METADATA_KEY_DISPLAY_DESCRIPTION =
262 "android.media.metadata.DISPLAY_DESCRIPTION";
RoboErik75847b92014-07-29 13:10:17 -0700263
264 /**
265 * An icon or thumbnail that is suitable for display to the user. When
266 * displaying an icon for media described by this metadata this should be
267 * preferred to other fields if present. This must be a {@link Bitmap}.
RoboErika13846d2014-11-06 10:55:06 -0800268 * <p>
269 * The icon should be relatively small and may be scaled down by the system
270 * if it is too large. For higher resolution artwork
271 * {@link #METADATA_KEY_DISPLAY_ICON_URI} should be used instead.
RoboErik75847b92014-07-29 13:10:17 -0700272 */
Sungsoo Limbb3b4012019-01-23 13:17:53 +0900273 public static final String METADATA_KEY_DISPLAY_ICON =
274 "android.media.metadata.DISPLAY_ICON";
RoboErik75847b92014-07-29 13:10:17 -0700275
276 /**
RoboErik3625bf72014-08-27 16:03:19 -0700277 * A Uri formatted String for an icon or thumbnail that is suitable for
278 * display to the user. When displaying more information for media described
279 * by this metadata the display description should be preferred to other
280 * fields when present. The icon can be loaded using a combination of
281 * {@link ContentResolver#openInputStream} and
282 * {@link BitmapFactory#decodeStream}.
RoboErika13846d2014-11-06 10:55:06 -0800283 * <p>
284 * For the best results, Uris should use the content:// style and support
285 * {@link ContentResolver#EXTRA_SIZE} for retrieving scaled artwork through
286 * {@link ContentResolver#openTypedAssetFileDescriptor(Uri, String, Bundle)}.
RoboErik75847b92014-07-29 13:10:17 -0700287 */
Sungsoo Limbb3b4012019-01-23 13:17:53 +0900288 public static final String METADATA_KEY_DISPLAY_ICON_URI =
289 "android.media.metadata.DISPLAY_ICON_URI";
RoboErik75847b92014-07-29 13:10:17 -0700290
RoboErik3625bf72014-08-27 16:03:19 -0700291 /**
292 * A String key for identifying the content. This value is specific to the
293 * service providing the content. If used, this should be a persistent
294 * unique key for the underlying content. It may be used with
295 * {@link MediaController.TransportControls#playFromMediaId(String, Bundle)}
296 * to initiate playback when provided by a {@link MediaBrowser} connected to
297 * the same app.
298 */
299 public static final String METADATA_KEY_MEDIA_ID = "android.media.metadata.MEDIA_ID";
300
Donghyun Cho3cea6d52016-06-14 15:49:12 +0900301 /**
Sungsoo Lim28b1d882016-06-23 17:08:33 +0900302 * A Uri formatted String representing the content. This value is specific to the
303 * service providing the content. It may be used with
304 * {@link MediaController.TransportControls#playFromUri(Uri, Bundle)}
305 * to initiate playback when provided by a {@link MediaBrowser} connected to
306 * the same app.
Sungsoo Lim28b1d882016-06-23 17:08:33 +0900307 */
308 public static final String METADATA_KEY_MEDIA_URI = "android.media.metadata.MEDIA_URI";
309
310 /**
Donghyun Cho3cea6d52016-06-14 15:49:12 +0900311 * The bluetooth folder type of the media specified in the section 6.10.2.2 of the Bluetooth
312 * AVRCP 1.5. It should be one of the following:
313 * <ul>
314 * <li>{@link MediaDescription#BT_FOLDER_TYPE_MIXED}</li>
315 * <li>{@link MediaDescription#BT_FOLDER_TYPE_TITLES}</li>
316 * <li>{@link MediaDescription#BT_FOLDER_TYPE_ALBUMS}</li>
317 * <li>{@link MediaDescription#BT_FOLDER_TYPE_ARTISTS}</li>
318 * <li>{@link MediaDescription#BT_FOLDER_TYPE_GENRES}</li>
319 * <li>{@link MediaDescription#BT_FOLDER_TYPE_PLAYLISTS}</li>
320 * <li>{@link MediaDescription#BT_FOLDER_TYPE_YEARS}</li>
321 * </ul>
322 */
Sungsoo Limbb3b4012019-01-23 13:17:53 +0900323 public static final String METADATA_KEY_BT_FOLDER_TYPE =
324 "android.media.metadata.BT_FOLDER_TYPE";
Donghyun Cho3cea6d52016-06-14 15:49:12 +0900325
Insun Kang7c090d52016-02-29 10:51:24 +0900326 private static final @TextKey String[] PREFERRED_DESCRIPTION_ORDER = {
RoboErik75847b92014-07-29 13:10:17 -0700327 METADATA_KEY_TITLE,
RoboErik75847b92014-07-29 13:10:17 -0700328 METADATA_KEY_ARTIST,
RoboErik67098d02014-08-06 17:48:46 -0700329 METADATA_KEY_ALBUM,
RoboErik75847b92014-07-29 13:10:17 -0700330 METADATA_KEY_ALBUM_ARTIST,
331 METADATA_KEY_WRITER,
332 METADATA_KEY_AUTHOR,
333 METADATA_KEY_COMPOSER
334 };
335
Insun Kang7c090d52016-02-29 10:51:24 +0900336 private static final @BitmapKey String[] PREFERRED_BITMAP_ORDER = {
RoboErik75847b92014-07-29 13:10:17 -0700337 METADATA_KEY_DISPLAY_ICON,
338 METADATA_KEY_ART,
339 METADATA_KEY_ALBUM_ART
340 };
341
Insun Kang7c090d52016-02-29 10:51:24 +0900342 private static final @TextKey String[] PREFERRED_URI_ORDER = {
RoboErik75847b92014-07-29 13:10:17 -0700343 METADATA_KEY_DISPLAY_ICON_URI,
344 METADATA_KEY_ART_URI,
345 METADATA_KEY_ALBUM_ART_URI
346 };
347
RoboErik8ae0f342014-02-24 18:02:08 -0800348 private static final int METADATA_TYPE_INVALID = -1;
349 private static final int METADATA_TYPE_LONG = 0;
RoboErik75847b92014-07-29 13:10:17 -0700350 private static final int METADATA_TYPE_TEXT = 1;
RoboErik8ae0f342014-02-24 18:02:08 -0800351 private static final int METADATA_TYPE_BITMAP = 2;
352 private static final int METADATA_TYPE_RATING = 3;
353 private static final ArrayMap<String, Integer> METADATA_KEYS_TYPE;
354
355 static {
356 METADATA_KEYS_TYPE = new ArrayMap<String, Integer>();
RoboErik75847b92014-07-29 13:10:17 -0700357 METADATA_KEYS_TYPE.put(METADATA_KEY_TITLE, METADATA_TYPE_TEXT);
358 METADATA_KEYS_TYPE.put(METADATA_KEY_ARTIST, METADATA_TYPE_TEXT);
RoboErik8ae0f342014-02-24 18:02:08 -0800359 METADATA_KEYS_TYPE.put(METADATA_KEY_DURATION, METADATA_TYPE_LONG);
RoboErik75847b92014-07-29 13:10:17 -0700360 METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM, METADATA_TYPE_TEXT);
361 METADATA_KEYS_TYPE.put(METADATA_KEY_AUTHOR, METADATA_TYPE_TEXT);
362 METADATA_KEYS_TYPE.put(METADATA_KEY_WRITER, METADATA_TYPE_TEXT);
363 METADATA_KEYS_TYPE.put(METADATA_KEY_COMPOSER, METADATA_TYPE_TEXT);
364 METADATA_KEYS_TYPE.put(METADATA_KEY_COMPILATION, METADATA_TYPE_TEXT);
365 METADATA_KEYS_TYPE.put(METADATA_KEY_DATE, METADATA_TYPE_TEXT);
RoboErikf1372422014-04-23 14:38:17 -0700366 METADATA_KEYS_TYPE.put(METADATA_KEY_YEAR, METADATA_TYPE_LONG);
RoboErik75847b92014-07-29 13:10:17 -0700367 METADATA_KEYS_TYPE.put(METADATA_KEY_GENRE, METADATA_TYPE_TEXT);
RoboErik8ae0f342014-02-24 18:02:08 -0800368 METADATA_KEYS_TYPE.put(METADATA_KEY_TRACK_NUMBER, METADATA_TYPE_LONG);
369 METADATA_KEYS_TYPE.put(METADATA_KEY_NUM_TRACKS, METADATA_TYPE_LONG);
370 METADATA_KEYS_TYPE.put(METADATA_KEY_DISC_NUMBER, METADATA_TYPE_LONG);
RoboErik75847b92014-07-29 13:10:17 -0700371 METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM_ARTIST, METADATA_TYPE_TEXT);
RoboErik8ae0f342014-02-24 18:02:08 -0800372 METADATA_KEYS_TYPE.put(METADATA_KEY_ART, METADATA_TYPE_BITMAP);
RoboErik217e8a22014-08-07 16:53:06 -0700373 METADATA_KEYS_TYPE.put(METADATA_KEY_ART_URI, METADATA_TYPE_TEXT);
RoboErik8ae0f342014-02-24 18:02:08 -0800374 METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM_ART, METADATA_TYPE_BITMAP);
RoboErik217e8a22014-08-07 16:53:06 -0700375 METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM_ART_URI, METADATA_TYPE_TEXT);
RoboErik8ae0f342014-02-24 18:02:08 -0800376 METADATA_KEYS_TYPE.put(METADATA_KEY_USER_RATING, METADATA_TYPE_RATING);
377 METADATA_KEYS_TYPE.put(METADATA_KEY_RATING, METADATA_TYPE_RATING);
RoboErik75847b92014-07-29 13:10:17 -0700378 METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_TITLE, METADATA_TYPE_TEXT);
379 METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_SUBTITLE, METADATA_TYPE_TEXT);
380 METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_DESCRIPTION, METADATA_TYPE_TEXT);
381 METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_ICON, METADATA_TYPE_BITMAP);
RoboErik217e8a22014-08-07 16:53:06 -0700382 METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_ICON_URI, METADATA_TYPE_TEXT);
Donghyun Cho3cea6d52016-06-14 15:49:12 +0900383 METADATA_KEYS_TYPE.put(METADATA_KEY_BT_FOLDER_TYPE, METADATA_TYPE_LONG);
Sungsoo Lim28b1d882016-06-23 17:08:33 +0900384 METADATA_KEYS_TYPE.put(METADATA_KEY_MEDIA_ID, METADATA_TYPE_TEXT);
385 METADATA_KEYS_TYPE.put(METADATA_KEY_MEDIA_URI, METADATA_TYPE_TEXT);
RoboErik8ae0f342014-02-24 18:02:08 -0800386 }
RoboErikf1372422014-04-23 14:38:17 -0700387
388 private static final SparseArray<String> EDITOR_KEY_MAPPING;
389
390 static {
391 EDITOR_KEY_MAPPING = new SparseArray<String>();
392 EDITOR_KEY_MAPPING.put(MediaMetadataEditor.BITMAP_KEY_ARTWORK, METADATA_KEY_ART);
393 EDITOR_KEY_MAPPING.put(MediaMetadataEditor.RATING_KEY_BY_OTHERS, METADATA_KEY_RATING);
394 EDITOR_KEY_MAPPING.put(MediaMetadataEditor.RATING_KEY_BY_USER, METADATA_KEY_USER_RATING);
395 EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_ALBUM, METADATA_KEY_ALBUM);
396 EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST,
397 METADATA_KEY_ALBUM_ARTIST);
398 EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_ARTIST, METADATA_KEY_ARTIST);
399 EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_AUTHOR, METADATA_KEY_AUTHOR);
400 EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER,
401 METADATA_KEY_TRACK_NUMBER);
402 EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_COMPOSER, METADATA_KEY_COMPOSER);
403 EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_COMPILATION,
404 METADATA_KEY_COMPILATION);
405 EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_DATE, METADATA_KEY_DATE);
406 EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_DISC_NUMBER,
407 METADATA_KEY_DISC_NUMBER);
408 EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_DURATION, METADATA_KEY_DURATION);
409 EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_GENRE, METADATA_KEY_GENRE);
410 EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS,
411 METADATA_KEY_NUM_TRACKS);
412 EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_TITLE, METADATA_KEY_TITLE);
413 EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_WRITER, METADATA_KEY_WRITER);
414 EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_YEAR, METADATA_KEY_YEAR);
415 }
416
RoboErik8ae0f342014-02-24 18:02:08 -0800417 private final Bundle mBundle;
RoboErik3625bf72014-08-27 16:03:19 -0700418 private MediaDescription mDescription;
RoboErik8ae0f342014-02-24 18:02:08 -0800419
420 private MediaMetadata(Bundle bundle) {
421 mBundle = new Bundle(bundle);
422 }
423
424 private MediaMetadata(Parcel in) {
Hyundo Moon3e8c1c92019-01-11 16:40:52 +0900425 mBundle = in.readBundle();
RoboErik8ae0f342014-02-24 18:02:08 -0800426 }
427
428 /**
RoboErikf1372422014-04-23 14:38:17 -0700429 * Returns true if the given key is contained in the metadata
430 *
431 * @param key a String key
432 * @return true if the key exists in this metadata, false otherwise
433 */
434 public boolean containsKey(String key) {
435 return mBundle.containsKey(key);
436 }
437
438 /**
RoboErik8ae0f342014-02-24 18:02:08 -0800439 * Returns the value associated with the given key, or null if no mapping of
440 * the desired type exists for the given key or a null value is explicitly
441 * associated with the key.
442 *
443 * @param key The key the value is stored under
RoboErik75847b92014-07-29 13:10:17 -0700444 * @return a CharSequence value, or null
445 */
Insun Kang7c090d52016-02-29 10:51:24 +0900446 public CharSequence getText(@TextKey String key) {
RoboErik75847b92014-07-29 13:10:17 -0700447 return mBundle.getCharSequence(key);
448 }
449
450 /**
451 * Returns the text value associated with the given key as a String, or null
452 * if no mapping of the desired type exists for the given key or a null
453 * value is explicitly associated with the key. This is equivalent to
454 * calling {@link #getText getText().toString()} if the value is not null.
455 *
456 * @param key The key the value is stored under
RoboErik8ae0f342014-02-24 18:02:08 -0800457 * @return a String value, or null
458 */
Insun Kang7c090d52016-02-29 10:51:24 +0900459 public String getString(@TextKey String key) {
RoboErik75847b92014-07-29 13:10:17 -0700460 CharSequence text = getText(key);
461 if (text != null) {
462 return text.toString();
463 }
464 return null;
RoboErik8ae0f342014-02-24 18:02:08 -0800465 }
466
467 /**
468 * Returns the value associated with the given key, or 0L if no long exists
469 * for the given key.
470 *
471 * @param key The key the value is stored under
472 * @return a long value
473 */
Insun Kang7c090d52016-02-29 10:51:24 +0900474 public long getLong(@LongKey String key) {
RoboErikf1372422014-04-23 14:38:17 -0700475 return mBundle.getLong(key, 0);
RoboErik8ae0f342014-02-24 18:02:08 -0800476 }
477
478 /**
RoboErik75847b92014-07-29 13:10:17 -0700479 * Returns a {@link Rating} for the given key or null if no rating exists
480 * for the given key.
RoboErik8ae0f342014-02-24 18:02:08 -0800481 *
482 * @param key The key the value is stored under
483 * @return A {@link Rating} or null
484 */
Insun Kang7c090d52016-02-29 10:51:24 +0900485 public Rating getRating(@RatingKey String key) {
RoboErik8ae0f342014-02-24 18:02:08 -0800486 Rating rating = null;
487 try {
488 rating = mBundle.getParcelable(key);
489 } catch (Exception e) {
490 // ignore, value was not a bitmap
Jeff Brownbf58d9b2014-06-23 16:13:53 -0700491 Log.w(TAG, "Failed to retrieve a key as Rating.", e);
RoboErik8ae0f342014-02-24 18:02:08 -0800492 }
493 return rating;
494 }
495
496 /**
RoboErik75847b92014-07-29 13:10:17 -0700497 * Returns a {@link Bitmap} for the given key or null if no bitmap exists
498 * for the given key.
RoboErik8ae0f342014-02-24 18:02:08 -0800499 *
500 * @param key The key the value is stored under
501 * @return A {@link Bitmap} or null
502 */
Insun Kang7c090d52016-02-29 10:51:24 +0900503 public Bitmap getBitmap(@BitmapKey String key) {
RoboErik8ae0f342014-02-24 18:02:08 -0800504 Bitmap bmp = null;
505 try {
506 bmp = mBundle.getParcelable(key);
507 } catch (Exception e) {
508 // ignore, value was not a bitmap
Jeff Brownbf58d9b2014-06-23 16:13:53 -0700509 Log.w(TAG, "Failed to retrieve a key as Bitmap.", e);
RoboErik8ae0f342014-02-24 18:02:08 -0800510 }
511 return bmp;
512 }
513
514 @Override
515 public int describeContents() {
516 return 0;
517 }
518
519 @Override
520 public void writeToParcel(Parcel dest, int flags) {
521 dest.writeBundle(mBundle);
522 }
523
RoboErikf1372422014-04-23 14:38:17 -0700524 /**
RoboErik75847b92014-07-29 13:10:17 -0700525 * Returns the number of fields in this metadata.
RoboErik66dea732014-05-01 16:03:59 -0700526 *
527 * @return The number of fields in the metadata.
528 */
529 public int size() {
530 return mBundle.size();
531 }
532
533 /**
RoboErik79fa4632014-05-27 16:49:09 -0700534 * Returns a Set containing the Strings used as keys in this metadata.
535 *
536 * @return a Set of String keys
537 */
538 public Set<String> keySet() {
539 return mBundle.keySet();
540 }
541
542 /**
RoboErik75847b92014-07-29 13:10:17 -0700543 * Returns a simple description of this metadata for display purposes.
544 *
545 * @return A simple description of this metadata.
RoboErik75847b92014-07-29 13:10:17 -0700546 */
RoboErik3625bf72014-08-27 16:03:19 -0700547 public @NonNull MediaDescription getDescription() {
RoboErik75847b92014-07-29 13:10:17 -0700548 if (mDescription != null) {
549 return mDescription;
550 }
551
RoboErik3625bf72014-08-27 16:03:19 -0700552 String mediaId = getString(METADATA_KEY_MEDIA_ID);
553
RoboErik75847b92014-07-29 13:10:17 -0700554 CharSequence[] text = new CharSequence[3];
555 Bitmap icon = null;
556 Uri iconUri = null;
557
558 // First handle the case where display data is set already
559 CharSequence displayText = getText(METADATA_KEY_DISPLAY_TITLE);
560 if (!TextUtils.isEmpty(displayText)) {
561 // If they have a display title use only display data, otherwise use
562 // our best bets
563 text[0] = displayText;
564 text[1] = getText(METADATA_KEY_DISPLAY_SUBTITLE);
565 text[2] = getText(METADATA_KEY_DISPLAY_DESCRIPTION);
566 } else {
567 // Use whatever fields we can
568 int textIndex = 0;
569 int keyIndex = 0;
570 while (textIndex < text.length && keyIndex < PREFERRED_DESCRIPTION_ORDER.length) {
571 CharSequence next = getText(PREFERRED_DESCRIPTION_ORDER[keyIndex++]);
572 if (!TextUtils.isEmpty(next)) {
573 // Fill in the next empty bit of text
574 text[textIndex++] = next;
575 }
576 }
577 }
578
579 // Get the best art bitmap we can find
580 for (int i = 0; i < PREFERRED_BITMAP_ORDER.length; i++) {
581 Bitmap next = getBitmap(PREFERRED_BITMAP_ORDER[i]);
582 if (next != null) {
583 icon = next;
584 break;
585 }
586 }
587
588 // Get the best Uri we can find
589 for (int i = 0; i < PREFERRED_URI_ORDER.length; i++) {
590 String next = getString(PREFERRED_URI_ORDER[i]);
591 if (!TextUtils.isEmpty(next)) {
592 iconUri = Uri.parse(next);
593 break;
594 }
595 }
596
Sungsoo Lim28b1d882016-06-23 17:08:33 +0900597 Uri mediaUri = null;
598 String mediaUriStr = getString(METADATA_KEY_MEDIA_URI);
599 if (!TextUtils.isEmpty(mediaUriStr)) {
600 mediaUri = Uri.parse(mediaUriStr);
601 }
602
RoboErik3625bf72014-08-27 16:03:19 -0700603 MediaDescription.Builder bob = new MediaDescription.Builder();
604 bob.setMediaId(mediaId);
605 bob.setTitle(text[0]);
606 bob.setSubtitle(text[1]);
607 bob.setDescription(text[2]);
608 bob.setIconBitmap(icon);
609 bob.setIconUri(iconUri);
Sungsoo Lim28b1d882016-06-23 17:08:33 +0900610 bob.setMediaUri(mediaUri);
Donghyun Cho3cea6d52016-06-14 15:49:12 +0900611 if (mBundle.containsKey(METADATA_KEY_BT_FOLDER_TYPE)) {
612 Bundle bundle = new Bundle();
613 bundle.putLong(MediaDescription.EXTRA_BT_FOLDER_TYPE,
614 getLong(METADATA_KEY_BT_FOLDER_TYPE));
615 bob.setExtras(bundle);
616 }
RoboErik3625bf72014-08-27 16:03:19 -0700617 mDescription = bob.build();
618
RoboErik75847b92014-07-29 13:10:17 -0700619 return mDescription;
620 }
621
622 /**
RoboErikf1372422014-04-23 14:38:17 -0700623 * Helper for getting the String key used by {@link MediaMetadata} from the
624 * integer key that {@link MediaMetadataEditor} uses.
625 *
626 * @param editorKey The key used by the editor
627 * @return The key used by this class or null if no mapping exists
628 * @hide
629 */
Mathew Inwood31a792a2018-08-17 08:54:26 +0100630 @UnsupportedAppUsage
RoboErikf1372422014-04-23 14:38:17 -0700631 public static String getKeyFromMetadataEditorKey(int editorKey) {
632 return EDITOR_KEY_MAPPING.get(editorKey, null);
633 }
634
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -0700635 public static final @android.annotation.NonNull Parcelable.Creator<MediaMetadata> CREATOR =
Jeff Brownbf58d9b2014-06-23 16:13:53 -0700636 new Parcelable.Creator<MediaMetadata>() {
RoboErik8ae0f342014-02-24 18:02:08 -0800637 @Override
638 public MediaMetadata createFromParcel(Parcel in) {
639 return new MediaMetadata(in);
640 }
641
642 @Override
643 public MediaMetadata[] newArray(int size) {
644 return new MediaMetadata[size];
645 }
646 };
647
648 /**
Ajay Panicker6e1d2302017-11-09 10:16:35 -0800649 * Compares the contents of this object to another MediaMetadata object. It
650 * does not compare Bitmaps and Ratings as the media player can choose to
651 * forgo these fields depending on how you retrieve the MediaMetadata.
652 *
653 * @param o The Metadata object to compare this object against
654 * @return Whether or not the two objects have matching fields (excluding
655 * Bitmaps and Ratings)
656 */
657 @Override
658 public boolean equals(Object o) {
659 if (o == this) {
660 return true;
661 }
662
663 if (!(o instanceof MediaMetadata)) {
664 return false;
665 }
666
667 final MediaMetadata m = (MediaMetadata) o;
668
669 for (int i = 0; i < METADATA_KEYS_TYPE.size(); i++) {
670 String key = METADATA_KEYS_TYPE.keyAt(i);
671 switch (METADATA_KEYS_TYPE.valueAt(i)) {
672 case METADATA_TYPE_TEXT:
673 if (!Objects.equals(getString(key), m.getString(key))) {
674 return false;
675 }
676 break;
677 case METADATA_TYPE_LONG:
678 if (getLong(key) != m.getLong(key)) {
679 return false;
680 }
681 break;
682 default:
683 // Ignore ratings and bitmaps when comparing
684 break;
685 }
686 }
687
688 return true;
689 }
690
691 @Override
692 public int hashCode() {
693 int hashCode = 17;
694
695 for (int i = 0; i < METADATA_KEYS_TYPE.size(); i++) {
696 String key = METADATA_KEYS_TYPE.keyAt(i);
697 switch (METADATA_KEYS_TYPE.valueAt(i)) {
698 case METADATA_TYPE_TEXT:
699 hashCode = 31 * hashCode + Objects.hash(getString(key));
700 break;
701 case METADATA_TYPE_LONG:
702 hashCode = 31 * hashCode + Long.hashCode(getLong(key));
703 break;
704 default:
705 // Ignore ratings and bitmaps when comparing
706 break;
707 }
708 }
709
710 return hashCode;
711 }
712
713 /**
RoboErik8ae0f342014-02-24 18:02:08 -0800714 * Use to build MediaMetadata objects. The system defined metadata keys must
715 * use the appropriate data type.
716 */
717 public static final class Builder {
718 private final Bundle mBundle;
719
720 /**
721 * Create an empty Builder. Any field that should be included in the
722 * {@link MediaMetadata} must be added.
723 */
724 public Builder() {
725 mBundle = new Bundle();
726 }
727
728 /**
729 * Create a Builder using a {@link MediaMetadata} instance to set the
730 * initial values. All fields in the source metadata will be included in
731 * the new metadata. Fields can be overwritten by adding the same key.
732 *
733 * @param source
734 */
735 public Builder(MediaMetadata source) {
736 mBundle = new Bundle(source.mBundle);
737 }
738
739 /**
RoboErikb9c87fb2014-11-19 12:14:55 -0800740 * Create a Builder using a {@link MediaMetadata} instance to set
741 * initial values, but replace bitmaps with a scaled down copy if they
742 * are larger than maxBitmapSize.
743 *
744 * @param source The original metadata to copy.
745 * @param maxBitmapSize The maximum height/width for bitmaps contained
746 * in the metadata.
747 * @hide
748 */
749 public Builder(MediaMetadata source, int maxBitmapSize) {
750 this(source);
751 for (String key : mBundle.keySet()) {
752 Object value = mBundle.get(key);
753 if (value != null && value instanceof Bitmap) {
754 Bitmap bmp = (Bitmap) value;
755 if (bmp.getHeight() > maxBitmapSize || bmp.getWidth() > maxBitmapSize) {
756 putBitmap(key, scaleBitmap(bmp, maxBitmapSize));
757 }
758 }
759 }
760 }
761
762 /**
RoboErik75847b92014-07-29 13:10:17 -0700763 * Put a CharSequence value into the metadata. Custom keys may be used,
764 * but if the METADATA_KEYs defined in this class are used they may only
765 * be one of the following:
766 * <ul>
767 * <li>{@link #METADATA_KEY_TITLE}</li>
768 * <li>{@link #METADATA_KEY_ARTIST}</li>
769 * <li>{@link #METADATA_KEY_ALBUM}</li>
770 * <li>{@link #METADATA_KEY_AUTHOR}</li>
771 * <li>{@link #METADATA_KEY_WRITER}</li>
772 * <li>{@link #METADATA_KEY_COMPOSER}</li>
773 * <li>{@link #METADATA_KEY_DATE}</li>
774 * <li>{@link #METADATA_KEY_GENRE}</li>
775 * <li>{@link #METADATA_KEY_ALBUM_ARTIST}</li>
776 * <li>{@link #METADATA_KEY_ART_URI}</li>
777 * <li>{@link #METADATA_KEY_ALBUM_ART_URI}</li>
778 * <li>{@link #METADATA_KEY_DISPLAY_TITLE}</li>
779 * <li>{@link #METADATA_KEY_DISPLAY_SUBTITLE}</li>
780 * <li>{@link #METADATA_KEY_DISPLAY_DESCRIPTION}</li>
781 * <li>{@link #METADATA_KEY_DISPLAY_ICON_URI}</li>
782 * </ul>
783 *
784 * @param key The key for referencing this value
785 * @param value The CharSequence value to store
786 * @return The Builder to allow chaining
787 */
Insun Kang7c090d52016-02-29 10:51:24 +0900788 public Builder putText(@TextKey String key, CharSequence value) {
RoboErik75847b92014-07-29 13:10:17 -0700789 if (METADATA_KEYS_TYPE.containsKey(key)) {
790 if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_TEXT) {
791 throw new IllegalArgumentException("The " + key
792 + " key cannot be used to put a CharSequence");
793 }
794 }
795 mBundle.putCharSequence(key, value);
796 return this;
797 }
798
799 /**
RoboErik8ae0f342014-02-24 18:02:08 -0800800 * Put a String value into the metadata. Custom keys may be used, but if
801 * the METADATA_KEYs defined in this class are used they may only be one
802 * of the following:
803 * <ul>
804 * <li>{@link #METADATA_KEY_TITLE}</li>
805 * <li>{@link #METADATA_KEY_ARTIST}</li>
806 * <li>{@link #METADATA_KEY_ALBUM}</li>
807 * <li>{@link #METADATA_KEY_AUTHOR}</li>
808 * <li>{@link #METADATA_KEY_WRITER}</li>
809 * <li>{@link #METADATA_KEY_COMPOSER}</li>
810 * <li>{@link #METADATA_KEY_DATE}</li>
RoboErik8ae0f342014-02-24 18:02:08 -0800811 * <li>{@link #METADATA_KEY_GENRE}</li>
RoboErikf1372422014-04-23 14:38:17 -0700812 * <li>{@link #METADATA_KEY_ALBUM_ARTIST}</li>
813 * <li>{@link #METADATA_KEY_ART_URI}</li>
RoboErik8ae0f342014-02-24 18:02:08 -0800814 * <li>{@link #METADATA_KEY_ALBUM_ART_URI}</li>
RoboErik75847b92014-07-29 13:10:17 -0700815 * <li>{@link #METADATA_KEY_DISPLAY_TITLE}</li>
816 * <li>{@link #METADATA_KEY_DISPLAY_SUBTITLE}</li>
817 * <li>{@link #METADATA_KEY_DISPLAY_DESCRIPTION}</li>
818 * <li>{@link #METADATA_KEY_DISPLAY_ICON_URI}</li>
RoboErik8ae0f342014-02-24 18:02:08 -0800819 * </ul>
RoboErika13846d2014-11-06 10:55:06 -0800820 * <p>
821 * Uris for artwork should use the content:// style and support
822 * {@link ContentResolver#EXTRA_SIZE} for retrieving scaled artwork
823 * through {@link ContentResolver#openTypedAssetFileDescriptor(Uri,
824 * String, Bundle)}.
RoboErik8ae0f342014-02-24 18:02:08 -0800825 *
826 * @param key The key for referencing this value
827 * @param value The String value to store
828 * @return The Builder to allow chaining
829 */
Insun Kang7c090d52016-02-29 10:51:24 +0900830 public Builder putString(@TextKey String key, String value) {
RoboErik8ae0f342014-02-24 18:02:08 -0800831 if (METADATA_KEYS_TYPE.containsKey(key)) {
RoboErik75847b92014-07-29 13:10:17 -0700832 if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_TEXT) {
RoboErik8ae0f342014-02-24 18:02:08 -0800833 throw new IllegalArgumentException("The " + key
834 + " key cannot be used to put a String");
835 }
836 }
RoboErik75847b92014-07-29 13:10:17 -0700837 mBundle.putCharSequence(key, value);
RoboErik8ae0f342014-02-24 18:02:08 -0800838 return this;
839 }
840
841 /**
842 * Put a long value into the metadata. Custom keys may be used, but if
843 * the METADATA_KEYs defined in this class are used they may only be one
844 * of the following:
845 * <ul>
846 * <li>{@link #METADATA_KEY_DURATION}</li>
847 * <li>{@link #METADATA_KEY_TRACK_NUMBER}</li>
848 * <li>{@link #METADATA_KEY_NUM_TRACKS}</li>
849 * <li>{@link #METADATA_KEY_DISC_NUMBER}</li>
RoboErikf1372422014-04-23 14:38:17 -0700850 * <li>{@link #METADATA_KEY_YEAR}</li>
RoboErik8ae0f342014-02-24 18:02:08 -0800851 * </ul>
852 *
853 * @param key The key for referencing this value
RoboErik75847b92014-07-29 13:10:17 -0700854 * @param value The long value to store
RoboErik8ae0f342014-02-24 18:02:08 -0800855 * @return The Builder to allow chaining
856 */
Insun Kang7c090d52016-02-29 10:51:24 +0900857 public Builder putLong(@LongKey String key, long value) {
RoboErik8ae0f342014-02-24 18:02:08 -0800858 if (METADATA_KEYS_TYPE.containsKey(key)) {
859 if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_LONG) {
860 throw new IllegalArgumentException("The " + key
861 + " key cannot be used to put a long");
862 }
863 }
864 mBundle.putLong(key, value);
865 return this;
866 }
867
868 /**
869 * Put a {@link Rating} into the metadata. Custom keys may be used, but
870 * if the METADATA_KEYs defined in this class are used they may only be
871 * one of the following:
872 * <ul>
873 * <li>{@link #METADATA_KEY_RATING}</li>
874 * <li>{@link #METADATA_KEY_USER_RATING}</li>
875 * </ul>
876 *
877 * @param key The key for referencing this value
RoboErik75847b92014-07-29 13:10:17 -0700878 * @param value The Rating value to store
RoboErik8ae0f342014-02-24 18:02:08 -0800879 * @return The Builder to allow chaining
880 */
Insun Kang7c090d52016-02-29 10:51:24 +0900881 public Builder putRating(@RatingKey String key, Rating value) {
RoboErik8ae0f342014-02-24 18:02:08 -0800882 if (METADATA_KEYS_TYPE.containsKey(key)) {
883 if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_RATING) {
884 throw new IllegalArgumentException("The " + key
885 + " key cannot be used to put a Rating");
886 }
887 }
888 mBundle.putParcelable(key, value);
889 return this;
890 }
891
892 /**
893 * Put a {@link Bitmap} into the metadata. Custom keys may be used, but
894 * if the METADATA_KEYs defined in this class are used they may only be
895 * one of the following:
896 * <ul>
897 * <li>{@link #METADATA_KEY_ART}</li>
898 * <li>{@link #METADATA_KEY_ALBUM_ART}</li>
RoboErik75847b92014-07-29 13:10:17 -0700899 * <li>{@link #METADATA_KEY_DISPLAY_ICON}</li>
RoboErik8ae0f342014-02-24 18:02:08 -0800900 * </ul>
RoboErikb9c87fb2014-11-19 12:14:55 -0800901 * <p>
Jaewan Kim762194c2016-06-27 16:25:07 +0900902 * Large bitmaps may be scaled down by the system when
903 * {@link android.media.session.MediaSession#setMetadata} is called.
904 * To pass full resolution images {@link Uri Uris} should be used with
RoboErikb9c87fb2014-11-19 12:14:55 -0800905 * {@link #putString}.
RoboErik8ae0f342014-02-24 18:02:08 -0800906 *
907 * @param key The key for referencing this value
908 * @param value The Bitmap to store
909 * @return The Builder to allow chaining
910 */
Insun Kang7c090d52016-02-29 10:51:24 +0900911 public Builder putBitmap(@BitmapKey String key, Bitmap value) {
RoboErik8ae0f342014-02-24 18:02:08 -0800912 if (METADATA_KEYS_TYPE.containsKey(key)) {
913 if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_BITMAP) {
914 throw new IllegalArgumentException("The " + key
915 + " key cannot be used to put a Bitmap");
916 }
917 }
918 mBundle.putParcelable(key, value);
919 return this;
920 }
921
922 /**
923 * Creates a {@link MediaMetadata} instance with the specified fields.
924 *
925 * @return The new MediaMetadata instance
926 */
927 public MediaMetadata build() {
928 return new MediaMetadata(mBundle);
929 }
RoboErikb9c87fb2014-11-19 12:14:55 -0800930
931 private Bitmap scaleBitmap(Bitmap bmp, int maxSize) {
932 float maxSizeF = maxSize;
933 float widthScale = maxSizeF / bmp.getWidth();
934 float heightScale = maxSizeF / bmp.getHeight();
935 float scale = Math.min(widthScale, heightScale);
936 int height = (int) (bmp.getHeight() * scale);
937 int width = (int) (bmp.getWidth() * scale);
938 return Bitmap.createScaledBitmap(bmp, width, height, true);
939 }
RoboErik8ae0f342014-02-24 18:02:08 -0800940 }
RoboErik8ae0f342014-02-24 18:02:08 -0800941}