您的位置:首页 > 移动开发 > Android开发

Android中如何获取视频文件的缩略图

2014-10-09 15:37 393 查看
在android中获取视频文件的缩略图有三种方法:

1.从媒体库中查询

2. android 2.2以后使用ThumbnailUtils类获取

3.调用jni文件,实现MediaMetadataRetriever类

三种方法各有利弊

第一种方法,新视频增加后需要SDCard重新扫描才能给新增加的文件添加缩略图,灵活性差,而且不是很稳定,适合简单应用

第二种方法,实现简单,但2.2以前的版本不支持

第三种方法,实现复杂,但比较灵活,推荐使用

下面给出三种方法的Demo

1.第一种方法:

public static Bitmap getVideoThumbnail(ContentResolver cr, String fileName) {

Bitmap bitmap = null;

BitmapFactory.Options options = new BitmapFactory.Options();

options.inDither = false;

options.inPreferredConfig = Bitmap.Config.ARGB_8888;

//select condition.

String whereClause = MediaStore.Video.Media.DATA + ” = ‘”

+ fileName + “‘”;

Log.v(TAG, “where = ” + whereClause);

//colection of results.

Cursor cursor = cr.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,

new String[] { MediaStore.Video.Media._ID }, whereClause,

null, null);

Log.v(TAG, “cursor = ” + cursor);

if (cursor == null || cursor.getCount() == 0) {

return null;

}

cursor.moveToFirst();

//image id in image table.

String videoId = cursor.getString(cursor

.getColumnIndex(MediaStore.Video.Media._ID));

Log.v(TAG, “videoId = ” + videoId);

if (videoId == null) {

return null;

}

cursor.close();

long videoIdLong = Long.parseLong(videoId);

//via imageid get the bimap type thumbnail in thumbnail table.

bitmap = MediaStore.Video.Thumbnails.getThumbnail(cr, videoIdLong,

Images.Thumbnails.MICRO_KIND, options);

Log.v(TAG, “bitmap = ” + bitmap);

return bitmap;

}

2. 第二种方法:

通过ThumbnailUtils的三种静态方法。

1. static Bitmap createVideoThumbnail(String filePath, int kind) //获取视频文件的缩略图,第一个参数为视频文件的位置,比如/sdcard/android123.3gp,而第二个参数可以为MINI_KIND或 MICRO_KIND最终和分辨率有关

2. static Bitmap extractThumbnail(Bitmap source, int width, int height, int options) //直接对Bitmap进行缩略操作,最后一个参数定义为OPTIONS_RECYCLE_INPUT ,来回收资源

3. static Bitmap extractThumbnail(Bitmap source, int width, int height) // 这个和上面的方法一样,无options选项

3. 第三种方法:

MediaMetadataRetriever是android中隐藏的一个类,开发者无法调用,只能实现一个相同的类来完成相关功能。

一种方式是修改android源码,将frameworks MediaMetadataRetriever.java中@hide标签去掉,在current.xml中添加MediaMetadataRetriever到可用.重新编译frameworks,应用就可以调用到MediaMetadataRetriever这个类了…这样是不适合应用开发的。

推荐的方法是实现MediaMetadataRetriever类

第一步:首先需要下载JNI库:libmedia_jni.so

进入SDK的Tools目录下,运行DDMS,

在DDMS中的菜单栏中,执行Device–FileExplore,

在弹出的文件列表中选择: System-Lib-libmedia_jni.so

选中这个文件后, 在弹出的文件列表的又上脚执行PULL file from device,提取出libmedia_jni.so文件

在Eclipse中新建文件夹libs-armeabi-,在里面放入libmedia_jni.so文件

第二部:实现MediaMetadataRetriever

public class MediaMetadataRetriever

{

static {

System.loadLibrary(“media_jni”);

native_init();

}

// 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 static native void native_init();

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 = 0×01;

public static final int MODE_CAPTURE_FRAME_ONLY = 0×02;

/*

* 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;

public static final int METADATA_KEY_WRITER = 21;

public static final int METADATA_KEY_MIMETYPE = 22;

public static final int METADATA_KEY_DISCNUMBER = 23;

public static final int METADATA_KEY_ALBUMARTIST = 24;

// Add more here…

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: