引用JNI版本----MediaMetadataRetriever获取视频缩略图(真机4.0测试通过)
16lz
2021-01-26
在 DDMS-file browser-system-lib导出jni库函数:libmedia_jni.so
然后在android项目中libs文件夹下面建立armeabi文件夹并把库函数拷贝进来;
然后创建一个android.media包(必须要在这个包下创建,否则出错),并创建MediaMetadataRetriever类,我在网上找到的这个类,Android 视频缩略图之MediaMetadataRetriever
有些方法已经不存在了,应该是版本问题,
没办法我只好看源码的jni(frameworks\base\media\jni)文件,看了之后知道有哪些函数,但是因为没接触过jni,所以要传哪些参数都没看懂,所以偷懒了
去android developers看了API(猛击这里),这样也确认了API的正确,也知道如何传参。
这样我重新在从网上获取到的这个类(MediaMetadataRetriever),再加上几行简单的 native 函数声明就简单粗暴的解决了我的问题。。
之所以导入jni库来获取缩略图是为了不用考虑版本问题,或者说简化维护版本问题。。
在android.media包下的代码:
package android.media;//package android.media;import java.io.FileDescriptor;import java.io.FileNotFoundException;import java.io.IOException;import android.content.ContentResolver;import android.content.Context;import android.content.res.AssetFileDescriptor;import android.graphics.Bitmap;import android.net.Uri;/*** 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 at any time position if possible, * and returns it as a bitmap. T * his is useful for generating a thumbnail for an input data source. * Call this method if one does not care about where the frame is located; * @return A Bitmap containing a representative video frame, * which can be null, if such a frame cannot be retrieved. */ public native Bitmap getFrameAtTime(); /** * 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...}
在另一个java包(com.example.thumbnaildemo)中的代码:
package com.example.thumbnaildemo;import java.io.File;import java.io.InputStream;import java.util.ArrayList;import java.util.List;import android.app.Activity;import android.content.ContentResolver;import android.database.Cursor;import android.graphics.Bitmap;import android.graphics.drawable.BitmapDrawable;import android.media.MediaMetadataRetriever;import android.media.ThumbnailUtils;import android.os.Bundle;import android.os.Environment;import android.provider.MediaStore;import android.provider.MediaStore.Video;import android.text.format.DateFormat;import android.util.Log;import android.widget.ImageView;public class MainActivity extends Activity { final static String TAG = "MainActivity";ImageView thumbnails;@Overrideprotected void onCreate(Bundle savedInstanceState) {Log.i(TAG,"------------------onCreate---------------------------");super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);thumbnails=(ImageView)findViewById(R.id.imageView2);/*InputStream input = getResources().openRawResource(R.drawable.girl); BitmapDrawable girl = new BitmapDrawable(input); Bitmap bitmap = girl.getBitmap(); bitmap =ThumbnailUtils.extractThumbnail(bitmap, 50, 50); thumbnails.setImageBitmap(bitmap);*/ File file = new File("/sdcard/mp4/china.mp4"); Bitmap bitmap = createVideoThumbnail(file.getAbsolutePath()); thumbnails.setImageBitmap(bitmap);/*List
更多相关文章
- Android(安卓)简史
- 从assets文件夹中读取txt文件
- Android(安卓)N及以上版本应用安装包下载完成自动弹出安装界面的
- Android(安卓)的一些基本问题解决方法(android studio)
- MyEclip1se8.5搭建Android环境
- 零基础学习教程之Linux下搭建android开发环境
- Java.lang.UnsatisfiedLinkError :nativeSetExternalAssetPath错
- MTP 看不到软件创建的文件夹(Android端)
- Tensorflow编译android平台的so库和jar包