Android(安卓)视频缩略图之MediaMetadataRetriever
16lz
2022-01-23
参考: http://www.ophonesdn.com/forum/thread-2973-1-1.html
http://topic.csdn.net/u/20100315/10/2726b427-ca14-4e06-bd44-a6a351f8c52a.html
http://www.pin5i.com/showtopic-android-generate-thumbnails-for-multimedia-files.html
1、
2.2之后 获得缩略图就简单了 因为用了ThumbnailUtils类,可以
Bitmap b = ThumbnailUtils.createVideoThumbnail(path,Video.Thumbnails.MICRO_KIND);ImageView iv = new ImageView(this);
参见: http://lipeng88213.iteye.com/blog/835183
2、
但是2.2之前呢 这个问题就比较郁闷了 查了查资料
其实 我们可以用MediaMetadataRetriever这个类
但是 里面有个问题
1.0之后 这个类被隐藏了 貌似2.3之后这个类又出现了吧
隐藏了。。。。那怎么办呢?别慌 我们自有办法 步骤如下:
一、找到MediaMetadataRetriever的源码 复制到你的工程里面去
切忌: 包名必须与MediaMetadataRetriever本身在系统里面的包名一样,也就是包名必须为android.media
二、找到so文件 新建一个和src同级别的libs文件夹 把so文件复制进去 这个so文件的名字大概为libmedia_jni.so
可能有人要问 如何获得so文件呢 方法有两个
A:如果你有android的系统源码 你直接可以搜索libmedia_jni.so 就能得到
B:在androidsdk目录——tools——ddms.bat 启动ddms
Device——File Explore
打开一个文件浏览器
system——lib——libmedia_jni.so
三、
这样之后 你就可以用MediaMetadataRetriever类了
MediaMetadataRetriever主要有两个功能:MODE_GET_METADATA_ONLY和MODE_CAPTURE_FRAME_ONLY
mode为MODE_CAPTURE_FRAME_ONLY时
调用captureFrame取得一帧。
mode为MODE_GET_METADATA_ONLY时
extractMetadata 提取文件信息,ARTIST、DATE、YEAR、DURATION、RATING、FRAME_RATE、VIDEO_FORMAT 可以得到时长等信息
和extractAlbumArt 提取专辑信息,这个下面的音乐文件可以用到。
代码如下:
获得缩略图
private Bitmap createVideoThumbnail(String filePath) { Bitmap bitmap = null; android.media.MediaMetadataRetriever retriever = new android.media.MediaMetadataRetriever(); try { retriever.setMode(android.media.MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY); retriever.setDataSource(filePath); bitmap = retriever.captureFrame(); } catch(IllegalArgumentException ex) { // Assume this is a corrupt video file } catch (RuntimeException ex) { // Assume this is a corrupt video file. } finally { try { retriever.release(); } catch (RuntimeException ex) { // Ignore failures while cleaning up. } } return bitmap; }
获得时长
private String ttt(String filePath){ android.media.MediaMetadataRetriever retriever = new android.media.MediaMetadataRetriever(); retriever.setMode(android.media.MediaMetadataRetriever.MODE_GET_METADATA_ONLY); retriever.setDataSource(filePath); String str = retriever.extractMetadata(android.media.MediaMetadataRetriever.METADATA_KEY_DURATION); System.out.println(str +" ====="); return str; }
下面是转载的另一篇 获取SD卡视频文件缩略图
private Bitmap createVideoThumbnail(String filePath) { Bitmap bitmap = null; MediaMetadataRetriever retriever = new MediaMetadataRetriever(); try { retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY); retriever.setDataSource(filePath); bitmap = retriever.captureFrame(); } catch(IllegalArgumentException ex) { // Assume this is a corrupt video file } catch (RuntimeException ex) { // Assume this is a corrupt video file. } finally { try { retriever.release(); } catch (RuntimeException ex) { // Ignore failures while cleaning up. } } return bitmap; } private void getVideoFile(final List list){ Bitmap bitmap = null; ContentResolver mContentResolver = this.getContentResolver(); Cursor cursor = mContentResolver.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, null, null, null, MediaStore.Video.DEFAULT_SORT_ORDER); if (cursor.moveToFirst()) { do { //ID:MediaStore.Audio.Media._ID int id = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID)); //名称 :MediaStore.Audio.Media.TITLE String tilte = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.TITLE)); //专辑名:MediaStore.Audio.Media.ALBUM String album = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.ALBUM)); //歌手名: MediaStore.Audio.Media.ARTIST String artist = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.ARTIST)); //路径 :MediaStore.Audio.Media.DATA String url = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA)); //总播放时长 :MediaStore.Audio.Media.DURATION int duration = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATION)); //大小 :MediaStore.Audio.Media.SIZE int size = (int)cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.SIZE)); //拍摄时间 int dateTaken = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATE_TAKEN)); String datetime = DateFormat.format("yyyy-MM-dd kk:mm:ss", dateTaken).toString(); bitmap = createVideoThumbnail(url); }
MediaMetadataRetriever.java
应放在工程的:
android.media 下面
跟上 MediaMetadataRetriever 类:
/** Copyright (C) 2008 The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package android.media;import android.content.ContentResolver;import android.content.Context;import android.content.res.AssetFileDescriptor;import android.graphics.Bitmap;import android.net.Uri;import android.os.ParcelFileDescriptor;import java.io.FileDescriptor;import java.io.IOException;import java.io.FileNotFoundException;/*** MediaMetadataRetriever class provides a unified interface for retrieving* frame and meta data from an input media file.* {@hide}*/public class MediaMetadataRetriever{ static { System.loadLibrary("media_jni"); } // The field below is accessed by native methods @SuppressWarnings("unused") private int mNativeContext; public MediaMetadataRetriever() { native_setup(); } /** * Call this method before setDataSource() so that the mode becomes * effective for subsequent operations. This method can be called only once * at the beginning if the intended mode of operation for a * MediaMetadataRetriever object remains the same for its whole lifetime, * and thus it is unnecessary to call this method each time setDataSource() * is called. If this is not never called (which is allowed), by default the * intended mode of operation is to both capture frame and retrieve meta * data (i.e., MODE_GET_METADATA_ONLY | MODE_CAPTURE_FRAME_ONLY). * Often, this may not be what one wants, since doing this has negative * performance impact on execution time of a call to setDataSource(), since * both types of operations may be time consuming. * * @param mode The intended mode of operation. Can be any combination of * MODE_GET_METADATA_ONLY and MODE_CAPTURE_FRAME_ONLY: * 1. MODE_GET_METADATA_ONLY & MODE_CAPTURE_FRAME_ONLY: * For neither frame capture nor meta data retrieval * 2. MODE_GET_METADATA_ONLY: For meta data retrieval only * 3. MODE_CAPTURE_FRAME_ONLY: For frame capture only * 4. MODE_GET_METADATA_ONLY | MODE_CAPTURE_FRAME_ONLY: * For both frame capture and meta data retrieval */ public native void setMode(int mode); /** * @return the current mode of operation. A negative return value indicates * some runtime error has occurred. */ public native int getMode(); /** * Sets the data source (file pathname) to use. Call this * method before the rest of the methods in this class. This method may be * time-consuming. * * @param path The path of the input media file. * @throws IllegalArgumentException If the path is invalid. */ public native void setDataSource(String path) throws IllegalArgumentException; /** * Sets the data source (FileDescriptor) to use. It is the caller's * responsibility to close the file descriptor. It is safe to do so as soon * as this call returns. Call this method before the rest of the methods in * this class. This method may be time-consuming. * * @param fd the FileDescriptor for the file you want to play * @param offset the offset into the file where the data to be played starts, * in bytes. It must be non-negative * @param length the length in bytes of the data to be played. It must be * non-negative. * @throws IllegalArgumentException if the arguments are invalid */ public native void setDataSource(FileDescriptor fd, long offset, long length) throws IllegalArgumentException; /** * Sets the data source (FileDescriptor) to use. It is the caller's * responsibility to close the file descriptor. It is safe to do so as soon * as this call returns. Call this method before the rest of the methods in * this class. This method may be time-consuming. * * @param fd the FileDescriptor for the file you want to play * @throws IllegalArgumentException if the FileDescriptor is invalid */ public void setDataSource(FileDescriptor fd) throws IllegalArgumentException { // intentionally less than LONG_MAX setDataSource(fd, 0, 0x7ffffffffffffffL); } /** * Sets the data source as a content Uri. Call this method before * the rest of the methods in this class. This method may be time-consuming. * * @param context the Context to use when resolving the Uri * @param uri the Content URI of the data you want to play * @throws IllegalArgumentException if the Uri is invalid * @throws SecurityException if the Uri cannot be used due to lack of * permission. */ public void setDataSource(Context context, Uri uri) throws IllegalArgumentException, SecurityException { if (uri == null) { throw new IllegalArgumentException(); } String scheme = uri.getScheme(); if(scheme == null || scheme.equals("file")) { setDataSource(uri.getPath()); return; } AssetFileDescriptor fd = null; try { ContentResolver resolver = context.getContentResolver(); try { fd = resolver.openAssetFileDescriptor(uri, "r"); } catch(FileNotFoundException e) { throw new IllegalArgumentException(); } if (fd == null) { throw new IllegalArgumentException(); } FileDescriptor descriptor = fd.getFileDescriptor(); if (!descriptor.valid()) { throw new IllegalArgumentException(); } // Note: using getDeclaredLength so that our behavior is the same // as previous versions when the content provider is returning // a full file. if (fd.getDeclaredLength() < 0) { setDataSource(descriptor); } else { setDataSource(descriptor, fd.getStartOffset(), fd.getDeclaredLength()); } return; } catch (SecurityException ex) { } finally { try { if (fd != null) { fd.close(); } } catch(IOException ioEx) { } } setDataSource(uri.toString()); } /** * Call this method after setDataSource(). This method retrieves the * meta data value associated with the keyCode. * * The keyCode currently supported is listed below as METADATA_XXX * constants. With any other value, it returns a null pointer. * * @param keyCode One of the constants listed below at the end of the class. * @return The meta data value associate with the given keyCode on success; * null on failure. */ public native String extractMetadata(int keyCode); /** * Call this method after setDataSource(). This method finds a * representative frame if successful and returns it as a bitmap. This is * useful for generating a thumbnail for an input media source. * * @return A Bitmap containing a representative video frame, which * can be null, if such a frame cannot be retrieved. */ public native Bitmap captureFrame(); /** * Call this method after setDataSource(). This method finds the optional * graphic or album art associated (embedded or external url linked) the * related data source. * * @return null if no such graphic is found. */ public native byte[] extractAlbumArt(); /** * Call it when one is done with the object. This method releases the memory * allocated internally. */ public native void release(); private native void native_setup(); private native final void native_finalize(); @Override protected void finalize() throws Throwable { try { native_finalize(); } finally { super.finalize(); } } public static final int MODE_GET_METADATA_ONLY = 0x01; public static final int MODE_CAPTURE_FRAME_ONLY = 0x02; /* * Do not change these values without updating their counterparts * in include/media/mediametadataretriever.h! */ public static final int METADATA_KEY_CD_TRACK_NUMBER = 0; public static final int METADATA_KEY_ALBUM = 1; public static final int METADATA_KEY_ARTIST = 2; public static final int METADATA_KEY_AUTHOR = 3; public static final int METADATA_KEY_COMPOSER = 4; public static final int METADATA_KEY_DATE = 5; public static final int METADATA_KEY_GENRE = 6; public static final int METADATA_KEY_TITLE = 7; public static final int METADATA_KEY_YEAR = 8; public static final int METADATA_KEY_DURATION = 9; public static final int METADATA_KEY_NUM_TRACKS = 10; public static final int METADATA_KEY_IS_DRM_CRIPPLED = 11; public static final int METADATA_KEY_CODEC = 12; public static final int METADATA_KEY_RATING = 13; public static final int METADATA_KEY_COMMENT = 14; public static final int METADATA_KEY_COPYRIGHT = 15; public static final int METADATA_KEY_BIT_RATE = 16; public static final int METADATA_KEY_FRAME_RATE = 17; public static final int METADATA_KEY_VIDEO_FORMAT = 18; public static final int METADATA_KEY_VIDEO_HEIGHT = 19; public static final int METADATA_KEY_VIDEO_WIDTH = 20; // Add more here...}
更多相关文章
- android studio 3.0 报错 Unable to find method 'com.android.b
- Android判断文件类型(视频、音频、图片等)
- 获取sdcard文件
- 【Android】共享APK中的资源文件
- Android(安卓)本地文件管理类
- android判断当前设备的支持哪些Feature
- Android(安卓)结束进程的方法forceStopPackage
- Android如何获取asset目录下所有文件的路径
- NPM 和webpack 的基础使用