Android:是否可以显示video缩略图?
我用库对话框创build了一个video录制应用程序。 库对话框以下列方式显示录制的video列表,其中每个项目由图标,video标题,标签和位置信息组成:
有谁知道是否有可能用video缩略图(单帧预览)replace图标?
谢谢!
如果您使用API 2.0或更新,这将工作。
int id = **"The Video's ID"** ImageView iv = (ImageView ) convertView.findViewById(R.id.imagePreview); ContentResolver crThumb = getContentResolver(); BitmapFactory.Options options=new BitmapFactory.Options(); options.inSampleSize = 1; Bitmap curThumb = MediaStore.Video.Thumbnails.getThumbnail(crThumb, id, MediaStore.Video.Thumbnails.MICRO_KIND, options); iv.setImageBitmap(curThumb);
如果你没有或不能通过光标,如果你只有path或文件对象,你可以使用自API级别8(2.2)公共静态位图createVideoThumbnail(String filePath,inttypes)
Android文档
以下代码完美运行:
Bitmap bMap = ThumbnailUtils.createVideoThumbnail(file.getAbsolutePath(), MediaStore.Video.Thumbnails.MICRO_KIND);
使用类:
import android.provider.MediaStore.Video.Thumbnails;
我们可以从video中获得两个预览缩略图大小:
Thumbnails.MICRO_KIND
为96 x 96
Thumbnails.MINI_KIND
为512 x 384像素
这是一个代码示例:
String filePath = "/sdcard/DCIM/Camera/my_video.mp4"; //change the location of your file! ImageView imageview_mini = (ImageView)findViewById(R.id.thumbnail_mini); ImageView imageview_micro = (ImageView)findViewById(R.id.thumbnail_micro); Bitmap bmThumbnail; //MICRO_KIND, size: 96 x 96 thumbnail bmThumbnail = ThumbnailUtils.createVideoThumbnail(filePath, Thumbnails.MICRO_KIND); imageview_micro.setImageBitmap(bmThumbnail); // MINI_KIND, size: 512 x 384 thumbnail bmThumbnail = ThumbnailUtils.createVideoThumbnail(filePath, Thumbnails.MINI_KIND); imageview_mini.setImageBitmap(bmThumbnail);
目前我使用下面的代码:
Bitmap bMap = ThumbnailUtils.createVideoThumbnail(file.getAbsolutePath(), MediaStore.Video.Thumbnails.MICRO_KIND);
但是,我发现更好的解决scheme与Glide库下面的代码(它也caching你的形象,比以前的方法有更好的性能)
Glide.with(context) .load(uri) .placeholder(R.drawable.ic_video_place_holder) .into(imageView);
我真的build议你使用Glide库。 这是生成和显示本地video文件的video缩略图的最有效方法之一。
只需将此行添加到您的gradle文件中:
compile 'com.github.bumptech.glide:glide:3.7.0'
这将变得如此简单:
String filePath = "/storage/emulated/0/Pictures/example_video.mp4"; Glide .with( context ) .load( Uri.fromFile( new File( filePath ) ) ) .into( imageViewGifAsBitmap );
你可以在这里find更多的信息: https : //futurestud.io/blog/glide-displaying-gifs-and-videos
干杯!
Android 1.5和1.6不提供这个缩略图,但正如发行说明中所看到的那样,2.0就是这样:
媒体
- MediaScanner现在可以为插入到MediaStore中的所有图像生成缩略图。
- 新的缩略图API,用于根据需要检索图像和video缩略图。
此解决scheme将适用于任何版本的Android。 它已被certificate在1.5和2.2工作。这不是另一个“这是为Android 2.0以上”的解决scheme。 我通过电子邮件信息板集合页面find了这个,并找不到原始链接。 所有的功劳都归原作。
在你的应用程序中,你可以通过调用这个
Bitmap bm = getVideoFrame(VideoStringUri);
在它自己的function(在OnCreate等)之外的某个地方,你需要:
private Bitmap getVideoFrame(String uri) { MediaMetadataRetriever retriever = new MediaMetadataRetriever(); try { retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY); retriever.setDataSource(uri); return retriever.captureFrame(); } catch (IllegalArgumentException ex) { ex.printStackTrace(); } catch (RuntimeException ex) { ex.printStackTrace(); } finally { try { retriever.release(); } catch (RuntimeException ex) { } } return null; }
在你的src文件夹中,你需要一个新的子目录android / media来存放这个类(从android源码本身复制而来),它允许你使用这个函数。 这部分不应该改变,重新命名或放置在其他地方。 MediaMetadataRetriever.java需要在你的源文件夹下的android.media下才能运行。
/* * 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 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"); native_init(); } // The field below is accessed by native methods 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 (ie, 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 = 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; 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... }
这是直播video缩略图的代码。
public class LoadVideoThumbnail extends AsyncTask<Object, Object, Bitmap>{ @Override protected Bitmap doInBackground(Object... params) {try { String mMediaPath = "http://commonsware.com/misc/test2.3gp"; Log.e("TEST Chirag","<< thumbnail doInBackground"+ mMediaPath); FileOutputStream out; File land=new File(Environment.getExternalStorageDirectory().getAbsoluteFile() +"/portland.jpg"); Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(mMediaPath, MediaStore.Video.Thumbnails.MICRO_KIND); ByteArrayOutputStream stream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream); byte[] byteArray = stream.toByteArray(); out=new FileOutputStream(land.getPath()); out.write(byteArray); out.close(); return bitmap; } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } @Override protected void onPostExecute(Bitmap result) { // TODO Auto-generated method stub super.onPostExecute(result); if(result != null){ ((ImageView)findViewById(R.id.imageView1)).setImageBitmap(result); } Log.e("TEST Chirag","====> End"); } }
- FILL_AND_STROKE有什么意义?
- PopupWindow $ BadTokenException:无法添加窗口 – 标记null无效
- 错误:程序包“com.google.example”main.xml中的属性“adSize”找不到资源标识符
- 如何在外部方法中获取值asynchronousonDataChange()
- Android的错误
- Android上的Web视图支持SSL吗?
- Android:自动selectdebugging/发布Maps v2 api key?
- 从Android电子市场安装应用后获取引荐来源
- Dialogs / AlertDialogs:如何在对话框启动时阻止执行(.NET风格)