How to get thumbnail for video in my /sdcard/Android/data/mypackage/files folder?

If you are on android-8 (Froyo) or above, you can use ThumbnailUtils.createVideoThumbnail:

Bitmap thumb = ThumbnailUtils.createVideoThumbnail(path,
    MediaStore.Images.Thumbnails.MINI_KIND);

Use Glide it will fetch the thumbnail in async.

 Glide.with(context)
                    .load(videoFilePath) // or URI/path
                    .into(imgView); //imageview to set thumbnail to

3 ways to get a thumbnail from a video:

  1. The best way is to use Glide. It will do all the work in the background, load the thumbnail right into the ImageView and even can show animation when loading. It can work with Uri, byte[] and many other sources. As @Ajji mentioned:

    Glide.with(context)
                .load(videoFilePath) // or URI/path
                .into(imgView); //imageview to set thumbnail to
    
  2. If you just need a bitmap in the most efficient way - use ThumbnailUtils. In my case, it produced a bitmap with a size of 294 912 bytes (video taken with a camera of Nexus5X - 1280x720) and the quality was the same as in the next approach. After you compress into JPEG with 90 it will generate a jpeg file of ~30Kb.

    Bitmap thumb = ThumbnailUtils.createVideoThumbnail(path,
    MediaStore.Images.Thumbnails.MINI_KIND);
    
  3. The last approach is to use MediaMetadataRetriever. But in my case, it produced a bitmap with size more than 6 times bigger than you got with ThumbnailUtils (with the same quality). So consider it as a last resort.

    MediaMetadataRetriever mMMR = new MediaMetadataRetriever();
                        mMMR.setDataSource(mContext, mAttachment.getUri());
                        bmp = mMMR.getFrameAtTime();
    

P.S.: Don't forget that images in Bitmap, byte[] and real file .jpeg formats can be easily converted in any direction within these types. In case of Uri's you often don't have real path to the source file but you can always get the byte stream from it like this:

    InputStream in =  mContext.getContentResolver().openInputStream(uri);

and with this input stream you can do whatever you want.


You can just use FFmpegMediaMetadataRetriever and forget the reflection:

/**
 *
 * @param path
 *            the path to the Video
 * @return a thumbnail of the video or null if retrieving the thumbnail failed.
 */
public static Bitmap getVideoThumbnail(String path) {
    Bitmap bitmap = null;

    FFmpegMediaMetadataRetriever fmmr = new FFmpegMediaMetadataRetriever();  

    try {
        fmmr.setDataSource(path);            

        final byte[] data = fmmr.getEmbeddedPicture();

        if (data != null) {
            bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
        }

        if (bitmap == null) {
            bitmap = fmmr.getFrameAtTime();   
        }
    } catch (Exception e) {
        bitmap = null;
    } finally {
        fmmr.release();
    }
    return bitmap;
}

see @Ajji 's answer :

 Glide.with(context)
                    .load(videoFilePath) // or URI/path
                    .into(imgView); //imageview to set thumbnail to

It sometimes returns black image, this issue is already mentioned in Glide library's issues

Use this code:

 BitmapPool bitmapPool = Glide.get(activity).getBitmapPool();
                int microSecond = 6000000;// 6th second as an example
                VideoBitmapDecoder videoBitmapDecoder = new VideoBitmapDecoder(microSecond);
                FileDescriptorBitmapDecoder fileDescriptorBitmapDecoder = new FileDescriptorBitmapDecoder(videoBitmapDecoder, bitmapPool, DecodeFormat.PREFER_ARGB_8888);
                Glide.with(activity)
                        .load(videoPath)
                        .asBitmap()
                        .override(50,50)// Example
                        .videoDecoder(fileDescriptorBitmapDecoder)
                        .into(holder.ivFirstUpload);