安卓端视频缩略图无法显示求助:Glide、Picasso均失效
解决Android中Glide/Picasso加载视频缩略图失败的问题
我来帮你搞定这个视频缩略图加载的坑——之前做视频列表的时候我也踩过类似的雷,咱们一步步排查解决:
先排查最常见的几个原因
- 权限没到位:如果你的视频是存储在外部SD卡,Android 6.0+必须申请
READ_EXTERNAL_STORAGE动态权限,光在Manifest里加权限是不够的。 - 路径/Uri错误:要么是视频文件路径写错了,要么是用了不兼容的Uri格式(比如Content Uri没处理好)。
- 没用到正确的加载API:Glide和Picasso默认不是为加载视频缩略图设计的,得用专门的配置。
针对Glide的正确加载写法(推荐用Glide 4.x)
Glide本身支持加载视频帧作为缩略图,只要用asBitmap()配合frame()指定取哪一帧:
// 假设你在RecyclerView的Adapter里加载缩略图 Glide.with(holder.itemView.getContext()) .asBitmap() // 这里可以传File、Uri或者视频路径字符串 .load(Uri.fromFile(new File(tutorial.getVideoPath()))) .apply(new RequestOptions() .frame(1000) // 取视频第1秒的帧(单位毫秒) .centerCrop() .placeholder(R.drawable.default_thumbnail) // 加载失败时显示占位图 .error(R.drawable.error_thumbnail)) .into(holder.thumbnailImageView);
如果是Glide 3.x,写法略有不同:
Glide.with(context) .load(videoUri) .asBitmap() .thumbnail(0.1f) .into(imageView);
针对Picasso的解决方案
Picasso默认不支持视频缩略图,得自定义RequestHandler来调用系统的缩略图生成API:
第一步:自定义RequestHandler
public class VideoThumbnailHandler extends RequestHandler { @Override public boolean canHandleRequest(Request data) { // 只处理本地文件Uri return "file".equals(data.uri.getScheme()); } @Override public Result load(Request data, int networkPolicy) throws IOException { // 调用系统工具生成缩略图 Bitmap thumbnail = ThumbnailUtils.createVideoThumbnail( data.uri.getPath(), MediaStore.Images.Thumbnails.MINI_KIND); if (thumbnail == null) { throw new IOException("无法生成视频缩略图,检查文件是否损坏或路径是否正确"); } return new Result(thumbnail, LoadedFrom.DISK); } }
第二步:初始化Picasso时添加Handler
在你的Application类里(或者Activity初始化时):
Picasso picasso = new Picasso.Builder(getApplicationContext()) .addRequestHandler(new VideoThumbnailHandler()) .build(); Picasso.setSingletonInstance(picasso);
第三步:加载缩略图
Picasso.get() .load(Uri.fromFile(new File(tutorial.getVideoPath()))) .placeholder(R.drawable.default_thumbnail) .error(R.drawable.error_thumbnail) .into(holder.thumbnailImageView);
额外的排查步骤
- 先验证系统能否生成缩略图:直接用系统工具测试,排除视频文件本身的问题:
Bitmap testBitmap = ThumbnailUtils.createVideoThumbnail( yourVideoPath, MediaStore.Images.Thumbnails.FULL_SCREEN_KIND); if (testBitmap == null) { // 要么视频文件损坏,要么路径完全错误,先解决这个问题 }
- 动态权限申请:别忘了在Activity里处理权限请求:
private static final int REQ_STORAGE_PERM = 1001; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 检查权限 if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQ_STORAGE_PERM); } else { // 权限已获取,加载视频列表 loadVideoList(); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == REQ_STORAGE_PERM) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { loadVideoList(); } else { Toast.makeText(this, "需要存储权限才能加载视频缩略图", Toast.LENGTH_SHORT).show(); } } }
结合你的CCVideoActivity代码的建议
从你的代码片段看,你在CCVideoActivity里有RecyclerView展示视频列表,记得在Adapter里加载缩略图时:
- 用
ViewHolder.itemView.getContext()作为Glide/Picasso的上下文,避免内存泄漏 - 确保
tutorial对象里的视频路径是正确的(可以打Log输出路径,验证文件是否存在)
内容的提问来源于stack exchange,提问作者bambang office
相关产品推荐
相关产品推荐

