如何获取 /sdcard/Android/data/mypackage/files 文件夹中视频的缩略图?

发布于 2024-10-05 02:12:34 字数 902 浏览 4 评论 0原文

MediaStore.Video.Media.EXTERNAL_CONTENT_URI 的查询仅返回 /sdcard/DCIM/100MEDIA 中的视频,

但我想获取 /sdcard/Android 中视频的缩略图/data/mypackage/files 文件夹。是否可以 ?

这是我的代码的一部分:

        ContentResolver cr = getContentResolver();
    String[] proj = {
                    BaseColumns._ID
    };

    Cursor c = cr.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, proj, null, null, null);
    if (c.moveToFirst()) {
        do
        {
            int id = c.getInt(0);
            Bitmap b = MediaStore.Video.Thumbnails.getThumbnail(cr, id, MediaStore.Video.Thumbnails.MINI_KIND, null);
            Log.d("*****My Thumbnail*****", "onCreate bitmap " + b);
            ImageView iv = (ImageView) findViewById(R.id.img_thumbnail);
            iv.setImageBitmap(b);
        }
        while( c.moveToNext() );
    }         
    c.close();

Query to MediaStore.Video.Media.EXTERNAL_CONTENT_URI returns only video in /sdcard/DCIM/100MEDIA

But I want to get thumbnails for video in my /sdcard/Android/data/mypackage/files folder. Is it possible ?

Here is part of my code:

        ContentResolver cr = getContentResolver();
    String[] proj = {
                    BaseColumns._ID
    };

    Cursor c = cr.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, proj, null, null, null);
    if (c.moveToFirst()) {
        do
        {
            int id = c.getInt(0);
            Bitmap b = MediaStore.Video.Thumbnails.getThumbnail(cr, id, MediaStore.Video.Thumbnails.MINI_KIND, null);
            Log.d("*****My Thumbnail*****", "onCreate bitmap " + b);
            ImageView iv = (ImageView) findViewById(R.id.img_thumbnail);
            iv.setImageBitmap(b);
        }
        while( c.moveToNext() );
    }         
    c.close();

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

做个ˇ局外人 2024-10-12 02:12:34

如果您使用的是 android-8 (Froyo) 或更高版本,则可以使用 ThumbnailUtils.createVideoThumbnail

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

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

Bitmap thumb = ThumbnailUtils.createVideoThumbnail(path,
    MediaStore.Images.Thumbnails.MINI_KIND);
我早已燃尽 2024-10-12 02:12:34

使用 Glide 它将异步获取缩略图。

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

Use Glide it will fetch the thumbnail in async.

 Glide.with(context)
                    .load(videoFilePath) // or URI/path
                    .into(imgView); //imageview to set thumbnail to
倒数 2024-10-12 02:12:34

从视频中获取缩略图的 3 种方法:

  1. 最好的方法是使用 Glide 。它将在后台完成所有工作,将缩略图直接加载到 ImageView 中,甚至可以在加载时显示动画。它可以与 Uri、byte[] 和许多其他源一起使用。
    正如@Ajji 提到的:

    Glide.with(上下文)
                .load(videoFilePath) // 或 URI/路径
                .into(imgView); //imageview设置缩略图
    
  2. 如果您只需要以最有效的方式获取位图 - 使用ThumbnailUtils
    就我而言,它生成了一个大小为 294 912 字节的位图(使用 Nexus5X 相机拍摄的视频 - 1280x720),质量与下一种方法相同。用 90 压缩成 JPEG 后,将生成约 30Kb 的 jpeg 文件。

    位图缩略图 = ThumbnailUtils.createVideoThumbnail(path,
    MediaStore.Images.Thumbnails.MINI_KIND);
    
  3. 最后一种方法是使用MediaMetadataRetriever。但就我而言,它生成的位图大小比使用 ThumbnailUtils 生成的位图大 6 倍以上(具有相同的质量)。因此,请将其视为最后的手段。

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

PS:不要忘记,Bitmapbyte[]real file .jpeg 格式的图像可以在这些格式中以任何方向轻松转换类型。对于 Uri,您通常没有源文件的真实路径,但您始终可以像这样从中获取字节流:

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

并且使用此输入流您可以做任何您想做的事情。

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.

满身野味 2024-10-12 02:12:34

您可以只使用 FFmpegMediaMetadataRetriever 并忘记反射:

