多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

uni-app x 的 uni.chooseMedia 跨端媒体选择 API 完整指南:参数、返回值、错误码与三端实现原理

uni-app x 的 uni.chooseMedia 跨端媒体选择 API 完整指南:参数、返回值、错误码与三端实现原理 示例工程前端移动开发跨平台【免费下载链接】uni-appA cross-platform framework using Vue.js项目地址https://gitcode.com/gh_mirrors/un/uni-app点击查看免费下载uni.chooseMedia 是 uni-app / uni-app x 提供的拍摄或从手机相册中选择图片或视频的统一媒体选择 API一次调用即可覆盖拍照、录像、相册多选图片/视频等高频场景。本文以 docs/api/choose-media.md 为核心结合仓库内uni-chooseMediaUTS 插件源码Android / iOS / HarmonyOS 三端实现与 hello uni-app x 示例页面完整讲解其参数含义、返回结构、错误码规范、实战代码以及底层实现细节帮助开发者正确选型并落地媒体选择功能。一、功能概述与兼容性uni.chooseMedia(options)用于拍摄或从手机相册中选择图片或视频是微信小程序wx.chooseMedia能力在 uni-app 生态中的统一封装。它相比旧的uni.chooseImage/uni.chooseVideo的优势在于一次调用同时支持图片与视频mix模式并在返回中区分文件类型相册多选、拍照、录像统一走一套参数体系返回统一结构的ChooseMediaSuccess便于上层渲染预览图、缩略图。平台兼容性| 平台 | 支持情况 | | :- | :- | | Web | 不支持x | | 微信小程序 | 4.41 起 | | Android | 4.51 起 | | iOS | 4.51 起 | | HarmonyOS | 4.61 起 |以上版本号来自 docs/api/choose-media.md 兼容性表pageOrientation、sizeType等个别参数的兼容性有差异见下文参数表。从 package.json 可以看到该能力以uni-chooseMediaUTS 插件形式发布分别编译为 KotlinAndroid、SwiftiOS、ArkTSHarmonyOS属于 DCloud 官方扩展 API 的一部分。能力模型uni.chooseMedia(options) │ ├── sourceType: [album] / [camera] / [album,camera] ├── mediaType: [image] / [video] / [image,video] / [mix] ├── count / maxDuration / camera / pageOrientation │ ├── success(res: ChooseMediaSuccess) │ └── res.tempFiles: ChooseMediaTempFile[]tempFilePath / fileType / size / byteSize / duration / width / height / thumbTempFilePath ├── fail(err: ChooseMediaFail) │ └── err.errCode1101001/1101005/1101006/1101008/1101010、err.errSubject、err.errMsg └── complete(res)二、options 参数详解uni.chooseMedia(options)仅接受一个ChooseMediaOptions对象参数。其类型定义见 interface.uts完整参数如下| 名称 | 类型 | 必填 | 默认值 | 描述 | | :- | :- | :- | :- | :- | | pageOrientation | string | 否 | 默认取 pages.json 中的 pageOrientation | 屏幕方向合法值auto/portrait/landscape| | count | number | 否 | 9 | 最多可以选择的文件个数 | | mediaType | Arraystring | 否 |[image,video]|image只能拍摄图片或从相册选择图片video只能拍摄视频或从相册选择视频mix可同时选择图片和视频合法值image、video、mix| | sourceType | Arraystring | 否 |[album,camera]|album从相册选择camera使用相机拍摄 | | maxDuration | number | 否 | 10 | 拍摄视频最长拍摄时间单位秒时间范围为 3s 至 30s 之间 | | camera | string | 否 | — | 仅在sourceType为camera时生效指定前置或后置摄像头 | | sizeType | Arraystring | 否 | — | 是否压缩所选文件微信小程序基础库 2.25.0 前仅对mediaType为image时有效2.25.0 及以后对全量mediaType有效 | | success | (ChooseMediaSuccess) void | 否 | — | 接口调用成功回调 | | fail | (ChooseMediaFail) void | 否 | — | 接口调用失败回调 | | complete | (any) void | 否 | — | 接口调用结束回调成功、失败都会执行 |参数合法值说明pageOrientation| 合法值 | 描述 | | :- | :- | | auto | 自动 | | portrait | 竖屏显示 | | landscape | 横屏显示 |camera| 合法值 | 描述 | | :- | :- | | front | 前置摄像头 | | back | 后置摄像头 |默认值与参数校正源码佐证在 protocol.uts 中可以看到默认值及合法性的统一处理逻辑这正是参数默认值的底层实现count为空时默认 9且超过 9 会被强制收敛为 9params.count 9时重置为 9mediaType为空时默认[image, video]sourceType为空时默认[album, camera]maxDuration为空时默认 10camera为空时默认back后置摄像头sizeType的默认值逻辑在源码中被注释保留[original, compressed]当前正式实现中未启用App 端选择后默认不压缩。也就是说即使你不传任何参数uni.chooseMedia()也等价于从相册或相机、图片或视频都允许、最多选 9 个、录像最长 10 秒、默认后置摄像头。开发者应理解这些隐式默认值避免以为只选了相册之类的误解。三、返回值ChooseMediaSuccess 与 ChooseMediaTempFileChooseMediaSuccess| 名称 | 类型 | 必填 | 描述 | | :- | :- | :- | :- | | tempFiles | ArrayChooseMediaTempFile | 是 | 选中的文件列表临时文件路径等 | | type | string | 是 | 本次选择的媒体类型合法值image/video/mix|当同时选择了图片和视频时type返回mix。Android 实现中mix判断来自mediaType参数见 app-android/index.utsiOS 的 PHPicker 实现则根据实际返回结果动态归类app-ios/index.uts。ChooseMediaTempFiletempFiles 数组元素| 名称 | 类型 | 必填 | 描述 | | :- | :- | :- | :- | | tempFilePath | string | 是 | 选定媒体文件的临时文件路径 | | fileType | string | 是 | 文件类型合法值image/video| | size | number | 是 | 文件数据量大小单位 kB | | byteSize | number | 否 | 文件的字节大小单位 BAndroid / iOS / HarmonyOS 4.61 起支持 | | duration | number | 否 | 视频时长秒 | | height | number | 否 | 视频高像素 | | width | number | 否 | 视频宽像素 | | thumbTempFilePath | string | 否 | 视频缩略图临时文件路径 |fileType 合法值image、video。type 合法值image、video、mix。精度说明从 HBuilderX 4.61 起ChooseMediaSuccess中的duration、size精度统一调整为小数点后 3 位数。源码中 Android 端通过DecimalFormat(#.###)格式化app-android/index.utsiOS 端通过NumberFormatter.maximumFractionDigits 3实现app-ios/index.uts两端实现一致。Android 端路径注意Android 端返回的路径是content://协议见文档原注及 app-android/index.uts 中getMediaTempFile对file:///content://的处理。如果你的业务代码后续要用uni.uploadFile、文件系统 API 或原生模块处理这些文件需注意content://URI 与绝对路径的差异。四、错误处理ChooseMediaFail 与错误码规范ChooseMediaFail| 名称 | 类型 | 必填 | 描述 | | :- | :- | :- | :- | | errCode | number | 是 | 错误码 | | errSubject | string | 是 | 统一错误主题模块名称 | | data | any | 否 | 错误信息中包含的数据 | | cause | Error | 否 | 源错误信息可包含多个错误详见 uni错误规范 | | errMsg | string | 是 | 错误描述 |errCode 错误码| 错误码 | 描述 | | :- | :- | | 1101001 | 用户取消 | | 1101005 | 未获取权限 | | 1101006 | 图片或视频保存失败 | | 1101008 | 拍照或录像失败 | | 1101010 | 其他错误 |上述错误码与描述在 unierror.uts 中定义ChooseMediaUniErrorsMap错误主题errSubject固定为uni-chooseMedia。错误码类型约束在 interface.uts 中声明属于模块级错误码段11010011101010。错误规范背景uni 错误规范在 docs/err-spec.md 中有完整定义所有异步 API 通过回调返回UniError类型错误包含errSubject区隔不同模块 errCode 冲突、errCode、errMsg、可选data与cause暴露底层来源。uni.chooseMedia从设计上遵循了该规范因此你可以用统一的错误拦截逻辑例如uni.addInterceptor或统一的fail处理来集中处理所有媒体选择失败场景fail: (err) { switch (err.errCode) { case 1101001: // 用户主动取消一般无需提示 break; case 1101005: // 引导用户去系统设置开启相册/相机权限 break; case 1101006: case 1101008: case 1101010: // 保存失败 / 拍摄失败 / 其他错误 break; } }五、完整实战示例uvue仓库 src/pages/API/choose-media/choose-media.uvue 中提供了完整的可运行示例与文档示例同步。以下为文档示例的核心逻辑整理涵盖来源切换、媒体类型切换、数量限制、摄像头选择、屏幕方向Android、最长拍摄时间iOS以及选择结果的预览/删除template scroll-view classpage-scroll-view uni-theme-root view classuni-theme-root page-head :titletitle/page-head view classuni-common-mt view classuni-list view classuni-list-cell cell-pd clickchooseMediaSource text classuni-label来源/text text classclick-t{{sourceTypes[sourceTypeIndex].title}}/text /view view classuni-list-cell cell-pd clickchooseMediaType text classuni-label方式/text text classclick-t{{mediaTypes[mediaTypeIndex].title}}/text /view view classuni-list-cell cell-pd text classuni-label数量限制/text input classclick-t :valuecount typenumber :maxlength1 blurchooseMediaCount/ /view !-- #ifdef APP-ANDROID -- view classuni-list-cell cell-pd clickchooseOrientationType text classuni-label屏幕方向/text text classclick-t{{orientationTypes[orientationTypeIndex].title}}/text /view !-- #endif -- view classuni-list-cell cell-pd clickchooseCameraType text classuni-label摄像头/text text classclick-t{{cameraTypes[cameraTypeIndex].title}}/text /view /view view classuni-list list-pd stylepadding: 15px; view classuni-row stylemargin-bottom: 10px; text classmedia-label点击预览 {{mediaList.length}}/{{count}}/text /view view classuni-row styleflex-wrap: wrap; view v-for(file,index) in mediaList :keyindex classuni-uploader__input-box image stylewidth: 104px; height: 104px; :srcfile.imagePath tappreviewMedia(index)/image image src/static/plus.png classimage-remove clickremoveMedia(index)/image /view image classuni-uploader__input-box tapchooseMedia src/static/plus.png/image /view /view /view /view /scroll-view /template script setup languts type FileSource { imagePath : string; filePath : string; fileType : string; }; const sourceTypeList [ { value: [camera], title: 拍摄 }, { value: [album], title: 相册 }, { value: [camera, album], title: 拍摄或相册 } ]; const mediaTypeList [ { value: [image], title: 仅图片 }, { value: [video], title: 仅视频 }, { value: [image, video], title: 不限制 } ]; const orientationTypeList [ { value: [portrait], title: 竖屏 }, { value: [landscape], title: 横屏 }, { value: [auto], title: 自动 } ]; const cameraTypeList [ { value: [front], title: 前置摄像头 }, { value: [back], title: 后置摄像头 } ]; const mediaList ref([] as ArrayFileSource) const sourceTypeIndex ref(2) const mediaTypeIndex ref(2) const cameraTypeIndex ref(1) const orientationTypeIndex ref(0) const count ref(9) const maxDuration ref(10) const chooseMediaCount (event: UniInputBlurEvent) { let countValue parseInt(event.detail.value) if (countValue 1 || countValue 9 || isNaN(countValue)) { uni.showToast({ position: bottom, title: 图片数量应该不小于1不大于9 }) return } count.value countValue } const chooseMedia () { if (mediaList.value.length count.value) { uni.showToast({ position: bottom, title: 已经有 count.value 个了请删除部分后重新选择 }) return } uni.chooseMedia({ count: count.value - mediaList.value.length, sourceType: sourceTypeList[sourceTypeIndex.value].value, mediaType: mediaTypeList[mediaTypeIndex.value].value, camera: cameraTypeList[cameraTypeIndex.value].value[0], // #ifdef APP-IOS maxDuration: maxDuration.value, // #endif // #ifdef APP-ANDROID pageOrientation: orientationTypeList[orientationTypeIndex.value].value[0], // #endif success: (res) { const tempFiles : ChooseMediaTempFile[] res.tempFiles as ChooseMediaTempFile[]; for (let i 0; i tempFiles.length; i) { const tempFile : ChooseMediaTempFile tempFiles[i] // 图片直接展示原图视频展示缩略图 const imagePath tempFile.fileType image ? tempFile.tempFilePath : tempFile.thumbTempFilePath; mediaList.value.push({ imagePath: imagePath!, filePath: tempFile.tempFilePath, fileType: tempFile.fileType }); } }, fail: (err) { console.log(err: , JSON.stringify(err)); uni.showToast({ title: choose media error.code: err.errCode ;message: err.errMsg, position: bottom }) } }) } const previewMedia (index: number) { const file : FileSource mediaList.value[index]; if (file.fileType image) { uni.previewImage({ current: 0, urls: [file.filePath] }) } else { // 视频跳转全屏播放页 uni.navigateTo({ url: /pages/API/choose-media/fullscreen-video }) } } const removeMedia (index: number) { mediaList.value.splice(index, 1) } /script示例中几个值得注意的实战细节条件编译maxDuration仅在APP-IOS编译pageOrientation仅在APP-ANDROID编译这是由两端能力差异决定的iOS 相机选完即回调、Android 相册系统 UI 支持页面方向与文档参数兼容性表一一对应数量联动调用时传入count: count.value - mediaList.value.length实现已选数量 本次选择 ≤ 总数限制视频预览图片用uni.previewImage视频跳转全屏页播放返回值消化图片取tempFilePath直接展示视频取thumbTempFilePath作为封面图避免直接加载视频文件。该 API 不支持 Web请运行到 App 平台体验文档示例说明。六、三端实现原理源码级解读uni-chooseMedia在仓库中的完整实现位于 src/uni_modules/uni-chooseMedia采用 UTS 插件架构公共类型定义在utssdk/interface.uts与utssdk/protocol.uts错误定义在utssdk/unierror.uts各端实现按目录分离utssdk/app-android、utssdk/app-ios、utssdk/app-harmony。从源码结构可以梳理出各平台的底层能力选型。Android 端入口 app-android/index.uts 的调用链为根据sourceType与mediaType组合出操作项列表拍摄、录像、从相册选择多于一项时用uni.showActionSheet弹窗让用户选择拍照 / 录像通过MediaStore.ACTION_IMAGE_CAPTURE/ACTION_VIDEO_CAPTURE启动系统相机 Intent借助FileProvider生成输出 Uri将临时文件写入应用缓存目录getAppCachePath() uni-media/maxDuration映射到MediaStore.EXTRA_DURATION_LIMITcamera映射到CAMERA_FACING1 前置 / 0 后置相册通过自定义的SystemPickerActivityDCloudUniMedia 模块拉起系统相册多选 UI支持content://结果回调权限Android 13targetSdk 33及以上直接使用系统相册选择器无需读存储权限低版本先申请READ_EXTERNAL_STORAGE相机路径申请CAMERA权限失败回调 1101005视频元数据用MediaMetadataRetriever读取时长/宽高/旋转角/码率/首帧缩略图MediaExtractor兜底补齐缺失字段如部分格式下 retriever 拿不到宽高、帧率时时长/大小统一按 3 位小数格式化。Android 配置config.jsonminSdkVersion为 21依赖androidx.appcompat:appcompat:1.6.1、androidx.activity:activity-ktx:1.9.2。iOS 端入口 app-ios/index.uts 的实现特点权限链拍摄前先申请相机权限AVCaptureDevice.requestAccess若mediaType含video还须先申请麦克风权限录像需要录音任一权限被拒则回调 1101005拍摄UIImagePickerControllersourceType cameracameraDevice根据camera参数取 front/rearvideoMaximumDuration会将maxDuration收敛到 330 秒区间相册iOS 14.0 使用PHPickerViewControllerPHPickerConfiguration.selectionLimit即countPHPickerFilter.images/videos对应mediaType低版本回退UIImagePickerControllerphotoLibraryPHPicker 无需相册权限即可使用临时文件图片/视频统一拷贝到沙盒 cache 目录UTSiOS.getMediaCacheDir()视频用AVURLAssetAVAssetImageGenerator提取首帧作为缩略图结果聚合PHPicker 的多选结果通过DispatchGroup并发处理NSItemProvider加载全部完成后统一回调。iOS 配置config.json 与 info.plistdeploymentTarget为 12Info.plist中必须声明NSCameraUsageDescription摄像头与NSMicrophoneUsageDescription麦克风用途文案否则调用拍摄会崩溃或被拒。HarmonyOS 端入口 app-harmony/index.uts 的实现特点拍摄调用系统相机拾取器cameraPicker.pick()通过PickerProfile传入cameraPosition前后摄与videoDuration录像时长媒体类型经getCameraPickerMediaTypes映射为PickerMediaType.PHOTO/VIDEO相册调用photoAccessHelper的照片选择器按mediaType映射PhotoViewMIMETypesIMAGE_TYPE / VIDEO_TYPE / IMAGE_VIDEO_TYPEcount透传为多选数量resultCode 语义resultCode -1视为用户取消1101001其余异常按拍摄失败1101008/未知错误1101010处理视频文件的元数据时长、宽高、缩略图、字节大小由media.uts中的getMediaAssetInfo统一补齐。七、Tips 与注意事项官方提示汇总文档末尾列出的平台注意事项开发时必须知悉相册选择是系统 UIchooseMedia 的相册选择在 App 平台使用系统 UI不同 ROM 风格有差异多选操作有的是长按、有的是 checkbox系统 UI 的暗黑模式、国际化跟随系统而不跟随 AppAndroid 端限制由于系统或 ROM 的限制拍照时的maxDuration和camera属性在部分手机上不生效精度变更从 HBuilderX 4.61 版起ChooseMediaSuccess中duration、size精度统一调整为小数点后 3 位数两端实现见上文iOS 临时文件iOS 端拍照和相册选择会在应用沙盒目录的 cache 目录产生临时文件位置详见 file-system-spec.md。如需主动删除临时文件使用 uni.getFileSystemManager 的文件管理能力默认不压缩App 平台通过 chooseMedia 选择媒体文件后默认没有压缩需自行调用 uni.compressImage 或 uni.compressVideo 来压缩尤其是视频时长较长或分辨率较高时应在上传前主动压缩以节省流量与存储。八、关联文档与资源API 文档docs/api/choose-media.md错误规范docs/err-spec.md示例页面src/pages/API/choose-media/choose-media.uvue插件实现src/uni_modules/uni-chooseMedia类型定义utssdk/interface.uts、默认值处理utssdk/protocol.uts、错误定义utssdk/unierror.uts、三端实现utssdk/app-{android,ios,harmony}/index.uts相关 API压缩图片 compress-image.md、压缩视频 compress-video.md、文件系统 get-file-system-manager.md、文件系统规格 file-system-spec.md赞分享示例工程前端移动开发跨平台【免费下载链接】uni-appA cross-platform framework using Vue.js项目地址https://gitcode.com/gh_mirrors/un/uni-app点击查看免费下载相关推荐uni-app x uni.openDocument 打开文档 API 完全指南参数、错误码与跨端底层实现uni app x uni.openDocument 打开文档 API 完全指南参数、错误码与跨端底层实现 uni.openDocument 是 uni ap示例工程前端移动开发跨平台uni-app x uni.scanCode 扫码 API 完全指南参数、跨端实现原理与实战示例uni app x uni.scanCode 扫码 API 完全指南参数、跨端实现原理与实战示例 uni app x 提供的 uni.scanCode 是调用示例工程前端移动开发跨平台uni-app x 跨端文件选择实战uni.chooseFile API 全参数解析与多平台实现原理uni app x 跨端文件选择实战uni.chooseFile API 全参数解析与多平台实现原理 uni.chooseFile 是 uni app / u示例工程前端移动开发跨平台上一篇终极指南深入解析Bear拦截库的LD_PRELOAD动态链接机制下一篇celld Worker Loader实验特性实战在Worker内动态启动沙箱isolate创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表