در حین پخش
فرادادههای رسانه را میتوان در حین پخش به روشهای مختلفی بازیابی کرد. سادهترین راه، گوش دادن به رویداد Player.Listener#onMediaMetadataChanged ؛ این رویداد یک شیء MediaMetadata برای استفاده فراهم میکند که دارای فیلدهایی مانند title و albumArtist است. به عنوان یک روش جایگزین، فراخوانی Player#getMediaMetadata همان شیء را برمیگرداند.
کاتلین
override fun onMediaMetadataChanged(mediaMetadata: MediaMetadata) { mediaMetadata.title?.let(::handleTitle) }
جاوا
@Override public void onMediaMetadataChanged(MediaMetadata mediaMetadata) { if (mediaMetadata.title != null) { handleTitle(mediaMetadata.title); } }
اگر برنامه شما نیاز به دسترسی به اشیاء خاص Metadata.Entry دارد، باید به Player.Listener#onMetadata (برای متادیتای پویا که هنگام پخش ارائه میشود) گوش دهد. از طرف دیگر، اگر نیاز به بررسی متادیتای استاتیک باشد، میتوان از طریق TrackSelections#getFormat به آن دسترسی پیدا کرد. Player#getMediaMetadata از هر دوی این منابع پر میشود.
بدون پخش
اگر نیازی به پخش نباشد، استفاده از MetadataRetriever برای استخراج فراداده کارآمدتر است زیرا از ایجاد و آمادهسازی پخشکننده جلوگیری میکند.
کاتلین
suspend fun retrieveMetadata(context: Context, mediaItem: MediaItem) { try { // 1. Build the retriever. // `MetadataRetriever` implements `AutoCloseable`, so wrap it in // a Kotlin `.use` block, which calls `close()` automatically. MetadataRetriever.Builder(context, mediaItem).build().use { retriever -> // 2. Retrieve metadata asynchronously. val trackGroups = retriever.retrieveTrackGroups().await() val timeline = retriever.retrieveTimeline().await() val durationUs = retriever.retrieveDurationUs().await() handleMetadata(trackGroups, timeline, durationUs) } } catch (e: Exception) { handleFailure(e) } }
جاوا
public void retrieveMetadata(Context context, MediaItem mediaItem) { // 1. Build the retriever. // `MetadataRetriever` implements `AutoCloseable`, so use try-with-resources // so that the resources are automatically released. try (MetadataRetriever retriever = new MetadataRetriever.Builder(context, mediaItem).build()) { // 2. Retrieve metadata asynchronously. ListenableFuture<TrackGroupArray> trackGroupsFuture = retriever.retrieveTrackGroups(); ListenableFuture<Timeline> timelineFuture = retriever.retrieveTimeline(); ListenableFuture<Long> durationUsFuture = retriever.retrieveDurationUs(); ListenableFuture<List<Object>> allFutures = Futures.allAsList(trackGroupsFuture, timelineFuture, durationUsFuture); Futures.addCallback( allFutures, new FutureCallback<List<Object>>() { @Override public void onSuccess(List<Object> result) { handleMetadata( Futures.getUnchecked(trackGroupsFuture), Futures.getUnchecked(timelineFuture), Futures.getUnchecked(durationUsFuture)); } @Override public void onFailure(Throwable t) { handleFailure(t); } }, directExecutor()); } }
عکسهای متحرک
همچنین میتوان فرادادههای عکس متحرک، از جمله فاصلهها و طول بخشهای تصویر و ویدیوی فایل را استخراج کرد.
برای عکسهای متحرک، TrackGroupArray که با MetadataRetriever به دست میآید، شامل یک TrackGroup با یک Format واحد است که ورودی فراداده MotionPhotoMetadata را در بر میگیرد.
کاتلین
0.until(trackGroups.length) .asSequence() .mapNotNull { trackGroups[it].getFormat(0).metadata } .filter { metadata -> metadata.length() == 1 } .map { metadata -> metadata[0] } .filterIsInstance<MotionPhotoMetadata>() .forEach(::handleMotionPhotoMetadata)
جاوا
for (int i = 0; i < trackGroups.length; i++) { TrackGroup trackGroup = trackGroups.get(i); Metadata metadata = trackGroup.getFormat(0).metadata; if (metadata != null && metadata.length() == 1) { Metadata.Entry metadataEntry = metadata.get(0); if (metadataEntry instanceof MotionPhotoMetadata) { MotionPhotoMetadata motionPhotoMetadata = (MotionPhotoMetadata) metadataEntry; handleMotionPhotoMetadata(motionPhotoMetadata); } } }