更新记录

1.0.0(2026-08-12)

  • 首发 Android、iOS 原生媒体选择能力。
  • Android 支持免权限系统选择器,以及宿主显式启用的自定义全屏相册模式。
  • 支持照片和视频单选、多选、混选、预览、原图导出和默认选中。
  • 支持主题色、深色模式、3/4/5 列布局及界面文案配置。
  • Android 自定义相册申请权限前展示用途说明,拒绝后可降级到系统选择器。
  • Android 拍照调用系统相机,不申请相机权限。
  • iOS 支持照片选择和拍照,并内置隐私清单。

平台兼容性

uni-app(4.25)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
× × × 6.0 13 ×
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
× × × × × × × × × × × ×

其他

多语言 暗黑模式 宽屏模式
× ×

原生可定制相册/媒体选择器

适用于 uni-app App 的 Android/iOS 原生媒体选择。Android 默认使用免权限的系统选择器,并可由符合宽泛相册权限政策的宿主显式启用自定义全屏相册。插件只返回用户确认选择的本地文件,不负责上传。

快速接入流程

① 导入整个插件目录到 uni_modules(目录名必须为 xss-nativealbum)
                 ↓
② 确认 uni_modules/xss-nativealbum 目录完整
                 ↓
③ 重新制作自定义调试基座,或进行 App 云打包
                 ↓
④ 复制下方最小示例,调用 openNativeAlbumPicker
                 ↓
⑤ 使用自定义基座运行到 Android/iOS 真机
                 ↓
⑥ 选择成功后,校验 path 并上传或保存文件

导入或升级插件后必须重新制作基座,普通标准基座无法运行本插件。

一、支持范围

  • HBuilderX 4.25 或更高版本,建议使用最新稳定版。
  • Android 6.0(API 23)或更高版本。
  • iOS 13.0 或更高版本。
  • 支持 uni-app App 的 Vue 2、Vue 3 页面。
  • 不支持 H5、小程序、HarmonyOS、nvue 和 uni-app x。

二、安装与运行

请按下面顺序操作,缺少第 2、3 步会出现“UTS 插件编译失败,无法使用”。

  1. 从插件市场导入,或把整个 xss-nativealbum 文件夹复制到项目的 uni_modules 目录。不要只复制 utssdk。插件 ID 与目录名均为 xss-nativealbum(无连字符),不要写成 xss-native-album
  2. 若手动解压发布包:zip 内可能没有外层目录。请先创建 uni_modules/xss-nativealbum,再把解压出的 package.jsonutssdkreadme.md 等内容完整放入该目录。
  3. 确认 uni_modules/xss-nativealbum 目录完整;当前版本没有 npm、Maven 或 CocoaPods 第三方依赖。
  4. 重新制作包含本插件的自定义调试基座,或直接进行 App 云打包。普通标准基座不包含本插件的原生代码。
  5. 使用自定义基座运行到 Android/iOS 真机测试,不要在浏览器中测试。

插件不包含 npm、Maven 或 CocoaPods 第三方依赖,不包含业务密钥、人脸/年龄识别 SDK 或模型文件。升级插件后应清理旧构建缓存,再重新制作基座。

iOS 本地编译需要 macOS 和完整 Xcode;没有本地环境可使用 HBuilderX 云打包。每次升级插件或修改原生代码、依赖、资源后,都要重新制作基座。

三、最小接入示例

下面的写法可用于 Vue 2、Vue 3 的 Options API 页面:

<template>
    <button @click="chooseMedia">选择照片或视频</button>
</template>

<script>
import {
    openNativeAlbumPicker,
    isNativeAlbumPickerSupported,
    isNativeAlbumTempFileAvailable
} from '@/uni_modules/xss-nativealbum'

export default {
    methods: {
        chooseMedia() {
            if (!isNativeAlbumPickerSupported()) {
                uni.showToast({ title: '请在 App 真机运行', icon: 'none' })
                return
            }

            openNativeAlbumPicker({
                maxCount: 9,
                // Android 默认 auto:未授权时使用免权限的系统选择器
                success: ({ tempFiles, quality }) => {
                    console.log('选中的文件', tempFiles, quality)
                },
                fail: (error) => {
                    console.log('打开失败', error.errCode, error.errMsg)
                },
                cancel: () => {
                    console.log('用户取消')
                }
            })
        }
    }
}
</script>

四、返回文件与上传

成功回调的结构:

{
    tempFiles: Array<{
        id: string          // 系统媒体资源 ID,可用于下次默认选中
        path: string        // file:// 本地临时 URL,业务通常使用这个字段
        absolutePath: string
        type: string        // image | video
        mimeType: string
        duration: number    // 毫秒,图片为 0
        size: number        // 字节
    }>
    tempFilePaths: Array<string> // 与 tempFiles[].path 一致
    quality: string              // hd | original
}

插件返回成功前已确认文件存在、可读且大小大于 0。上传前建议再次即时校验:

const file = tempFiles[0]
if (!isNativeAlbumTempFileAvailable(file.path)) {
    uni.showToast({ title: '文件已失效,请重新选择', icon: 'none' })
    return
}

uni.uploadFile({
    url: 'https://你的服务器/upload',
    filePath: file.path,
    name: 'file', // 必须与服务端 multipart 文件字段名一致
    success: (result) => console.log('上传完成', result),
    fail: (error) => console.log('上传失败', error)
})

多选时对 tempFiles 逐个上传即可。path 是 App 临时文件,不应作为永久地址保存;请在选择成功后及时上传,或复制到业务自己的持久目录。上传最终是否成功还取决于网络、服务端接口和鉴权。

如果在电脑上的 HBuilderX 控制台点击手机路径时显示“文件不可用”,通常只是电脑不能访问手机 App 沙盒,不代表手机里的文件失效。请以 isNativeAlbumTempFileAvailable(path) 或手机 App 内的实际使用结果为准。

再次打开需要恢复选中状态时,把上次的 tempFiles.map(item => item.id) 传给 defaultSelectedIds,不要传临时路径。用户删除或重新导入系统媒体后,旧 ID 可能失效。

五、预览与选择规则

  • 点击网格中的照片或视频:从当前资源开始,左右滑动查看当前相册的其他资源。
  • 点击底部“预览”:从第一项已选资源开始,左右滑动查看所有已选资源;顶部显示当前位置和选中状态。
  • showPreview: false 时,点击网格资源会直接选择,不打开预览。
  • mediaType: 'image' 只显示照片;video 只显示视频并隐藏拍照入口;all 显示全部分类。
  • allowMixed: false 时,照片和视频不能同时选中。
  • 默认选中标记的可点击区域大于图标本身,点击标记用于选择,点击缩略图用于预览。

六、配置参数

参数 默认值 说明
title 选择照片或视频 顶部辅助标题和无障碍说明
themeColor #FF7D37 主题色
backgroundColor / textColor 跟随模式 页面背景色、主要文字色;自动深色时建议不传
darkMode auto autolightdark
columns 4 每行列数,自动限制为 3–5
selectionMode multiple singlemultiple
maxCount 9 多选上限;单选固定为 1
defaultSelectedIds [] 上次返回的资源 ID 数组
mediaType all allimagevideo
androidPickerMode auto Android 选择模式:autosystemcustom,详见下方权限说明
allowMixed true 是否允许图片和视频混选
showAlbumSwitch true 是否允许切换相册
showCamera true 是否显示拍照入口
showPreview true 是否允许点击缩略图预览
showOriginalOption true 是否显示高清/原图选项
defaultQuality hd hdoriginal
showVideoDuration true 是否显示视频时长
selectionIndicator number numberchecknone
confirmText / previewText / cancelText 见名称 完成、预览、取消文案
emptyTitle / emptyDescription 内置中文 空状态标题和说明
cameraText 拍摄 拍照入口文案
mediaPermissionTitle 相册权限使用说明 Android 申请相册权限时展示的用途说明标题
mediaPermissionMessage 内置用途说明 Android 申请相册权限时展示的具体数据、功能和用途;建议改成宿主 App 的真实业务表述
permissionContinueText / permissionCancelText 继续 / 取消 Android 权限用途说明按钮文案
maxSelectedText 已达到最大选择数量 达到上限时提示
mixedNotAllowedText 图片和视频不能同时选择 禁止混选时提示

