uniapp_04_获取缩略图的几种方法
关于 uniapp 获取缩略图
- 前言
- 获取图片缩略图
- 获取视频缩略图
- 参考文档
前言
项目中实现的一个文件管理功能,视频原本是列表的方式展示, 后来就在想是否可以让视频向图片一样排列显示一个缩略图而不是名称列表。
Android中,视频和图片都是有缩略图的我们可以直接获取
获取图片缩略图
获取图片的缩略图,我想到的方式有两种,
第二种方式与下面视频缩略图获取基本相同所以在此不做过多描述
- 压缩图片
利用BitmapFactory中的decodeFile对图片进行压缩
- 从媒体数据库查询
android.provider.MediaStore.Images.Thumbnails
获取视频缩略图
-
ThumbnailUtils
ThumbnailUtils 是安卓2.2添加的方法, 三个静态方法
createVideoThumbnail(path, kind) 创建视频缩略图
extractThumbnail(bitmap, width, height) 将bitmap裁剪为指定的大小
extractThumbnail(bitmap, width, height, options) 将bitmap裁剪为指定的大小
注:
path 是文件路径
options: ThumbnailUtils.OPTIONS_RECYCLE_INPUT等
kind: MediaStore.Images.Thumbnails.* | MediaStore.Video.Thumbnails.*MICRO_KIND 96 * 96的缩略图
MINI_KIND:512*384的缩略图、
FULL_SCREEN_KIND:完整大小的图片
const MediaStore = plus.android.importClass('android.provider.MediaStore');
const ThumbnailUtils = plus.android.importClass('android.media.ThumbnailUtils');
const filePath = "/storage/emulated/0/Movies/QQ视频_2fac0bc06be7d09476f952d4d259ae471641725653.mp4";
let bitmap = ThumbnailUtils.createVideoThumbnail(filePath, MediaStore.Video.Thumbnails.MINI_KIND);
bitmap = ThumbnailUtils.extractThumbnail(bitmap, 90, 90, ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
plus.android.invoke(bitmap, "recycle")
-
MediaMetadataRetriever
/**
* @method getVideoThumbnail
* @description 获取视频的缩略图
* */
getVideoThumbnail: function(path) {
// 必须要先获取到存储权限才能使用
const Main = plus.android.runtimeMainActivity(); // 此处相当于 context
const Build = plus.android.importClass('android.os.Build');
const MediaMetadataRetriever = plus.android.importClass("android.media.MediaMetadataRetriever");
const retriever = new MediaMetadataRetriever();
const hashMap = plus.android.importClass("java.util.HashMap");
const Url = plus.android.importClass("android.net.Uri");
const File = plus.android.importClass("java.io.File"); // 导入包并new这个类
const FileProvider = plus.android.importClass("android.support.v4.content.FileProvider");
const filePath = "/storage/emulated/0/Movies/QQ视频_2fac0bc06be7d09476f952d4d259ae471641725653.mp4"
// 判断是否是本地文件 ? 根据文件路径获取缩略图 : 根据网络路径获取缩略图
// 判断是否是网络资源
// const isValidUrl = (string) => {
// try {
// new URL(string);
// return true;
// } catch (_) {
// return false;
// }
// }
const reg = /^https?/ig;
if(reg.test(filePath)){
plus.android.invoke(retriever, 'setMode', MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY)
// retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY);
// retriever.setDataSource(Main, Url.fromFile(new File(filePath)));
retriever.setDataSource(filePath);
// if(Build.VERSION.SDK_INT >= 24) {
// retriever.setDataSource( Main, FileProvider.getUriForFile( this, "uni.UNICB2E32F.provider", new File(filePath)));
// } else {
// retriever.setDataSource(Main, Url.fromFile(new File(filePath)))
// }
} else {
retriever.setDataSource("视频链接",new hashMap());
}
// const bim = retriever.captureFrame();
const bim = retriever.getFrameAtTime(parseInt(0));// 获取 第一帧 0 表示首帧图片
// bim.recycle();
console.log(plus.android.invoke(bim, "getByteCount")/1024);
// retriever.getScaledFrameAtTime(-1, OPTION_CLOSEST_SYNC,512,512); // 指定缩略图大小 512 * 512
// retriever.getFrameAtTime() // 正常
// retriever.getFrameAtTime( parseInt(1), MediaMetadataRetriever.OPTION_CLOSEST_SYNC)
// retriever.frameAtTime // 报 undefind
// console.log();
// let u = retriever.getFrameAtTime(-1)
// let u = retriever.getScaledFrameAtTime(-1 , MediaMetadataRetriever.OPTION_CLOSEST_SYNC, 100 , 100)
// console.log(Bytes);
plus.android.invoke(bim, "recycle")
retriever.release()
},
-
Thumbnails
android.provider.MediaStore.Images.Thumbnails 和 android.provider.MediaStore.Video.Thumbnails
在安卓 29 MediaStore.Video.Thumbnails 已经被改成了 ContentResolver#loadThumbnail
-
写法一 getThumbnail()
// 使用 MediaStore.Video.Thumbnails.getThumbnail() 图片的话和这个差不多 将id换成需要的图片id将video 换成 image
const Main = plus.android.runtimeMainActivity(); // 此处相当于 context
const MediaStore = plus.android.importClass('android.provider.MediaStore');
const media_id = '24571'
const resolver = Main.getContentResolver();
const bitmap = MediaStore.Video.Thumbnails.getThumbnail(resolver, Number(media_id), MediaStore.Video.Thumbnails.MINI_KIND, null);
-
写法二 查询数据库
const MediaStore = plus.android.importClass('android.provider.MediaStore');
const thumbColumns = [
MediaStore.Video.Thumbnails.DATA,
MediaStore.Video.Thumbnails.VIDEO_ID
];
const Resolver = Main.getContentResolver(); // 获取ContentResolver实例
plus.android.importClass(Resolver);
// MediaStore.Video.Thumbnails.VIDEO_ID + "=" + '24571' 后面这个 24571是视频的id 而且查询缩略图必须要有条件 不然返回的是null
const cursor = Resolver.query(MediaStore.Video.Thumbnails.EXTERNAL_CONTENT_URI, thumbColumns, MediaStore.Video.Thumbnails.VIDEO_ID + "=" + '24571', null, null);
plus.android.importClass(cursor);
// 此处使用 do {} while() 的原因是 cursor !=null && cursor.moveToNext() 单独输出都是true 取且之后确实 false
do {
const _id = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Thumbnails.VIDEO_ID));
const fileParh = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Thumbnails.DATA));
} while(cursor !=null && cursor.moveToNext())
cursor.close(); // 关闭游标
-
解决新视频或图片缩略图为 null
const Main = plus.android.runtimeMainActivity(); // 此处相当于 context
const Intent = plus.android.importClass("android.content.Intent"); // 导入 Intent
const mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
const File = plus.android.importClass("java.io.File"); // 导入包并new这个类
const FileProvider = plus.android.importClass("android.support.v4.content.FileProvider");
const filePath = ""
const contentUri = FileProvider.getUriForFile( this, "uni.UNICB2E32F.provider", new File(filePath))
plus.android.invoke(mediaScanIntent , 'setData', contentUri);
plus.android.invoke(Main , 'sendBroadcast', mediaScanIntent);