Android: Можно ли отображать миниатюры видео?

Я создал приложение для записи видео с диалоговым окном библиотеки. Диалоговое окно библиотеки отображает список записанных видеороликов, в которых каждый элемент состоит из значка, заголовка видео, тегов и информации о местоположении следующим образом:

Alt text

Кто-нибудь знает, можно ли заменить значки видео эскизами (предварительный просмотр с одним кадром)?

Благодаря!

Если вы используете 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); 

Если вы не можете или не можете пройти через курсор, и если у вас есть только пути или объекты File, вы можете использовать, поскольку API-уровень 8 (2.2) public static Bitmap createVideoThumbnail (String filePath, int kind)

Документация для Android

Следующий код работает отлично:

 Bitmap bMap = ThumbnailUtils.createVideoThumbnail(file.getAbsolutePath(), MediaStore.Video.Thumbnails.MICRO_KIND); 

Использование класса:

 import android.provider.MediaStore.Video.Thumbnails; 

Мы можем получить два размера миниатюр предварительного просмотра из видео:

Thumbnails.MICRO_KIND для 96 x 96

Thumbnails.MINI_KIND для 512 x 384 px

Это пример кода:

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

Но я нашел лучшее решение с библиотекой Glide со следующим кодом (он также кэширует ваш образ и имеет лучшую производительность, чем предыдущий подход)

 Glide.with(context) .load(uri) .placeholder(R.drawable.ic_video_place_holder) .into(imageView); 

Я действительно предлагаю вам использовать библиотеку Glide . Это один из наиболее эффективных способов генерации и отображения миниатюры видео для локального видеофайла.

Просто добавьте эту строку в свой файл 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 ); 

Вы можете найти более подробную информацию здесь: https://futurestud.io/blog/glide-displaying-gifs-and-videos

Приветствия!

Android 1.5 и 1.6 не предлагают эти миниатюры, но 2.0 делает это, как видно из официальных релизов :

СМИ

  • MediaScanner теперь генерирует эскизы для всех изображений, когда они вставлены в MediaStore.
  • Новый миниатюрный API для получения эскизов изображений и видео по запросу.

Это решение будет работать для любой версии Android. Он доказал свою эффективность в 1.5 и 2.2. Это не другое решение «Это для Android 2.0+». Я нашел это через страницу сбора сообщений электронной почты и не могу найти исходную ссылку. Весь кредит идет на оригинальный плакат.

В своем приложении вы будете использовать это, позвонив:

 Bitmap bm = getVideoFrame(VideoStringUri); 

Где-то в его собственной функции (вне OnCreate, ect) вам понадобится:

 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... } 

Это код для миниатюры видео в реальном времени.

 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"); } } 
Intereting Posts
Какова цель Google Cloud Messaging Перезапустите службу, даже если приложение отключено и продолжает работать в фоновом режиме даже после закрытия приложения How? Ищете способ остановить форсирование моего приложения в полноэкранном режиме, когда показано добавление admob interstitial Сглаживание в TextureView Андроид google map поиск расстояние Как создать базу данных SQLite в Android путем импорта из файла SQL? Gradle: принудительное использование репозитория для зависимости Android GC – LogCat всегда показывает активность GC Android IllegalArgumentException для cancelDialog Android Webview: Mailto не может реализовать Получить JSONObject по ID из другого JSONObject – Android «Невозможно получить ошибку viewWidth после первого макета» Настройка текста текста текста TextView программным способом с помощью setTextColor () отображает андроид: duplicateParentState недействителен Не удается запустить проект андроида на netbeans: ЭТОТ ИНСТРУМЕНТ НЕИСПРАВЛЯЕТСЯ Проект проекта gradle для Android в другом дереве каталогов