回调与辅助 API:

API/回调 说明
isNativeAlbumPickerSupported() 当前是否具备打开原生相册的 App 环境
isNativeAlbumTempFileAvailable(path) 文件使用或上传前确认仍存在、可读且非空
success(result) 全部选中文件导出并校验成功
fail(error) 打开、导出或返回结果解析失败
cancel() 用户主动关闭且未完成选择
complete(value) 成功、失败或取消后都会调用一次

完整类型定义以 utssdk/interface.uts 为准。

七、权限与隐私

  • Android 插件清单不强制合并媒体读取权限,安装插件本身不会让宿主 App 自动携带宽泛相册权限。
  • Android auto(默认):若宿主已有对应相册授权则使用自定义相册;否则直接使用免权限的系统选择器,不主动申请宽泛权限。
  • Android system:始终使用系统选择器,不申请相册读取权限。界面样式、预选和自定义拍照入口等参数由系统决定或不生效。
  • Android custom:仅当宿主已在自己的 manifest.json 中完整声明当前媒体类型所需权限时,才会主动申请并进入自定义相册;声明不完整时自动回退到系统选择器。
  • custom 模式尚未授权时,会先展示可取消的权限用途说明;用户点击“继续”后才调用系统权限,并在系统权限框显示期间保留原生顶部用途提示。
  • Android 拍照入口调用系统相机 App(ACTION_IMAGE_CAPTURE),插件不声明、不申请 Android 相机权限,减少宿主 App 的敏感权限和审核披露项。
  • iOS 照片权限用于展示并选择媒体;相机权限仅在用户主动点击拍照入口后申请。用途文案由插件 Info.plist 声明。
  • iOS 插件内置 PrivacyInfo.xcprivacy:声明不跟踪、不收集数据,并为清理 App 容器内过期临时文件所使用的文件时间戳 API 声明 C617.1
  • 只有用户点击“完成”确认的资源才会导出到 App 临时缓存。插件自身没有上传接口、账号、广告、支付或埋点,不会把媒体发送给插件作者。
  • 演示工程已关闭 uni统计;接入方业务是否上传、保存或分享文件由自己的代码决定,并应在应用隐私政策中说明用途、接收方、保存期限和删除方式。
  • 插件不包含人脸或年龄识别功能、SDK及模型,不会分析媒体中的人物身份或年龄。

Android 自定义相册模式可由宿主按需声明的权限及实际用途:

