如何从外部存储、DocumentFile或Uri获取视频缩略图?现有代码返回Bitmap空值
解决从DocumentFile/Uri获取视频缩略图的问题
首先得说清楚你原来的代码为什么会返回null:documentFile.getUri().getPath()拿到的并不是视频文件的真实本地路径,而是content Uri的路径片段(比如/tree/primary:Videos/xxx.mp4),而ThumbnailUtils.createVideoThumbnail接受String路径的那个方法,只能识别真实的本地文件路径,没法处理content Uri,所以自然返回null了。
下面给你几个靠谱的解决方案:
方案一:用MediaMetadataRetriever(推荐,兼容性最好)
这个类可以直接通过content Uri获取视频帧作为缩略图,适配所有Android版本,而且符合Android 10及以上的存储权限规范(不需要访问真实文件路径)。代码示例:
Uri videoUri = documentFile.getUri(); MediaMetadataRetriever retriever = new MediaMetadataRetriever(); Bitmap thumbnail = null; try { // 直接传入Context和视频的content Uri retriever.setDataSource(getBaseContext(), videoUri); // 获取视频第一帧作为缩略图,也可以指定时间戳(比如getFrameAtTime(1000*1000)表示取1秒处的帧) thumbnail = retriever.getFrameAtTime(); // 如果需要固定大小的缩略图,可以对Bitmap进行缩放 // thumbnail = Bitmap.createScaledBitmap(thumbnail, 96, 96, true); } catch (Exception e) { e.printStackTrace(); } finally { // 记得释放资源 retriever.release(); }
方案二:Android 11+用ThumbnailUtils的Uri重载方法
如果你只需要适配Android 11(API 30)及以上版本,可以用ThumbnailUtils新增的支持Uri的重载方法:
Uri videoUri = documentFile.getUri(); Bitmap thumbnail = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { try { // 指定缩略图的尺寸,这里用MICRO_KIND对应的大小 Size thumbnailSize = new Size(MediaStore.Video.Thumbnails.MICRO_KIND, MediaStore.Video.Thumbnails.MICRO_KIND); thumbnail = ThumbnailUtils.createVideoThumbnail(videoUri, thumbnailSize, null); } catch (IOException e) { e.printStackTrace(); } }
关于用InputStream获取缩略图
当然可以!不过要注意,不是所有InputStream都支持MediaMetadataRetriever的数据源设置,最好通过FileDescriptor来处理,示例代码如下:
Uri videoUri = documentFile.getUri(); InputStream inputStream = getContentResolver().openInputStream(videoUri); MediaMetadataRetriever retriever = new MediaMetadataRetriever(); Bitmap thumbnail = null; try { // 通过InputStream的FileDescriptor设置数据源 retriever.setDataSource(inputStream.getFD()); thumbnail = retriever.getFrameAtTime(); } catch (Exception e) { e.printStackTrace(); } finally { retriever.release(); try { if (inputStream != null) { inputStream.close(); } } catch (IOException e) { e.printStackTrace(); } }
不过还是更推荐直接用Uri的方式,代码更简洁,兼容性也更好~
内容的提问来源于stack exchange,提问作者mostafa3dmax
相关产品推荐
相关产品推荐

