• android 中获取视频文件的缩略图(非原创)


    在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…
    }

  • 相关阅读:
    退役了
    Luogu1835 素数密度_NOI导刊2011提高(04
    Luogu1941 飞扬的小鸟
    Luogu4711 「化学」相对分子质量
    CF285E Positions in Permutations
    JZOJ 5944
    BZOJ3827: [Poi2014]Around the world && CF526E Transmitting Levels
    BZOJ3831: [Poi2014]Little Bird
    CF526F Pudding Monsters
    运算符重载
  • 原文地址:https://www.cnblogs.com/yishujun/p/5412639.html
Copyright © 2020-2023  润新知