权限 适用版本 用途
READ_EXTERNAL_STORAGE Android 12 及以下(建议设置 maxSdkVersion=32 读取并展示照片和视频
READ_MEDIA_IMAGES Android 13 及以上 读取并展示照片
READ_MEDIA_VIDEO Android 13 及以上 读取并展示视频
READ_MEDIA_VISUAL_USER_SELECTED Android 14 及以上 读取用户明确选择允许访问的照片和视频

插件清单没有媒体读取权限,也没有 Android CAMERAWRITE_EXTERNAL_STORAGE、定位、通讯录、设备标识、广告或后台权限。

Android 两种接入方式

普通发布动态、上传头像等偶发选择场景,保持默认即可:

openNativeAlbumPicker({
    androidPickerMode: 'system', // 或不传,使用默认 auto
    mediaType: 'image',
    maxCount: 9
})

只有“大范围浏览整个相册”是 App 核心、持续功能,且目标应用市场政策允许时,才建议使用自定义模式:

openNativeAlbumPicker({
    androidPickerMode: 'custom',
    mediaType: 'all',
    mediaPermissionTitle: '照片和视频权限使用说明',
    mediaPermissionMessage: '用于在发布动态时浏览并选择您指定的照片或视频;未确认选择的内容不会上传。'
})

并在宿主 manifest.jsonapp-plus.distribute.android 节点中按实际 mediaType 声明权限。下面是 all 的完整示例;仅选照片或仅选视频时可去掉不需要的 Android 13+ 权限:

{
    "app-plus": {
        "distribute": {
            "android": {
                "permissions": [
                    "<uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\" android:maxSdkVersion=\"32\"/>",
                    "<uses-permission android:name=\"android.permission.READ_MEDIA_IMAGES\"/>",
                    "<uses-permission android:name=\"android.permission.READ_MEDIA_VIDEO\"/>",
                    "<uses-permission android:name=\"android.permission.READ_MEDIA_VISUAL_USER_SELECTED\"/>"
                ]
            }
        }
    }
}

演示工程为了展示自定义相册,已经在宿主 manifest.json 中主动声明上述权限并传入 androidPickerMode: 'custom';这不是插件对所有接入方的默认行为。

宿主 App 上架前必做

插件只能保证自身的权限调用流程,最终上架主体仍是接入插件的宿主 App。发布前请逐项确认:

  1. mediaPermissionTitlemediaPermissionMessage 改成宿主 App 的真实功能和用途,不要使用与业务不符的通用文案。
  2. 在宿主 App 隐私政策和应用市场权限清单中写明照片/视频的访问场景、使用目的、处理方式、保存期限和是否上传或共享;内容必须与实际业务一致。
  3. Android 13 及以上可能出现照片、视频或“仅选择的照片和视频”等系统授权选项;需要分别测试允许、部分允许、拒绝和再次授权。
  4. 若宿主同时接入其他 SDK 或插件并申请相同权限,应统一核对全部权限用途说明,避免重复提示或说明冲突。
  5. 使用正式包名、签名和目标 SDK,在华为、小米、OPPO、vivo 及计划发布的其他渠道真机复测。应用市场规则可能调整,提交前应复核目标渠道的最新要求。
  6. 若宿主只是偶尔让用户选择少量照片或视频,必须使用 auto / system 并避免声明宽泛相册权限;custom 仅适用于相册浏览和多选属于核心、持续使用场景的应用。Google Play 等渠道可能要求证明该权限与核心功能直接相关。
  7. 宿主应在用户同意其隐私政策后,且仅在用户主动点击媒体选择功能时调用插件;不要在 App 启动、插件导入或页面初始化时主动打开相册。

用户拒绝 Android 自定义相册的读取权限后,插件会提供“系统相册”降级入口,并把用户在系统选择器中确认的文件按相同的 success 结果返回;宿主无需另写结果解析逻辑。

八、常见问题

提示“UTS 插件编译失败,无法使用”

确认插件目录完整,然后清理旧构建缓存并重新制作自定义基座。不要继续使用导入或更新插件前制作的旧基座。

找不到模块 / 导入路径报错

检查目录和 import 是否都是 xss-nativealbum(无连字符)。正确路径为 @/uni_modules/xss-nativealbum,不要写成 xss-native-album。若手动解压时建错了文件夹名,请改名为 xss-nativealbum 后再编译。

提示“请在 App 真机运行”

当前正在 H5、小程序、浏览器或不包含插件的普通基座中运行。请使用自定义基座或打包 App 真机测试。

错误码

错误码 含义
9201001 相册已经打开,请避免快速连点
9201002 当前页面无法取得原生容器
9201003 原生相册打开或文件导出失败
9201004 返回结果解析失败
9201005 启动原生页面失败
9201090 当前状态建议降级到系统相册选择器

隐私、权限声明

1. 本插件需要申请的系统权限列表:

Android:默认使用系统照片选择器,不申请相册读取权限;仅当宿主 App 显式启用自定义相册模式时,按系统版本和媒体类型申请 READ_EXTERNAL_STORAGE、READ_MEDIA_IMAGES、READ_MEDIA_VIDEO、READ_MEDIA_VISUAL_USER_SELECTED。Android 拍照调用系统相机,不申请 CAMERA 权限。 iOS:浏览、选择照片或视频时申请照片读取权限;仅在用户主动点击拍照入口时申请相机权限。

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集、不上传、不共享用户数据,不连接插件作者服务器,也不包含第三方统计、广告或数据采集 SDK。 插件仅在设备本地读取用户授权访问的照片和视频,并将用户确认选择的文件复制到宿主 App 的临时目录后返回给宿主业务代码。未确认选择的媒体不会交给宿主使用。宿主 App 后续是否上传、保存或分享文件,由接入方业务决定,不属于本插件的数据处理行为。

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

无。本插件不包含广告、广告 SDK、推广弹窗或广告数据采集功能。

暂无用户评论。