/**
 *
 * @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;
}

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;
}
紧拥背影 2024-10-12 02:12:34
BitmapFactory.Options options = new BitmapFactory.Options();
options.inDither = false;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;

Bitmap bitmapThumb = MediaStore.Video.Thumbnails.getThumbnail(mActivity.getContentResolver(),
     Long.parseLong(video_id), 
     Images.Thumbnails.MINI_KIND, 
     options);

使用选项加载位图以减小位图大小。

BitmapFactory.Options options = new BitmapFactory.Options();
options.inDither = false;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;

Bitmap bitmapThumb = MediaStore.Video.Thumbnails.getThumbnail(mActivity.getContentResolver(),
     Long.parseLong(video_id), 
     Images.Thumbnails.MINI_KIND, 
     options);

Use Options to load bitmap of decrease the bitmap size..

憧憬巴黎街头的黎明 2024-10-12 02:12:34

请参阅@Ajji的回答:

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

它有时会返回黑色图像,这个问题已在 Glide 库的问题中提到

使用此代码:

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

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);
谁对谁错谁最难过 2024-10-12 02:12:34

VIDEO_ID 获取视频缩略图:

public static Drawable getVideoThumbnail(Context context, int videoID) {
        try {
            String[] projection = {
                    MediaStore.Video.Thumbnails.DATA,
            };
            ContentResolver cr = context.getContentResolver();
            Cursor cursor = cr.query(
                    MediaStore.Video.Thumbnails.EXTERNAL_CONTENT_URI,
                    projection, 
                    MediaStore.Video.Thumbnails.VIDEO_ID + "=?", 
                    new String[] { String.valueOf(videoID) }, 
                    null);
            cursor.moveToFirst();
            return Drawable.createFromPath(cursor.getString(0));
        } catch (Exception e) {
        }
        return null;
    }

Get video thumbnail from VIDEO_ID:

public static Drawable getVideoThumbnail(Context context, int videoID) {
        try {
            String[] projection = {
                    MediaStore.Video.Thumbnails.DATA,
            };
            ContentResolver cr = context.getContentResolver();
            Cursor cursor = cr.query(
                    MediaStore.Video.Thumbnails.EXTERNAL_CONTENT_URI,
                    projection, 
                    MediaStore.Video.Thumbnails.VIDEO_ID + "=?", 
                    new String[] { String.valueOf(videoID) }, 
                    null);
            cursor.moveToFirst();
            return Drawable.createFromPath(cursor.getString(0));
        } catch (Exception e) {
        }
        return null;
    }
瀞厅☆埖开 2024-10-12 02:12:34

您可以将此方法与任何 Uri 结合使用:

public static Bitmap getVideoFrame(Uri uri, Context context) {
    MediaMetadataRetriever retriever = new MediaMetadataRetriever();
    retriever.setDataSource(context, uri);
    return retriever.getFrameAtTime();
}

You can use this method with any Uri:

public static Bitmap getVideoFrame(Uri uri, Context context) {
    MediaMetadataRetriever retriever = new MediaMetadataRetriever();
    retriever.setDataSource(context, uri);
    return retriever.getFrameAtTime();
}
喵星人汪星人 2024-10-12 02:12:34

这是与马修·威利斯类似的答案,但增加了反思。为什么?因为科学。

/**
 *
 * @param path
 *            the path to the Video
 * @return a thumbnail of the video or null if retrieving the thumbnail failed.
 */
public static Bitmap getVidioThumbnail(String path) {
    Bitmap bitmap = null;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) {
        bitmap = ThumbnailUtils.createVideoThumbnail(path, Thumbnails.MICRO_KIND);
        if (bitmap != null) {
            return bitmap;
        }
    }
    // MediaMetadataRetriever is available on API Level 8 but is hidden until API Level 10
    Class<?> clazz = null;
    Object instance = null;
    try {
        clazz = Class.forName("android.media.MediaMetadataRetriever");
        instance = clazz.newInstance();
        final Method method = clazz.getMethod("setDataSource", String.class);
        method.invoke(instance, path);
        // The method name changes between API Level 9 and 10.
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD) {
            bitmap = (Bitmap) clazz.getMethod("captureFrame").invoke(instance);
        } else {
            final byte[] data = (byte[]) clazz.getMethod("getEmbeddedPicture").invoke(instance);
            if (data != null) {
                bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
            }
            if (bitmap == null) {
                bitmap = (Bitmap) clazz.getMethod("getFrameAtTime").invoke(instance);
            }
        }
    } catch (Exception e) {
        bitmap = null;
    } finally {
        try {
            if (instance != null) {
                clazz.getMethod("release").invoke(instance);
            }
        } catch (final Exception ignored) {
        }
    }
    return bitmap;
}

Here is a similar answer to Matthew Willis but with added reflection. Why? because science.

/**
 *
 * @param path
 *            the path to the Video
 * @return a thumbnail of the video or null if retrieving the thumbnail failed.
 */
