从Uri获取视频缩略图

13
我想从我的图库中选择一个视频。这部分代码运行良好。但现在我想显示一个位图作为缩略图。我尝试了下面的代码,但它一直显示:NullPointerException。

我想从我的图库中选择一个视频。这部分代码运行良好。但现在我想显示一个位图作为缩略图。我尝试了下面的代码,但它一直显示:NullPointerException

Bitmap bitmap2 = ThumbnailUtils.createVideoThumbnail(uri.getPath, MediaStore.Video.Thumbnails.MICRO_KIND);

这全部在一个 onActivityResult() 中。

我该如何从视频 Uri 中获取 Bitmap?

谢谢你的帮助。


尝试这个:https://dev59.com/02Ag5IYBdhLWcg3wfrEn#32689039 - Kriti
8个回答

24
在最新的API 24中,如果您坚持接受答案中的方法,可能会遇到一些问题。例如,在这一行中int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);有时会收到W/System.err: java.lang.IllegalArgumentException: column '_data' does not exist错误信息。此外,在最新的API中,如果您处理小部件或共享内容,可能会出现SecurityException错误,请记住这一点。至于从Uri获取视频缩略图——我使用的是利用MediaMetadataRetriever的方法,因此您不需要获取String filePath:
            MediaMetadataRetriever mMMR = new MediaMetadataRetriever();
            mMMR.setDataSource(context, videoUri);
            bmp = mMMR.getFrameAtTime();

希望这能帮到你


1
如果你听从CommonsWare的建议,最好的方法应该是……我们不应该处理文件或绝对路径,而应该处理可以通过内容提供者访问的内容URI。 - me_
我们能获取图库展示的缩略图吗?我的意思是谷歌照片应用程序显示不同的缩略图,我们能获取完全相同的缩略图吗? - Mateen Chaudhry
这个工作得很好,我试图在getFrameAtTime中放置一个数字,但是会出现黑色图像,似乎必须将其留空..谢谢。 - DragonFire

16

onActivityResult

String[] filePathColumn = {MediaStore.Images.Media.DATA};
Cursor cursor = context.getContentResolver().query(uri, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String picturePath = cursor.getString(columnIndex);
cursor.close();

Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(picturePath, MediaStore.Video.Thumbnails.MICRO_KIND);

编辑

Kotlin 版本

val filePathColumn = arrayOf(MediaStore.Images.Media.DATA)
val cursor = context.contentResolver.query(uri, filePathColumn, null, null, null)
cursor.moveToFirst()

val columnIndex = cursor.getColumnIndex(filePathColumn[0])
val picturePath = cursor.getString(columnIndex)
cursor.close()

val bitmap = ThumbnailUtils.createVideoThumbnail(picturePath, MediaStore.Video.Thumbnails.MICRO_KIND)

1
难道不应该是MediaStore.Video.Media.DATA吗?虽然它们的值相同,但为了严谨起见... - algrid
1
它不适用于Android 26。错误是:“Caused by: android.database.CursorIndexOutOfBoundsException: Requested column: -1, # of columns: 0”。有什么想法吗? - mary
1
我的视频文件的URI格式为:"content://{appId}.fileprovider/external_files/Android/data/{appId}/files/789080a6-0ee1-4efd-8b2a-dd6869be593f"。查询无法找到该文件,因此columnIndex为-1;对于这个问题有什么想法吗? - mary
1
如果我以这种方式更改我的uri,游标将为空。 - mary
2
位图为空。 - mary
显示剩余5条评论

5
尝试一下这个:
Bitmap bitmap2 = ThumbnailUtils.createVideoThumbnail( uri.getPath() , MediaStore.Images.Thumbnails.MINI_KIND );

2

对于API 27,针对文档URI(1000微秒)

MediaMetadataRetriever mmr = new MediaMetadataRetriever();
mmr.setDataSource( context, doc_uri );
Bitmap bm = mmr.getScaledFrameAtTime( 1000, MediaMetadataRetriever.OPTION_NEXT_SYNC, 128, 128 );

0
这对我有效:
Bitmap thumb = ThumbnailUtils.createVideoThumbnail(filePath, Thumbnails.MINI_KIND);

使用ThumbnailUtils,您可以创建两种类型的缩略图。

MediaStore.Images.Thumbnails.MICRO_KIND - 类型将生成大小为96 x 96的缩略图。 MediaStore.Images.Thumbnails.MINI_KIND - 类型将生成大小为512 x 384的缩略图。


0
Cursor c = MediaStore.Video.query(cr,uri, new String[]{
    MediaStore.Video.VideoColumns._ID,
    MediaStore.Video.VideoColumns.DATA});
if (c!=null){
    c.moveToFirst();
    int id = Integer.valueOf( c.getString(0) );
    c.close();
    BitmapFactory.Options options=new BitmapFactory.Options();
    options.inSampleSize = 1;
    try {
        return MediaStore.Video.Thumbnails.getThumbnail(cr, id, MediaStore.Video.Thumbnails.MINI_KIND, options);
    }catch (java.lang.SecurityException ex){
        ex.printStackTrace();
        //TODO: add create ThumbnailUtils.createVideoThumbnail
        return null;
    }
}

1
感谢您提供这段代码片段,它可能会提供一些有限的、即时的帮助。一个适当的解释将极大地提高其长期价值,因为它可以展示为什么这是一个好的问题解决方案,并使其对未来读者在其他类似问题上更有用。请[编辑]您的答案以添加一些解释,包括您所做的假设。 - Dwhitz

0

取消信号 ca = new CancellationSignal();

var vthumb = ThumbnailUtils.createVideoThumbnail(new File(value),new Size(120,120), ca);


0
  1. createVideoThumbnail() 需要文件路径,而不是内容 URI。
  2. 文件路径需要外部读取权限。

如果您收到 null 响应,则可能是使用了内容 URI(尽管在 ThumbnailsUtils.java 中的假设是视频文件损坏)。当我修复了这个问题后,我遇到了权限错误。

我能够通过视频 ID 获取内容 URI 的文件路径,像这样:

val selection = MediaStore.Video.Media._ID + " = $id"
val cursor = 
this.contentResolver.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, null, 
selection, null, null)      

然后像 SO 中其他答案中一样继续使用光标。

contentResolver.query()文档


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接