更新记录
1.0.0(2026-08-22) 下载此版本
1.0.0
标识
- 插件公开 ID 为
dyl-media-picker - UTS 导入路径为
@/uni_modules/dyl-media-picker
新增
- Android/iOS 原生全屏媒体选择器
- 支持图片、视频及混合选择
- "全部 / 图片 / 视频" 筛选 Tab
- 四列网格分页加载(每页 60 条)
- 选择顺序编号和取消重排
- 图片缩放和视频播放预览
- 视频时长和文件大小限制校验
- 原文件流式导出到应用缓存
- 准备进度显示和取消/重试
- Android 版本适配(API 21–34+)
- iOS PhotoKit/iCloud 支持
- 24 小时自动缓存清理
clearMediaPickerCacheAPI- 完整错误码体系(9201001–9201008)
平台兼容性
uni-app x(4.76)
| Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|
| - | - | 13.0 | 12 | - | - |
dyl-media-picker
面向 uni-app x 的 Android / iOS 原生全屏图片、视频选择器。
通过一次 API 调用打开原生媒体选择界面,支持图片、视频或混合选择,并提供分类筛选、分页加载、全屏预览、数量与文件限制、原文件导出和缓存清理能力。
功能特性
- 图片、视频单选或混合多选,最多可选 99 个文件
- 全部、图片、视频三个分类 Tab,支持指定初始 Tab
- 按选择顺序编号,确认后按选择顺序返回结果
- 支持视频时长、文件大小和选择数量限制
- 图片缩放预览、视频播放和暂停控制
- iOS 预览采用相邻页面缓存、缩略图到高清图渐进加载和 PhotoKit 预热,降低快速滑动时的白屏、黑屏概率
- 视频预览使用封面占位,媒体内容在可用区域内居中;Android 暂停时保留控制栏,iOS 使用系统播放器控制栏
- 支持 iCloud 媒体下载和原文件导出进度提示
- 结果统一导出为本地绝对路径,不向业务层暴露
content://或ph://地址 - 自动清理过期缓存,也支持业务层主动清理
平台与环境
| 项目 | 支持范围 |
|---|---|
| 应用框架 | 仅 uni-app x App |
| HBuilderX | 4.76 及以上 |
| Android | Android 5.0 / API 21 及以上 |
| iOS | iOS 12.0 及以上 |
插件直接弹出原生页面,不需要在 pages.json 中注册插件页面。
如果同一个业务页面还需要编译到 Web 或小程序,请使用条件编译,只在 App 端导入和调用本插件。
接入与自定义基座
本插件包含 Kotlin、Swift、原生依赖、系统 Framework 和权限配置。以下情况需要重新制作自定义调试基座:
- 首次将
dyl-media-picker加入项目 - 修改了
utssdk/app-android或utssdk/app-ios下的代码或配置 - 升级插件后,新版本包含原生实现或原生依赖变更
- 调整了 Android 权限、目标 SDK,或 iOS
Info.plist、Framework 配置
只修改业务页面中的调用参数、回调处理或界面逻辑,不需要因为这些改动重新制作基座。
Android 和 iOS 基座需要分别构建。调试时请确认运行的是包含当前插件版本的最新基座;旧基座不会动态获得新加入的原生代码。
如果项目曾使用旧目录 jx-media-picker,请直接替换为 dyl-media-picker,不要同时保留两份插件;同时更新所有 import 后重新制作自定义基座。新版本使用独立的 dyl-media-picker 缓存目录,旧缓存由系统缓存策略回收,也可以在升级前主动清理。
快速开始
import {
chooseMedia,
type ChooseMediaResult,
type ChooseMediaFail
} from '@/uni_modules/dyl-media-picker'
const openMediaPicker = () : void => {
chooseMedia({
count: 9,
mediaType: ['image', 'video'],
initialTab: 'all',
success: (result : ChooseMediaResult) : void => {
console.log('已选择:', result.tempFiles.length)
if (result.tempFiles.length > 0) {
const firstFile = result.tempFiles[0]
console.log(firstFile.tempFilePath)
}
},
fail: (error : ChooseMediaFail) : void => {
console.log(error.errCode, error.errMsg)
},
complete: () : void => {
console.log('选择流程结束')
}
})
}
chooseMedia 使用回调 API,不返回 Promise:
- 选择并成功导出全部文件时调用
success - 用户返回或主动取消时调用
fail,错误码为9201006 - 其他权限、参数、初始化或导出错误也调用
fail - 无论成功或失败,最后都只调用一次
complete success与fail互斥,不会在同一次调用中同时触发
常用配置
只选择图片
chooseMedia({
count: 9,
mediaType: ['image'],
initialTab: 'image',
success: (result) : void => {
console.log(result.tempFiles)
}
})
只选择视频
chooseMedia({
count: 1,
mediaType: ['video'],
initialTab: 'video',
maxVideoDuration: 60,
maxFileSize: 200 * 1024 * 1024,
success: (result) : void => {
console.log(result.tempFiles)
}
})
图片和视频混选
chooseMedia({
count: 9,
mediaType: ['image', 'video'],
initialTab: 'all',
title: '选择素材',
accentColor: '#00C853',
success: (result) : void => {
console.log(result.tempFiles)
}
})
API
chooseMedia(options)
打开原生媒体选择器。同一时间只允许存在一个选择器实例,重复调用会返回 9201002。
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
count |
number |
9 |
最大选择数量,必须是 1–99 的整数 |
mediaType |
MediaPickerMediaType[] |
['image', 'video'] |
可选择的媒体类型,数组不得为空 |
initialTab |
MediaPickerTab |
'all' |
初始 Tab:'all'、'image' 或 'video' |
maxVideoDuration |
number |
0 |
视频最大时长,单位为秒;0 表示不限制,必须是非负整数 |
maxFileSize |
number |
0 |
单个文件最大大小,单位为字节;0 表示不限制,必须是非负整数 |
title |
string |
'相册' |
原生选择页标题 |
accentColor |
string |
'#00C853' |
主题色,支持 #RRGGBB 或 #AARRGGBB |
success |
(result: ChooseMediaResult) => void |
- | 文件全部导出成功回调 |
fail |
(error: ChooseMediaFail) => void |
- | 取消或失败回调 |
complete |
() => void |
- | 流程结束回调 |
MediaPickerMediaType 可取:
type MediaPickerMediaType = 'image' | 'video'
MediaPickerTab 可取:
type MediaPickerTab = 'all' | 'image' | 'video'
如果 initialTab 与 mediaType 冲突,插件会回退到当前允许的媒体分类。例如只允许视频时,初始页最终会使用视频分类。
ChooseMediaResult
type ChooseMediaResult = {
tempFiles: MediaPickerFile[]
}
结果数组保持用户的选择顺序。确认后插件先将选中的系统资源导出到插件缓存,全部成功后再一次性返回。
MediaPickerFile
| 字段 | 类型 | 说明 |
|---|---|---|
identifier |
string |
系统媒体资源标识,用于插件内部定位和去重;受平台权限与资源生命周期约束,不应作为文件地址使用 |
type |
'image' \| 'video' |
媒体类型 |
tempFilePath |
string |
导出的原文件本地绝对路径 |
thumbnailPath |
string |
导出的缩略图本地绝对路径 |
name |
string |
原始文件名 |
mimeType |
string |
MIME 类型 |
size |
number |
原文件大小,单位为字节 |
width |
number |
媒体宽度,单位为像素 |
height |
number |
媒体高度,单位为像素 |
duration |
number |
视频时长,单位为秒;图片固定为 0 |
createTime |
number |
媒体创建时间,毫秒时间戳 |
tempFilePath 和 thumbnailPath 是普通本地绝对路径,可用于文件读取、上传和后续原生处理。它们属于插件缓存文件,不是永久文件。
ChooseMediaFail
interface ChooseMediaFail extends IUniError {
errCode: MediaPickerErrorCode
identifier: string | null
}
当某个具体媒体导出失败时,identifier 可能携带对应资源标识;没有明确资源时为 null。
clearMediaPickerCache(options)
清理插件缓存目录中超过 24 小时的旧会话。
import {
clearMediaPickerCache,
type ClearMediaPickerCacheResult,
type ChooseMediaFail
} from '@/uni_modules/dyl-media-picker'
const clearPickerCache = () : void => {
clearMediaPickerCache({
success: (result : ClearMediaPickerCacheResult) : void => {
console.log('删除文件数:', result.removedFileCount)
console.log('释放字节数:', result.freedSize)
},
fail: (error : ChooseMediaFail) : void => {
console.log(error.errCode, error.errMsg)
}
})
}
| 返回字段 | 类型 | 说明 |
|---|---|---|
removedFileCount |
number |
本次删除的文件数量 |
freedSize |
number |
本次释放的空间,单位为字节 |
选择器打开期间不要清理缓存;此时清理请求会失败并返回 9201008。
预览与导出行为
图片预览
- 支持全屏查看和缩放
- iOS 优先显示可用缩略图,再渐进加载高清图
- 当前页和相邻页会被缓存与预热,快速左右滑动时不必每次重新创建全部媒体视图
- 系统内存紧张时可能主动回收非当前页缓存,插件会在再次进入该页时重新加载
视频预览
- 使用视频封面作为播放器准备完成前的占位内容
- 媒体按比例在预览区域内居中显示
- Android 暂停时控制栏保持可见,便于继续播放或拖动进度
- iOS 使用
AVPlayerViewController的系统播放控制栏 - 离开当前预览页时会暂停视频,避免多个视频同时播放
iCloud 媒体
iOS 素材只存在于 iCloud 时,高清预览或确认导出需要联网下载。下载期间可能先显示缩略图或视频封面;网络速度会直接影响高清内容和播放器的就绪时间。
maxFileSize 在系统能提前获取文件大小时会在选择阶段校验。对于 iCloud 等大小暂不可知的资源,最终以导出阶段的校验结果为准。
权限说明
Android
- API 21–22:无需运行时授权
- API 23–32:运行时申请
READ_EXTERNAL_STORAGE - API 33+:根据
mediaType申请READ_MEDIA_IMAGES、READ_MEDIA_VIDEO - API 34+:支持
READ_MEDIA_VISUAL_USER_SELECTED部分媒体访问 - 要完整使用 Android 14 部分媒体访问,宿主
targetSdkVersion应不低于 34 - 插件不会覆盖宿主工程的目标 SDK 配置
用户拒绝权限或当前授权状态不可用时,插件返回 9201003。
iOS
- 使用 PhotoKit 读取系统相册
- iOS 14+ 支持 limited Photos 权限,并只展示当前被授权的素材
- 插件声明
NSPhotoLibraryUsageDescription,宿主可以根据产品文案覆盖该字段 - 原生配置依赖
Photos、PhotosUI、UIKit、AVFoundation和AVKit等系统 Framework
权限或 Framework 配置发生变化后,需要重新制作 iOS 自定义基座。
缓存生命周期
- 导出目录:
<application-cache>/dyl-media-picker/<session-id>/ - 每次打开选择器时自动删除超过 24 小时的旧会话
- 调用
clearMediaPickerCache时同样只清理超过 24 小时的旧会话 - 操作系统仍可能因空间压力提前回收缓存
- 需要长期保留的文件,应在成功回调中尽快上传或复制到业务持久目录
- 不要把缓存路径长期写入数据库后直接复用
错误码
| 错误码 | 含义 | 常见原因 |
|---|---|---|
9201001 |
参数不合法 | 数量越界、媒体类型为空、颜色格式错误或限制值不是非负整数 |
9201002 |
选择器已打开 | 上一次选择流程尚未结束,又调用了 chooseMedia |
9201003 |
相册权限不足 | 用户拒绝权限,或当前授权状态不可用 |
9201004 |
选择器初始化失败 | 原生页面、数据源或宿主环境初始化异常 |
9201005 |
原文件导出失败 | 系统资源已删除、iCloud 下载失败或文件复制失败 |
9201006 |
用户取消选择 | 用户从选择器主界面返回或关闭选择器 |
9201007 |
缓存空间不足 | 导出目录无法创建、写入或设备可用空间不足 |
9201008 |
缓存清理失败 | 选择器正在使用缓存,或目录删除失败 |
业务层通常应将 9201006 作为正常取消处理,不必展示错误提示。
常见问题
加入插件后运行没有效果,或提示找不到原生类
当前运行的自定义基座没有包含插件。重新制作对应平台的自定义基座,并确认设备安装的是新基座。
iOS 云打包能通过,但旧基座仍然表现为修改前的版本
UTS 原生插件代码会编译进基座。仅替换业务资源不会更新 Swift 实现,需要重新制作并安装 iOS 基座。
Android 14 只能看到部分照片
这是系统的部分媒体授权行为。确认宿主目标 SDK 不低于 34,并在授权流程中处理 READ_MEDIA_VISUAL_USER_SELECTED。
iOS 预览 iCloud 视频时短暂显示封面
播放器需要等待系统返回可播放的 AVAsset。插件会保留视频封面,资源下载完成后再切换到播放器;请确认设备网络可用。
成功回调中的路径过一段时间失效
返回的是插件缓存路径。需要持久保存时,请在成功回调后立即复制到业务目录或完成上传。
如何避免数组越界
UTS 在 Android 和 iOS 原生端访问越界数组会抛出异常。读取 tempFiles[index] 前应显式检查:
if (index >= 0 && index < result.tempFiles.length) {
const file = result.tempFiles[index]
console.log(file.tempFilePath)
}
调试与验收
当前项目提供了调用示例页面:媒体选择器调试页。
完整的自动检查、真机测试矩阵和发布前清单见:TESTING.md。
建议至少在以下场景进行真机回归:
- 首次授权、拒绝后重试、iOS limited Photos、Android 14 部分媒体权限
- 图片、视频、混合选择,以及数量、时长、大小限制
- 连续快速左右滑动图片和视频,并多次滑回同一素材
- 从预览页返回列表,确认列表位置、选中状态和缩略图不闪烁
- iCloud 原图和视频的弱网下载、取消与失败
- 导出大文件时的进度、空间不足和缓存清理
从 uni.chooseMedia 迁移
// 旧代码
uni.chooseMedia({
count: 9,
mediaType: ['image', 'video'],
success: (result) : void => {
console.log(result.tempFiles)
}
})
// 新代码
import { chooseMedia } from '@/uni_modules/dyl-media-picker'
chooseMedia({
count: 9,
mediaType: ['image', 'video'],
success: (result) : void => {
// 返回原文件、缩略图、尺寸、时长、MIME 和创建时间等完整信息
console.log(result.tempFiles)
}
})
迁移后需要注意:
- 本插件只支持 uni-app x App
- 首次接入必须重新制作 Android / iOS 自定义基座
- 用户取消会进入
fail,错误码为9201006 - 返回路径位于插件缓存,长期使用前需要持久化
- iCloud 素材可能在确认后继续下载和导出

收藏人数:
下载插件并导入HBuilderX
赞赏(0)
下载 96
赞赏 0
下载 12525536
赞赏 1944
赞赏
京公网安备:11010802035340号