public static Bitmap getVidioThumbnail(String path) {
    Bitmap bitmap = null;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) {
        bitmap = ThumbnailUtils.createVideoThumbnail(path, Thumbnails.MICRO_KIND);
        if (bitmap != null) {
            return bitmap;
        }
    }
    // MediaMetadataRetriever is available on API Level 8 but is hidden until API Level 10
    Class<?> clazz = null;
    Object instance = null;
    try {
        clazz = Class.forName("android.media.MediaMetadataRetriever");
        instance = clazz.newInstance();
        final Method method = clazz.getMethod("setDataSource", String.class);
        method.invoke(instance, path);
        // The method name changes between API Level 9 and 10.
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD) {
            bitmap = (Bitmap) clazz.getMethod("captureFrame").invoke(instance);
        } else {
            final byte[] data = (byte[]) clazz.getMethod("getEmbeddedPicture").invoke(instance);
            if (data != null) {
                bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
            }
            if (bitmap == null) {
                bitmap = (Bitmap) clazz.getMethod("getFrameAtTime").invoke(instance);
            }
        }
    } catch (Exception e) {
        bitmap = null;
    } finally {
        try {
            if (instance != null) {
                clazz.getMethod("release").invoke(instance);
            }
        } catch (final Exception ignored) {
        }
    }
    return bitmap;
}
闻呓 2024-10-12 02:12:34

如果您直接创建缩略图如下

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

如果您正在为大型视频集(针对大量视频)创建缩略图,则此方法会出现问题。应用程序将冻结,直到加载所有缩略图,因为所有进程都在主线程中执行。

使用 SuziLoader

此加载程序将在后台加载本地存储在文件系统上的视频缩略图。

String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/video.mp4";
ImageView mThumbnail = (ImageView) findViewById(R.id.thumbnail);

SuziLoader loader = new SuziLoader(); //Create it for once
loader.with(MainActivity.this) //Context
    .load(path) //Video path
    .into(mThumbnail) // imageview to load the thumbnail
    .type("mini") // mini or micro
    .show(); // to show the thumbnail

要获取此依赖项,请使用以下步骤

第 1 步。将 JitPack 存储库添加到您的构建文件
将其添加到存储库末尾的根 build.gradle 中:

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}

添加依赖项ADD READ EXTERNAL STORAGE Permission

dependencies {
    compile 'com.github.sushinpv:SuziVideoThumbnailLoader:0.1.0'
}

第 2 步。在清单中

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

If you are directly creating thumbnails as follows

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

Then there is a problem with this method if your are creating thumbnails for large video set(for large number of videos). the application will freeze until all the thumbnails are loaded because all the process are executing in the main thread.

Use SuziLoader

This loader will load the thumbnails for the videos which is locally stored on your filesystem in background.

String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/video.mp4";
ImageView mThumbnail = (ImageView) findViewById(R.id.thumbnail);

SuziLoader loader = new SuziLoader(); //Create it for once
loader.with(MainActivity.this) //Context
    .load(path) //Video path
    .into(mThumbnail) // imageview to load the thumbnail
    .type("mini") // mini or micro
    .show(); // to show the thumbnail

To get this dependency use the following steps

Step 1. Add the JitPack repository to your build file
Add it in your root build.gradle at the end of repositories:

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}

Step 2. Add the dependency

dependencies {
    compile 'com.github.sushinpv:SuziVideoThumbnailLoader:0.1.0'
}

ADD READ EXTERNAL STORAGE Permission in manifest

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
旧故 2024-10-12 02:12:34

尝试类似于此代码片段的操作:

img.setImageBitmap(ThumbnailUtils.createVideoThumbnail(
                   Environment.getExternalStorageDirectory().getPath() + "/WhatsApp/Media/WhatsApp Video/"+getItem(position),
                   MediaStore.Video.Thumbnails.FULL_SCREEN_KIND));

Try something similar to this code snippet:

img.setImageBitmap(ThumbnailUtils.createVideoThumbnail(
                   Environment.getExternalStorageDirectory().getPath() + "/WhatsApp/Media/WhatsApp Video/"+getItem(position),
                   MediaStore.Video.Thumbnails.FULL_SCREEN_KIND));
季末如歌 2024-10-12 02:12:34
Uri uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
        String[] projection = { MediaStore.Video.VideoColumns.DATA };
        Cursor c = getContentResolver().query(uri, projection, null, null, null);
        int vidsCount = 0;
        if (c != null) {
            vidsCount = c.getCount();
            while (c.moveToNext()) {
                String path = c.getString(0);
                Bitmap thumb = ThumbnailUtils.createVideoThumbnail(path,
                        MediaStore.Images.Thumbnails.MINI_KIND);
            }
            c.close();
        }
Uri uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
        String[] projection = { MediaStore.Video.VideoColumns.DATA };
        Cursor c = getContentResolver().query(uri, projection, null, null, null);
        int vidsCount = 0;
        if (c != null) {
            vidsCount = c.getCount();
            while (c.moveToNext()) {
                String path = c.getString(0);
                Bitmap thumb = ThumbnailUtils.createVideoThumbnail(path,
                        MediaStore.Images.Thumbnails.MINI_KIND);
            }
            c.close();
        }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文