更新记录
1.0.23(2026-09-17)
- 修复 Android 部分系统上,接入插件后 App 内嵌 H5 调用
uni.chooseImage或文件选择控件无法打开选图界面的问题。 - 无需修改项目配置或调用代码;需要重新制作并安装 Android 自定义基座,正式包也需要重新打包。仅更新页面资源无法生效,iOS 和 HarmonyOS 不受影响。
1.0.22(2026-09-14)
- 修复 iOS 使用列表渐进缩略图时云打包可能编译失败的问题;现有 API、参数和调用无需调整。
- 本次仅影响 iOS;升级后需重新制作并安装 iOS 自定义基座或重新打包,Android、HarmonyOS 无需重新制作。
1.0.21(2026-09-11)
- 修复 iOS 大图库媒体列表在分页前处理全部缩略图导致首屏等待较长的问题;现在先完成媒体分页,再按当前页生成缩略图。
- 现有 API、参数、调用方式和 Android、HarmonyOS 行为无需调整。
- 本次包含 iOS 原生代码变更,升级后需要重新制作并安装 iOS 自定义基座或正式包;仅更新页面资源或 WGT 无法生效。
平台兼容性
uni-app(5.07)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| √ | √ | × | × | √ | √ | 6.0 | √ | √ |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| × | × | × | × | × | × | × | × | × | × | × | × |
uni-app x(5.07)
| Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|
| × | × | 6.0 | √ | √ | × |
lizhao-gallery-pro
lizhao-gallery-pro 是面向 uni-app / uni-app x 的系统相册媒体插件。取得用户授权后,应用可以直接读取图片和视频,并完成分页筛选、缩略图展示、临时文件导出、上传、保存到系统相册、元数据读取和相册变化监听。
这个插件能解决什么问题
- 不弹系统选择器,直接构建自己的图片、视频或混合素材列表。
- 分页读取大图库,并按时间、相册和来源筛选媒体。
- 为九宫格、瀑布流和素材管理页生成缩略图。
- 将系统媒体导出为页面可预览、接口可上传的临时文件。
- 批量上传相册媒体,或把业务生成的图片和视频保存到系统相册。
- 按相机、截图、微信、QQ、下载等来源组织素材。
- 读取图片 EXIF、视频参数,以及由业务显式开启的位置元数据。
- 监听相册变化,或使用持久化游标完成增量备份和同步。
适合社区发帖、评价晒单、工单上报、素材管理、云盘备份、自定义相册选择器和内容审核等业务。
本插件读取的是系统相册中当前应用有权访问的媒体,不会绕过系统权限。Web/H5 和小程序不能使用 App 端的系统相册整库读取能力。
支持平台
| 平台 | 图片/视频读取 | 缩略图与导出 | 保存与监听 | 是否需要自定义基座 | 说明 |
|---|---|---|---|---|---|
| App Android | 支持 | 支持 | 支持 | 需要 | Android 13+ 按图片、视频分别授权;Android 12 及以下使用存储读取权限。 |
| App iOS | 支持 | 支持 | 支持 | 需要 | 使用 PhotoKit;有限照片权限下只返回用户允许访问的媒体。 |
| App HarmonyOS | 条件支持 | 条件支持 | 条件支持 | 需要 | 完整相册访问需要应用通过 AppGallery Connect(AGC)受限权限审核、取得对应 ACL、声明权限并完成用户授权。 |
| Web/H5 | 不支持 | 不支持 | 不支持 | 不需要 | API 明确返回不支持,不伪造成功。 |
| 微信/支付宝小程序 | 不支持 | 不支持 | 不支持 | 不需要 | 小程序应使用平台自己的媒体选择 API。 |
uni-app 与 uni-app x 使用同一套公开方法。平台能力应以本表和 getGalleryCapabilities() 的运行结果为准。
先选择接入方式
| 你的需求 | 推荐方法 | 下一步 |
|---|---|---|
| 只读取图片 | getGalleryImages |
用 nextPageToken 分页 |
| 只读取视频 | getGalleryVideos |
根据 durationMs 展示时长 |
| 图片和视频混合展示 | getGalleryMedia |
根据 mediaType 区分样式 |
| 做自己的素材选择器 | 列表使用渐进缩略图 | 选中后调用 prepareGalleryMedia |
| 上传相册中的媒体 | uploadGalleryMedia |
监听 progress 和逐项结果 |
| 保存业务生成的文件 | saveMediaToGallery |
选择目标相册和重复策略 |
| 做相册入口或来源分类 | getGalleryAlbums + 查询过滤 |
使用返回的 albumId 或 sourceType |
| 读取拍摄和视频参数 | getGalleryMetadata |
默认不读取位置 |
| 相册变化后刷新页面 | startGalleryChangeObserver |
页面卸载时停止监听 |
| 做增量备份或同步 | getGalleryChanges |
业务处理成功后保存 nextCursor |
第一次接入建议从模块一开始;已经有媒体 ID 时,可以直接查看缩略图、导出、上传或元数据模块。
下载与导入
- 从 DCloud 插件市场导入插件。
- App 端使用包含本插件原生代码和权限配置的自定义基座或正式安装包。
- 页面只能从插件根目录导入,不要直接导入
utssdk子目录。
uni-app 导入
import * as GalleryPro from '@/uni_modules/lizhao-gallery-pro'
uni-app x 导入
import * as GalleryPro from '@/uni_modules/lizhao-gallery-pro'
下面以普通 uni-app 写法说明业务流程;uni-app x 使用同名 API,完整强类型页面见文末示例路径。
按业务模块使用
模块一:申请权限并读取第一批图片和视频
适合第一次接入。流程是先检查权限,未授权时再请求,授权成功后读取第一批媒体。
import * as GalleryPro from '@/uni_modules/lizhao-gallery-pro'
function loadFirstPage() {
GalleryPro.getGalleryMedia({
mediaType: 'all',
pageSize: 30,
thumbnailMode: 'progressive',
thumbnailBatchSize: 4,
success(res) {
// 先显示当前页名称、类型和尺寸等信息。
console.log('首批媒体', res.items)
console.log('是否还有下一页', res.hasMore, res.nextPageToken)
},
thumbnailProgress(event) {
// 每批只更新 event.items 对应的列表项。
console.log('缩略图进度', event.current, event.total, event.items)
},
fail(err) {
console.log('读取相册失败', err.errCode, err.errMsg)
}
})
}
GalleryPro.checkGalleryPermission({
mediaType: 'all',
success(permission) {
if (permission.granted) {
loadFirstPage()
return
}
GalleryPro.requestGalleryPermission({
mediaType: 'all',
preferFullAccess: true,
success(result) {
if (result.granted) {
loadFirstPage()
} else if (result.shouldOpenSettings) {
console.log('请引导用户到系统设置中开启相册权限')
}
},
fail(err) {
console.log('请求相册权限失败', err.errCode, err.errMsg)
}
})
},
fail(err) {
console.log('检查相册权限失败', err.errCode, err.errMsg)
}
})
success 表示权限检查或请求动作正常完成,是否真正获得权限仍要读取 granted 和 status。不要把权限受限当成空相册。列表使用 thumbnailMode: 'progressive' 时,success 先返回当前页基础数据,thumbnailProgress 再分批补充缩略图,complete 在当前页缩略图处理结束后触发。
模块二:分页读取并筛选需要的媒体
适合素材库、相册备份和媒体管理。getGalleryImages、getGalleryVideos 与 getGalleryMedia 使用同一套分页和筛选参数。
getGalleryMedia 用于图片视频混合列表;需要全量读取时,必须根据 hasMore 和 nextPageToken 循环读取下一页,不能用超大 pageSize 代替分页。
let nextPageToken = ''
let mediaItems = []
function loadNextPage() {
GalleryPro.getGalleryMedia({
mediaType: 'all',
pageSize: 30,
pageToken: nextPageToken,
// 示例:只看最近 7 天、来自相机或系统识别为 camera 的媒体。
startTime: Date.now() - 7 * 24 * 60 * 60 * 1000,
sourceType: 'camera',
sortOrder: 'desc',
success(res) {
mediaItems = mediaItems.concat(res.items)
nextPageToken = res.nextPageToken
console.log('已加载/总数', mediaItems.length, res.total)
},
fail(err) {
console.log('分页读取失败', err.errCode, err.errMsg)
}
})
}
只读取图片时改用 getGalleryImages,只读取视频时改用 getGalleryVideos。如果已经从相册分组取得 albumId,可以把它传给查询方法,只读取该相册。
不要自行修改 nextPageToken,也不要用超大的 pageSize 一次加载整个图库。筛选条件变化时应清空旧令牌并从第一页重新查询。
获取全部可访问图片,并筛选 2:1 全景图
“全部图片”是指当前应用在系统授权范围内能够访问的全部图片。必须持续请求下一页,直到 hasMore 为 false;iOS 有限照片权限等场景只会返回用户允许访问的图片。
2:1 表示图片的宽高比,不是 JPG、PNG 这类文件格式。查询结果包含 width、height 和 mimeType,可以先分页读取,再按宽高比筛选。考虑到裁剪、拼接和编码可能产生少量像素偏差,普通业务建议使用 1.95 ~ 2.05 的容差范围:
let panoramaImages = []
function loadAllPanoramaImages(pageToken = '') {
GalleryPro.getGalleryImages({
pageSize: 100,
pageToken,
sortOrder: 'desc',
success(res) {
const currentPage = res.items.filter((item) => {
if (item.width <= 0 || item.height <= 0) {
return false
}
const aspectRatio = item.width / item.height
return aspectRatio >= 1.95 && aspectRatio <= 2.05
})
panoramaImages = panoramaImages.concat(currentPage)
if (res.hasMore && res.nextPageToken !== '') {
loadAllPanoramaImages(res.nextPageToken)
return
}
console.log('2:1 全景图片读取完成', panoramaImages.length, panoramaImages)
},
fail(err) {
console.log('读取全景图片失败', err.errCode, err.errMsg)
}
})
}
// 每次重新筛选前清空旧结果,并从第一页开始。
panoramaImages = []
loadAllPanoramaImages()
如果业务要求像素必须严格等于 2:1,可把判断改为 item.width === item.height * 2。如果还要限制文件编码格式,可同时判断 item.mimeType,例如只保留 image/jpeg。仅凭 2:1 尺寸不能判断图片是否带有完整的 360° 全景元数据;需要识别可交互全景图时,还应在导出文件后检查对应的全景元数据。
模块三:渐进显示缩略图并一次准备可用文件
相册返回的 id 是后续操作的稳定入口。推荐让列表先显示基础信息并渐进补缩略图;用户真正选中某一项后,再一次准备预览、上传和视频 poster 路径。
路径用途保持固定:renderPath 用于页面显示,uploadPath 用于上传,不要在页面层自行转换系统资产标识。
getGalleryImages不会修改或压缩系统相册中的原文件。启用缩略图后,插件会另外生成经过缩放和 JPEG 编码的缓存文件;thumbnailPath只适合列表小图,不要直接放大作为详情页或全屏预览。大图、视频和上传请使用prepareGalleryMedia的结果。
const selectedId = '从列表结果取得的媒体ID'
GalleryPro.prepareGalleryMedia({
id: selectedId,
posterWidth: 640,
posterHeight: 360,
success(res) {
// image/video 的 src 使用 renderPath。
console.log('预览路径', res.renderPath)
// uni.uploadFile 使用 uploadPath。
console.log('上传路径', res.uploadPath)
// video 的 poster 或列表封面使用 posterPath。
console.log('视频首帧', res.posterPath)
console.log('是否复用已有导出', res.cacheHit)
},
fail(err) {
console.log('准备媒体失败', err.errCode, err.errMsg)
}
})
视频组件直接绑定 <video :src="prepared.renderPath" :poster="prepared.posterPath" />。posterPath 是 JPEG 缓存路径;图片也会返回可用于占位展示的缩略图路径。仅上传、不需要 poster 时可传 includePoster: false。
同一媒体未变化时,再次调用会复用已有导出并返回 cacheHit: true,预览后上传不需要重复复制。旧的 getGalleryThumbnails、getMediaById 和 exportMediaToTempFile 继续可用;用户删除媒体、撤销权限或云端原图尚未下载时,准备或导出仍可能失败。
模块四:上传媒体或批量保存到系统相册
uploadGalleryMedia 用于把已存在于系统相册的媒体上传到业务服务器。先用 dryRun: true 可以只验证导出链路,不发起网络请求。
调试时也可以记为 dryRun=true;批量结果顺序与 options.ids 一致,仍需检查每一项的 success。
GalleryPro.uploadGalleryMedia({
ids: ['media-id-1', 'media-id-2'],
url: 'https://example.com/upload',
name: 'file',
formData: { scene: 'feedback' },
concurrency: 2,
retryCount: 1,
progress(event) {
console.log('上传进度', event.current, event.total, event.progress)
},
success(res) {
console.log('上传成功/失败', res.successCount, res.failCount)
console.log('逐项结果', res.items)
},
fail(err) {
console.log('上传任务无法完成', err.errCode, err.errMsg)
}
})
saveMediaToGallery 用于把业务生成、下载或插件导出的本地文件保存到系统相册。
GalleryPro.saveMediaToGallery({
paths: [
'/本地可访问路径/report-photo.jpg',
'/本地可访问路径/report-video.mp4'
],
albumName: '工单附件',
duplicatePolicy: 'skip',
progress(event) {
console.log('保存进度', event.current, event.total, event.progress)
},
success(res) {
console.log('保存/跳过/失败', res.successCount, res.skippedCount, res.failCount)
},
fail(err) {
console.log('保存到相册失败', err.errCode, err.errMsg)
}
})
上传结果和保存结果都按输入顺序返回。duplicatePolicy: 'skip' 只跳过系统当前可见范围内能够确认的重复项,不应把它当作跨设备文件去重方案;需要保留每次保存结果时使用 duplicatePolicy: 'allow'。
模块五:按相册和来源组织素材
适合相册入口、文件夹侧栏、来源筛选和素材分类页。getGalleryAlbums 默认使用快速模式:先返回相册名称、数量和最新媒体信息,不在返回前生成封面,因此大图库不会因为缩略图处理而延迟显示整个文件夹列表。常见来源包括相机、截图、微信、QQ、下载,例如截图筛选可传 sourceType='screenshot'。
第一步:快速显示文件夹列表
GalleryPro.getGalleryAlbums({
mediaType: 'all',
sourceType: 'all',
// 可以省略,默认就是 false。
includeCoverThumbnail: false,
success(res) {
console.log('先显示这些文件夹', res.albums)
const firstAlbum = res.albums[0]
if (firstAlbum == null) return
GalleryPro.getGalleryMedia({
mediaType: 'all',
albumId: firstAlbum.albumId,
pageSize: 30,
success(list) {
console.log('当前相册媒体', list.items)
}
})
},
fail(err) {
console.log('读取相册分组失败', err.errCode, err.errMsg)
}
})
默认快速模式下,coverThumbnailPath 为空是正常结果,不表示文件夹读取失败。相册名称、count、imageCount、videoCount 和 latestMediaId 已经可以立即用于渲染侧栏或列表。
第二步:列表显示后再补封面(推荐)
先把 res.albums 赋给页面数据,让文件夹完成一次渲染;下一轮再使用每个相册的 latestMediaId 生成封面:
let albumList = []
function fillAlbumCovers(ids, offset = 0) {
if (offset >= ids.length) return
const batch = ids.slice(offset, offset + 4)
GalleryPro.getGalleryThumbnails({
ids: batch,
width: 180,
height: 180,
success(thumbnails) {
thumbnails.items.forEach(thumbnail => {
const album = albumList.find(item => item.latestMediaId == thumbnail.id)
if (album != null) album.coverThumbnailPath = thumbnail.thumbnailPath
})
// 当前批次完成后再处理下一批,避免一次生成全部封面。
setTimeout(() => fillAlbumCovers(ids, offset + batch.length), 0)
},
fail(err) {
// 单批失败不隐藏文件夹,也不阻塞后续批次。
console.log('这一批封面暂未生成', err.errCode, err.errMsg)
setTimeout(() => fillAlbumCovers(ids, offset + batch.length), 0)
}
})
}
GalleryPro.getGalleryAlbums({
mediaType: 'all',
includeCoverThumbnail: false,
success(res) {
// 先更新页面,文件夹名称和数量会立即出现。
albumList = res.albums
const ids = res.albums
.map(album => album.latestMediaId)
.filter((id, index, values) => id.length > 0 && values.indexOf(id) == index)
if (ids.length == 0) return
setTimeout(() => fillAlbumCovers(ids, 0), 0)
}
})
内置 uni-app 和 uni-app x 示例会每批处理 4 个封面,并输出查询耗时,适合直接观察“文件夹先出现、封面随后补齐”的效果。
在示例页可以按下面顺序验证:
| 按钮 | 页面表现 | 日志标记 | 适用场景 |
|---|---|---|---|
| 快速读取文件夹 | 文件夹名称和数量先出现,封面显示“待加载” | ALBUMS_FAST_OK |
只需要文件夹信息 |
| 快速读取并补封面 | 文件夹先出现,封面随后每批 4 个逐步补齐 | ALBUMS_FAST_OK、ALBUMS_LAZY_COVER_OK |
正式项目推荐 |
| 读取时生成封面(性能对照) | 等封面都处理后一次显示,可与前两项耗时对比 | ALBUMS_EAGER_COVER_OK |
兼容必须一次返回封面的旧页面 |
首次测试建议选择“快速读取并补封面”。看到文件夹名称和数量后即可操作列表,不需要等待所有封面;个别封面生成失败也不应隐藏已经显示的文件夹。
需要一次返回封面时
如果页面必须等封面准备好再接收结果,可以显式开启:
GalleryPro.getGalleryAlbums({
mediaType: 'all',
sourceType: 'all',
includeCoverThumbnail: true,
success(res) {
console.log('相册和封面均已处理', res.albums)
}
})
这种方式会等待封面缓存读取或生成,大图库首次调用可能明显慢于默认快速模式,不建议用于文件夹侧栏首屏。
sourceType 可使用 camera / screenshot / wechat / qq / download / other / all。来源分类依赖系统相册目录、文件名和平台元数据,不同设备或应用保存目录可能存在差异。
模块六:读取图片 EXIF、视频参数和位置信息
先从列表取得媒体 ID,再按需批量读取元数据。GPS 默认关闭,只有显式设置 includeLocation: true 才会请求并读取位置。
GalleryPro.getGalleryMetadata({
ids: ['media-id-1', 'media-id-2'],
includeExif: true,
includeLocation: false,
useCache: true,
progress(event) {
console.log('元数据进度', event.current, event.total)
},
success(res) {
console.log('成功/失败', res.successCount, res.failCount)
res.items.forEach((item) => {
console.log(item.id, item.width, item.height, item.durationMs)
})
},
fail(err) {
console.log('元数据任务无法启动', err.errCode, err.errMsg)
}
})
批量读取允许部分成功,items 始终与输入 ids 顺序一致。位置不会写入插件缓存,也不会被上传或转换成地址;业务只有在确实需要时才应开启位置读取,并避免把坐标写入日志。
模块七:相册变化实时监听与增量同步
页面正在展示相册时,可以注册变化监听。success 返回的 observerId 要保存下来,并在页面卸载时停止。
let galleryObserverId = ''
GalleryPro.startGalleryChangeObserver({
mediaType: 'all',
debounceMs: 500,
includeChanges: true,
change(event) {
console.log('相册发生变化', event.reason, event.changeCount)
console.log('新增/删除/修改', event.addedIds, event.removedIds, event.updatedIds)
},
success(res) {
galleryObserverId = res.observerId
},
fail(err) {
console.log('注册相册监听失败', err.errCode, err.errMsg)
}
})
function stopGalleryObserver() {
if (!galleryObserverId) return
GalleryPro.stopGalleryChangeObserver({
observerId: galleryObserverId,
success() {
galleryObserverId = ''
}
})
}
备份、云盘同步等需要可靠重试的业务,应使用持久化增量游标。首次不传 cursor 会建立基线;处理完变化后再保存新的 nextCursor。当 resetReason 为 cursorExpired 时,原游标已过期,应重新执行一次全量同步并保存新基线。
const savedCursor = uni.getStorageSync('gallery-change-cursor') || ''
GalleryPro.getGalleryChanges({
cursor: savedCursor,
mediaType: 'all',
maxChanges: 2000,
success(res) {
if (res.resetRequired) {
console.log('需要重新执行一次全量同步', res.resetReason)
} else if (!res.isInitial) {
console.log('新增', res.addedIds)
console.log('删除', res.removedIds)
console.log('修改', res.updatedIds)
}
// 业务处理成功后再推进游标,失败时保留旧游标即可重试。
uni.setStorageSync('gallery-change-cursor', res.nextCursor)
},
fail(err) {
console.log('读取相册增量失败', err.errCode, err.errMsg)
}
})
退出账号或不再使用某条基线时,调用 clearGalleryChangeCursor({ cursor })。监听只在应用进程存活期间有效,不能替代系统后台任务。
模块八:判断能力并管理缓存
先读取能力矩阵,可以在不支持的平台隐藏对应入口。
const capabilities = GalleryPro.getGalleryCapabilities()
if (!capabilities.images && !capabilities.videos) {
console.log(capabilities.message)
}
GalleryPro.clearGalleryCache({
cacheType: 'thumbnail',
success(res) {
console.log('已清理数量和字节', res.removedCount, res.releasedBytes)
},
fail(err) {
console.log('清理缓存失败', err.errCode, err.errMsg)
}
})
cacheType 可使用 thumbnail / export / changeCursor / metadata / all。清理导出缓存后,之前返回的临时路径可能失效;业务需要再次预览或上传时应重新导出。
只清理缩略图时也可以简写为 clearGalleryCache({ cacheType: 'thumbnail' })。Web/H5 和小程序等不支持平台会明确失败,不会返回伪造成功结果。
常用 API 与配置
API 用途总览
| 业务模块 | 适用业务 | 常用方法 | 使用结果 |
|---|---|---|---|
| 权限 | 页面入口、首次授权 | checkGalleryPermission、requestGalleryPermission |
当前授权状态和设置引导 |
| 媒体列表 | 图片、视频、混合素材选择 | getGalleryImages、getGalleryVideos、getGalleryMedia |
分页媒体列表 |
| 缩略图与单项 | 九宫格、详情页 | 渐进列表、getGalleryThumbnails、getMediaById |
缩略图或单个媒体信息 |
| 准备、导出与上传 | 预览、poster、编辑、业务提交 | prepareGalleryMedia、exportMediaToTempFile、uploadGalleryMedia |
可渲染、可上传路径和逐项结果 |
| 保存 | 保存生成或下载的本地媒体 | saveMediaToGallery |
按输入顺序返回保存明细 |
| 相册分组 | 相册入口、来源分类 | getGalleryAlbums |
相册、封面和数量 |
| 元数据 | 素材详情、拍摄参数 | getGalleryMetadata |
EXIF、视频参数和可选位置 |
| 实时变化 | 页面刷新 | startGalleryChangeObserver、stopGalleryChangeObserver |
变化事件和监听器 ID |
| 增量同步 | 备份、云盘、局部刷新 | getGalleryChanges、clearGalleryChangeCursor |
新增、删除、修改 ID 和新游标 |
| 能力与缓存 | 跨平台入口、空间管理 | getGalleryCapabilities、clearGalleryCache |
能力矩阵和清理结果 |
通用回调
异步方法按需要支持以下回调:
| 回调 | 触发时机 |
|---|---|
success |
当前任务成功完成;批量任务可能包含单项失败,仍需检查结果明细 |
fail |
参数、权限、平台能力或整个任务无法完成 |
complete |
成功或失败后均触发一次 |
progress |
上传、保存或元数据批处理完成一个阶段或单项时触发 |
权限参数 GalleryPermissionOptions
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
mediaType |
image / video / all |
all |
检查或请求的媒体类型 |
preferFullAccess |
boolean |
false |
iOS 有限权限时是否更倾向请求完整访问 |
success / fail / complete |
function |
无 | 权限动作回调 |
列表参数 GalleryQueryOptions
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
mediaType |
image / video / all |
all |
专用图片或视频方法会覆盖该值 |
pageSize |
number |
30 |
每页数量,建议 1~100 |
pageToken |
string |
空字符串 | 使用上次返回的 nextPageToken |
startTime / endTime |
number |
无 | 毫秒时间戳范围 |
albumId |
string |
无 | getGalleryAlbums 返回的相册 ID |
sourceType |
GallerySourceType |
all |
来源分类过滤 |
sortOrder |
desc / asc |
desc |
时间排序方向 |
includeHidden |
boolean |
false |
Android/HarmonyOS 仍受系统可见资产范围限制 |
includeThumbnail |
boolean |
false |
旧的同步缩略图开关;未传 thumbnailMode 时保持原行为 |
thumbnailMode |
none / sync / progressive |
兼容旧开关 | progressive 先返回列表,再按当前页分批补缩略图 |
thumbnailBatchSize |
number |
4 |
渐进模式每批数量,范围 1~20 |
thumbnailWidth / thumbnailHeight |
number |
240 |
查询时请求的缩略图尺寸 |
thumbnailProgress |
function |
无 | 渐进模式批次回调,包含 items/current/total/done |
options.includeHidden 只表达查询偏好;Android 与 HarmonyOS 仍受系统公开媒体范围限制,不保证包含系统隐藏媒体。
缩略图、单项与导出参数
| 方法 | 必填参数 | 常用可选参数 |
|---|---|---|
getGalleryThumbnails |
ids |
width=240、height=240、quality=80 |
getMediaById |
id |
includeThumbnail=false |
exportMediaToTempFile |
id |
exportType=render、fileName |
prepareGalleryMedia |
id |
includePoster=true、posterWidth=320、posterHeight=320 |
exportType 可使用 render / upload / original,它只表示本次使用意图,不会生成三份文件。一次导出始终同时返回同一文件的 renderPath 和 uploadPath;相同媒体未变化时会复用有效缓存,并通过 cacheHit 告知是否命中。
上传参数 GalleryUploadOptions
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
ids |
Array<string> |
无 | 必填,结果顺序与该数组一致 |
url |
string |
无 | dryRun=true 时可以不传 |
dryRun |
boolean |
false |
只验证导出,不发起网络请求 |
name |
string |
file |
文件表单字段名 |
formData |
UTSJSONObject |
无 | 附加表单字段 |
concurrency |
number |
1 |
建议 1~3 |
retryCount |
number |
0 |
单项失败重试次数 |
timeoutMs |
number |
60000 |
单文件上传超时毫秒数 |
保存参数 GallerySaveOptions
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
paths |
Array<string> |
无 | 必填,本地绝对路径或 file:// 路径 |
albumName |
string |
系统默认相册 | 自定义目标相册名称 |
duplicatePolicy |
allow / skip |
allow |
保存重复项或跳过可见重复项 |
progress |
function |
无 | 每处理完一项触发 |
相册与元数据参数
| 方法 | 必填参数 | 常用可选参数 |
|---|---|---|
getGalleryAlbums |
无 | mediaType=all、sourceType=all、includeCoverThumbnail=false |
getGalleryMetadata |
ids |
includeExif=true、includeLocation=false、useCache=true |
includeCoverThumbnail=false 是默认快速模式,coverThumbnailPath 返回空字符串;设为 true 才会在相册结果返回前处理封面。需要首屏流畅时,推荐使用 latestMediaId + getGalleryThumbnails 在列表显示后补封面。
getGalleryMetadata 接受 1~100 个不重复 ID。位置必须由 includeLocation: true 显式开启,并受平台权限控制。
监听与增量参数
| 方法 | 必填参数 | 常用可选参数 |
|---|---|---|
startGalleryChangeObserver |
change |
mediaType=all、debounceMs、includeChanges=false、maxChanges=2000 |
stopGalleryChangeObserver |
observerId |
无 |
getGalleryChanges |
无 | cursor、mediaType=all、maxChanges=2000 |
clearGalleryChangeCursor |
cursor |
无 |
首次不传 cursor 调用 getGalleryChanges 会建立基线。旧游标在有效期内保持不变,业务处理失败时可继续使用旧游标重试。
缓存参数 GalleryClearCacheOptions
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
cacheType |
GalleryCacheType |
all |
thumbnail / export / changeCursor / metadata / all |
olderThanMs |
number |
无 | 只清理早于该毫秒时间戳的缓存 |
主要返回值
权限与列表
| 类型 | 关键字段 | 说明 |
|---|---|---|
GalleryPermissionResult |
granted、status、limited、shouldOpenSettings、platform、message |
success 回调后仍需依据 granted/status 判断授权结果 |
GalleryQueryResult |
total、items、hasMore、nextPageToken、mediaType |
当前查询条件下的一页结果 |
GalleryMediaByIdResult |
item、message |
返回单个媒体;媒体已删除时会失败 |
媒体项 GalleryMediaItem
| 字段 | 类型 | 说明 |
|---|---|---|
id |
string |
当前平台稳定媒体 ID,后续 API 使用该值 |
mediaType |
image / video |
媒体类型 |
fileName / mimeType |
string |
文件名和 MIME 类型 |
width / height |
number |
像素宽高 |
durationMs |
number |
视频时长,图片为 0 |
size |
number |
文件大小,单位字节 |
createTime / modifiedTime |
number |
毫秒时间戳 |
albumId / albumName |
string |
所属相册 |
sourceType / sourceLabel |
string |
来源分类和中文说明 |
originalPath |
string |
原始路径或平台资产标识,不保证可直接渲染 |
renderPath |
string |
页面可显示路径 |
uploadPath |
string |
上传可用路径 |
thumbnailPath |
string |
缩略图路径 |
requiresExport |
boolean |
是否需要先导出才能稳定显示 |
缩略图、导出、上传与保存
| 类型 | 关键字段 | 说明 |
|---|---|---|
GalleryThumbnailItem |
id、thumbnailPath、width、height、message |
单个缩略图结果 |
GalleryThumbnailResult |
success、items、message |
批量缩略图结果 |
GalleryThumbnailProgress |
items、current、total、done、message |
当前页渐进缩略图批次 |
GalleryExportResult |
id、renderPath、uploadPath、size、cacheHit、message |
导出后的临时文件信息 |
GalleryPrepareResult |
id、mediaType、renderPath、uploadPath、posterPath、size、cacheHit |
一次准备预览、上传和 poster 路径 |
GalleryUploadResult |
successCount、failCount、items、message |
items 与输入 ids 顺序一致 |
GallerySaveResult |
successCount、failCount、skippedCount、items、message |
items 与输入 paths 顺序一致 |
GalleryUploadItemResult 和 GallerySaveItemResult 都包含输入下标、单项成功状态、错误码和中文说明;批量结果的 success=false 不代表所有单项都失败。
相册分组 GalleryAlbumItem
| 字段 | 说明 |
|---|---|
albumId / albumName |
相册 ID 和名称 |
sourceType |
来源分类 |
count / imageCount / videoCount |
媒体总数和分类数量 |
coverThumbnailPath |
相册封面缩略图;默认快速模式下为空字符串 |
latestMediaId / latestMediaType |
最新媒体 ID 和类型;可交给 getGalleryThumbnails 按需生成封面 |
latestFileName / latestCreateTime |
最新媒体文件名和创建时间 |
元数据结果 GalleryMetadataItem
| 字段 | 说明 |
|---|---|
id / success / mediaType |
输入 ID、单项状态和媒体类型 |
width / height / durationMs / orientation |
宽高、视频时长和方向 |
captureTime |
拍摄时间,未知为 0 |
cameraMake / cameraModel / lensModel |
相机、机型和镜头信息 |
iso / exposureTime / aperture |
ISO、曝光时间和光圈,未知时省略 |
focalLength / focalLength35mm |
焦距和 35mm 等效焦距,未知时省略 |
videoCodec / videoBitrate / videoFrameRate |
视频编码、码率和帧率 |
locationAvailable / location |
本次是否返回位置及经纬度;默认不读取 |
fromCache |
非敏感字段是否来自缓存 |
errCode / message |
单项诊断码和中文结果 |
GalleryMetadataResult.items 与输入 ids 顺序一致。success=true 的单项也可能携带非致命 9070032,表示缓存读写失败,但原始媒体元数据仍读取成功。
监听、增量和缓存结果
| 类型 | 关键字段 | 说明 |
|---|---|---|
GalleryChangeObserverStartResult |
observerId、message |
保存 ID 以便停止监听 |
GalleryChangeEvent |
reason、addedIds、removedIds、updatedIds、changeCount |
includeChanges=false 时精确 ID 可能为空 |
GalleryChangesResult |
isInitial、resetRequired、resetReason、三类 ID、nextCursor |
成功处理后再保存新游标 |
GalleryClearChangeCursorResult |
cursor、removed、message |
游标不存在仍可按幂等成功处理 |
GalleryClearCacheResult |
removedCount、releasedBytes、message |
返回本次实际清理结果 |
能力矩阵 GalleryCapabilities
常用字段包括 images、videos、mixed、pagination、timeRange、sourceClassification、thumbnails、exportTempFile、upload、saveMedia、metadata、exif、locationMetadata、changeObserver、incrementalChanges、persistentChangeCursor、customBaseRecommended 和 message。
错误码
| 错误码 | 含义 | 说明 |
|---|---|---|
| 9070001 | unsupported or context unavailable | 当前平台不支持,或 App 上下文不可用 |
| 9070002 | permission denied | 相册读取权限未授权或请求失败 |
| 9070003 | invalid options | 参数为空、ID 列表为空或格式不正确 |
| 9070004 | media not found | 指定媒体不存在,可能已被删除或 ID 不属于当前平台 |
| 9070005 | album query failed | 相册分组查询失败 |
| 9070006 | cache failed | 缓存目录创建或写入失败 |
| 9070007 | query failed | 相册列表、分组或平台桥接查询失败 |
| 9070008 | thumbnail failed | 缩略图生成失败 |
| 9070009 | export failed | 媒体导出失败,iOS 可能需要先下载 iCloud 原图 |
| 9070010 | upload failed | 上传过程失败,包含上传地址为空、网络请求失败或超时 |
| 9070011 | cache clear failed | 缓存清理失败 |
| 9070012 | cancelled | 任务被取消或系统中断 |
| 9070013 | file unavailable | 导出后的文件不可访问 |
| 9070014 | internal failed | 插件内部异常,建议保留日志排查 |
| 9070015 | observer register failed | 原生相册变化观察器注册失败 |
| 9070016 | observer not found | observerId 不存在或已经停止 |
| 9070017 | invalid observer options | 缺少 change 回调或监听参数不合法 |
| 9070018 | invalid save options | paths 为空、全部为空字符串或参数不合法 |
| 9070019 | source unavailable | 本地源文件不存在、不可读或不是普通文件 |
| 9070020 | unsupported media type | 输入文件无法识别为支持的图片或视频 |
| 9070021 | add permission denied | 系统相册写入或判重所需读取权限被拒绝 |
| 9070022 | album operation failed | 创建、查找或更新指定目标相册失败 |
| 9070023 | save media failed | 创建相册记录、复制文件或 PhotoKit 保存失败 |
| 9070024 | save unsupported | 当前平台没有系统相册保存实现 |
| 9070025 | invalid change cursor options | 增量参数或游标格式不合法 |
| 9070026 | change snapshot failed | 增量快照扫描、读取或写入失败 |
| 9070027 | gallery changes unsupported | 当前平台不支持系统相册增量变化 |
| 9070028 | clear change cursor failed | 指定增量游标清理失败 |
| 9070029 | invalid gallery metadata options | 元数据参数无效,例如 ID 为空、超过 100 个或存在重复 ID |
| 9070030 | gallery metadata read failed | 单个媒体的元数据读取失败 |
| 9070031 | gallery metadata unsupported | 当前平台不支持系统相册元数据读取 |
| 9070032 | gallery metadata cache failed | 非敏感元数据缓存读写失败;属于非致命错误,插件继续读取原始媒体 |
常见问题
为什么权限检查成功后仍然不能读取相册
权限 API 的 success 表示检查动作完成,不代表已经授权。请检查 granted 和 status;denied 或 restricted 时不要继续读取,也不要把结果展示为“相册为空”。
HarmonyOS 为什么返回 9070002
HarmonyOS 完整相册访问需要同时满足三层条件:应用已通过 AppGallery Connect(AGC)受限权限审核且 Profile 取得 READ_IMAGEVIDEO、WRITE_IMAGEVIDEO 等所需 ACL,应用安装包已经声明对应权限,用户在设备上完成运行时授权。任一条件缺失都可能返回 9070002。
ohos.permission.MEDIA_LOCATION 用于受控读取媒体位置,属于运行时敏感权限,不是 Gallery Pro 需要申请的 ACL 项。只有业务显式开启 includeLocation 时才需要处理位置授权。
返回空数组是没有权限吗
不是。权限失败会通过权限状态或 fail 返回明确错误;成功返回空数组通常表示当前相册没有可见媒体,或时间、相册、来源等筛选条件没有匹配结果。
为什么列表中的路径不能直接预览
不同平台可能返回系统资产标识,而不是普通文件路径。Android 列表中的 originalPath / renderPath / uploadPath 可能都是 content://,它们用于标识 MediaStore 资产,不保证能直接交给 <image>、<video> 或 uni.uploadFile。列表先使用 thumbnailPath;需要大图、视频、poster 或上传路径时调用 prepareGalleryMedia。旧代码也可继续调用 exportMediaToTempFile,页面使用其 renderPath,上传使用 uploadPath。
为什么 getGalleryImages 获取的图片在部分手机上很模糊
getGalleryImages 不会修改或压缩系统相册中的原文件,但启用 includeThumbnail 或随后调用 getGalleryThumbnails 时,返回的 thumbnailPath 是经过缩放和 JPEG 编码的缓存缩略图。缩略图用于列表快速显示;如果把较小的缩略图放大到详情页或全屏区域,在高分辨率设备上会明显模糊。
- 列表小图使用
thumbnailPath,并让thumbnailWidth / thumbnailHeight或width / height接近实际显示所需的物理像素。不要把180 × 180的缩略图放大到数百像素区域。 - 2:1 全景图列表可以按页面尺寸请求较大的同比例缩略图,例如
800 × 400;希望保留完整画面时,页面图片使用aspectFit,使用aspectFill会裁剪画面边缘。 - 详情页、全屏预览、图片编辑必须调用
exportMediaToTempFile,使用该方法返回的renderPath。不要把列表结果中的thumbnailPath当作原图路径。 - iOS 列表结果中的
renderPath可能与thumbnailPath相同,因此也不能把它当作原图;仍应以exportMediaToTempFile返回的renderPath为准。 - 上传原文件时使用导出结果中的
uploadPath,不要上传thumbnailPath。
如果同一套页面代码在部分手机清晰、部分手机模糊,请优先记录实际绑定到 <image :src> 的字段、缩略图请求尺寸和图片显示尺寸,检查是否在不同设备上把小尺寸 thumbnailPath 放大显示。
为什么文件夹已经显示,但相册封面为空
这是 getGalleryAlbums 的默认快速模式。插件会先返回文件夹名称、数量和最新媒体信息,避免等待全部缩略图后才显示侧栏。需要封面时,使用每个相册的 latestMediaId 调用 getGalleryThumbnails;如果确实需要一次返回全部封面,再显式传入 includeCoverThumbnail: true。
大图库如何避免卡顿
媒体列表使用合理的 pageSize,保存 nextPageToken 并按需加载下一页;推荐设置 thumbnailMode: 'progressive',先渲染当前页基础信息,再通过 thumbnailProgress 分批补图。文件夹列表保持 includeCoverThumbnail: false,先渲染名称和数量,再分批补封面。不要在首屏串行生成全部缩略图,也不要为了“读取全部”把 pageSize 设置得非常大。
iOS 为什么只能看到部分照片
用户可能选择了有限照片权限。此时 status 通常为 limited,插件只能读取系统允许当前应用访问的媒体。业务可以说明用途并让用户自行调整授权范围,但不能绕过系统选择。
为什么默认读不到照片位置
位置属于敏感信息,includeLocation 默认是 false。显式开启后仍受平台权限和媒体本身是否包含位置影响。位置不会进入插件缓存,locationAvailable=false 也不能直接证明原媒体没有 GPS。
保存后为什么仍可能出现重复媒体
默认策略 allow 会正常保存每个输入文件。skip 只能根据系统当前可见范围判断可见重复项;文件内容变化、权限范围变化或不同设备之间都可能无法命中。
为什么相册监听没有触发
先确认监听注册成功并保存了 observerId。监听只在应用进程存活期间有效,系统变化可能经过 debounceMs 防抖;需要跨启动可靠同步时改用 getGalleryChanges 和持久化游标。
为什么只更新页面资源后原生能力没有变化
本插件包含 Android、iOS 和 HarmonyOS 原生实现。首次集成,或修改插件原生代码、权限声明、原生依赖后,需要重新制作并安装对应平台的自定义基座、正式安装包或 HAP。普通页面和 README 修改不需要重新制作基座。
完整示例
- uni-app:
uni_modules/lizhao-gallery-pro/example/uniapp/galleryPro.vue - uni-app x:
uni_modules/lizhao-gallery-pro/example/uniappx/index.uvue
完整示例包含权限、图片/视频/混合列表、分页、相册分组、缩略图、临时导出、上传 dry-run、保存、元数据、变化监听、增量游标和缓存管理。
注意事项
- 页面必须从插件根目录导入,不要直接引用
utssdk内部文件。 - Android 13 及以上按图片和视频分别授权;Android 12 及以下使用外部存储读取权限。用户永久拒绝后,根据
shouldOpenSettings引导到系统设置。 - iOS
limited表示用户只授权部分照片,所有列表、分组、判重和变化结果都以系统当前可见范围为准。 - HarmonyOS 完整相册能力需要 ACL、应用权限声明和用户授权同时生效。没有 ACL 时,重复调用运行时权限请求不能解决问题。
- 读取位置必须显式设置
includeLocation: true;插件不进行逆地理编码,不上传、不记录、不缓存位置。 - 图片 EXIF、视频参数和位置均由系统公开 API 在本地读取;云端原图尚未下载时可能出现单项失败。
originalPath可能是content://等平台资产标识,不保证能直接交给页面或上传接口;优先使用缩略图和prepareGalleryMedia结果。- 临时导出文件与缩略图受缓存清理影响。清理后原路径失效时,应重新调用对应 API。
- 上传和保存是批量任务,必须查看逐项结果,不能只依据整体
success判断每个文件。 - 来源分类能覆盖常见目录,但不同系统、ROM 和第三方应用保存路径可能导致分类差异。
- 页面卸载时停止变化监听;增量同步只在业务处理成功后保存新的
nextCursor。 - Web/H5 和小程序不支持本插件的系统相册整库读取;请使用各平台提供的选择器能力。
- 只修改 README、普通页面或样式时不需要重新制作自定义基座;修改原生实现、权限或依赖时必须重新制作并安装匹配包。
联系方式
微信:l-z-1-8-7-1512-5421(使用时去掉连字符)。
作者系列 UTS 插件
以下为已在 DCloud 插件市场上架的作者系列 UTS 插件,可按业务场景组合使用。未列出的插件表示当前未确认公开市场页,后续上架后再补充。
| 插件 | 能力方向 | 插件市场 |
|---|---|---|
lizhao-nfc-pro |
NFC 标签读写、NDEF、IsoDep 与诊断 | 查看插件 |
lizhao-float-window |
悬浮窗、画中画、权限与诊断 | 查看插件 |
lizhao-device-id |
设备标识、隐私策略与诊断 | 查看插件 |
lizhao-scan-pro |
原生扫码、连续扫码、相册识别 | 查看插件 |
lizhao-choose-file |
原生文件选择、上传、进度与取消 | 查看插件 |
lizhao-bg-audio |
背景音频播放、队列、倍速与事件 | 查看插件 |
lizhao-smart-tts |
系统 TTS、云端合成、听书方案 | 查看插件 |
lizhao-share-plus |
系统分享、远程文件下载后分享 | 查看插件 |
lizhao-sqlite-pro |
原生 SQLite、迁移、备份与诊断 | 查看插件 |
lizhao-icon-pro |
SVG 图标组件、多主题与缓存 | 查看插件 |
lizhao-cast-screen |
DLNA 投屏、AirPlay 路由入口 | 查看插件 |
lizhao-call-kit |
电话、短信、通讯录原生能力 | 查看插件 |
lizhao-app-keepalive |
应用保活、唤醒、自愈与报告 | 查看插件 |
lizhao-doc-corrector |
文档扫描、矫正、增强与识别 | 查看插件 |
lizhao-emu-detect |
模拟器环境检测、风险评分与证据 | 查看插件 |
lizhao-gallery-pro |
相册媒体分页、筛选、缩略图与导出 | 查看插件 |
lizhao-video-thumb |
视频封面、批量取帧与 Base64 返回 | 查看插件 |
lizhao-ble |
BLE 扫描、连接、读写、通知与自动重连 | 查看插件 |
lizhao-sse-pro |
SSE、Line、JSONL 与 Raw 流式请求 | 查看插件 |
lizhao-pdf-pro |
PDF 阅读、签批、真实写回与页面处理 | 查看插件 |
lizhao-serial-port |
路径串口、USB 串口、多会话收发与诊断 | 查看插件 |
lizhao-wechat-kit |
微信登录、分享、支付、小程序与客服 | 查看插件 |
lizhao-video-editor |
视频裁剪、压缩、取帧与 FFmpeg/FFprobe | 查看插件 |
lizhao-vpn-pro |
企业 VPN、IKEv2、安全接入与脱敏诊断 | 查看插件 |
lizhao-camera-pro |
原生相机、拍照录像、水印与媒体保存 | 查看插件 |
lizhao-tcp-pro |
TCP 客户端、服务端、多连接与诊断 | 查看插件 |
lizhao-notify-pro |
本地通知、点击动作、进度与定时提醒 | 查看插件 |

收藏人数:
购买源码授权版(
试用
赞赏(0)
下载 6486
赞赏 5
下载 12648413
赞赏 1953
赞赏
京公网安备:11010802035340号