更新记录
0.2.0(2026-09-25) 下载此版本
- 新增按
shareId管理的多记录本地收件箱,默认保留最近 20 条,最多可配置 100 条。 - 新增
SharedRecord、SharedItemFailure、接收状态和平台能力数据结构。 - 新增完整记录监听、历史读取、单条确认、全部清理、主动修剪、能力查询和状态查询接口。
- 新增附件数量、单文件大小、单次总大小、MIME 类型白名单和保留时长配置。
- Android 与 iOS 支持完整、部分成功和失败三种记录状态,并返回逐项失败原因。
- Android Cache 与 iOS App Group 均加入历史淘汰、过期清理和孤立附件清理。
- 保留 0.1.x 的四个接口;旧读取与监听映射到最新一条记录,旧清理接口映射为清空全部记录。
- 示例页升级为白色中文收件箱界面,可查看状态、历史、失败项目,并按条确认清理。
- 同步更新插件版本、iOS Extension 版本和 0.2.0 接入、存储、测试及验证文档。
- 本次按开发安排只完成编码与文档收口,未启动模拟器或执行最新页面、Extension 的运行调试。
0.1.0(2026-08-24) 下载此版本
- 实现 Android
ACTION_SEND/ACTION_SEND_MULTIPLE系统分享入口。 - 支持文字、链接、单图、多图和普通文件,附件复制到应用私有缓存。
- 完成冷启动、运行中回调、最近结果持久化、重复回放与显式清理。
- 完成 iOS App Group 宿主桥接和 Share Extension 可编译源码模板。
- 新增交互式收件箱示例页、API 文档、iOS 集成指南与双端测试清单。
- 通过 Android、iOS 插件模块及 uni-app x 整项目编译。
平台兼容性
uni-app x(4.0)
| Chrome | Safari | Android | Android插件版本 | iOS | iOS插件版本 | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|---|---|
| × | × | 5.0 | 0.2.0 | 12 | 0.2.0 | × | × |
其他
| 多语言 | 暗黑模式 | 宽屏模式 | 蒸汽模式 |
|---|---|---|---|
| × | × | × | √ |
接收系统分享文字图片与文件
xs-share-receiver 是面向 uni-app x App 的系统分享接收 UTS 插件。它把 Android 系统分享 Intent 与 iOS Share Extension 统一为本地收件记录,可接收其他应用主动分享的文字、网页链接、单图、多图和普通文件。
当前版本:0.2.0
0.2.0 源码已完成。当前版本新增历史、失败明细、限制、确认和清理能力;本轮按项目安排未启动模拟器,也未完成 0.2.0 最新代码的真机端到端验收。Android 必须使用包含插件原生清单的自定义基座或正式安装包;iOS 必须使用自己的 Bundle ID、App Group 和描述文件构建签名 Share Extension。
这个插件解决什么问题
普通页面代码不能直接把 Android 分享 Intent 和 iOS NSItemProvider 当作稳定业务数据使用。来源 URI 可能只有短暂读取权限,系统分享入口也属于原生安装包能力。本插件负责:
- 把应用注册到系统分享面板。
- 在临时授权有效时读取并复制附件。
- 把双端内容统一为
SharedRecord。 - 保存多条本地收件记录并回放最新一条。
- 记录每个未接收附件的失败原因。
- 按业务策略限制数量、大小、类型和保留时间。
- 在业务处理完成后按
shareId确认并清理。
插件不负责“从本应用分享出去”,也不包含上传、云同步、文件预览、解压、OCR、病毒扫描或业务入库。
适用场景
- 从微信、浏览器、相册或文件管理器把内容送入业务 App。
- 制作“保存到应用”“发送到工作台”“导入到项目”等系统入口。
- 接收图片、合同、报表、音视频或其他业务附件。
- 将临时 URI 转换为后续可读取的本地文件路径。
- 给离线采集、资料归档和待处理收件箱提供入口层。
0.2.0 新能力
| 能力 | 说明 |
|---|---|
| 多记录收件箱 | 默认保留最近 20 条,可配置 1~100 条 |
| 唯一分享编号 | 每次分享生成 shareId,用于业务幂等和确认 |
| 结果完整度 | 返回 complete、partial 或 failed |
| 失败明细 | 返回失败项索引、名称、MIME 和稳定原因码 |
| 可配置限制 | 历史数、附件数、单文件大小、单次总大小、类型白名单、保留时长 |
| 消费确认 | 可按 shareId 移除记录并选择是否删除附件 |
| 自动修剪 | 清理过期、超容量记录和孤立附件 |
| 运行状态 | 查询平台就绪、监听状态、记录数、文件数和占用字节 |
| 能力查询 | 查询当前平台公开能力和最低系统版本 |
| 向后兼容 | 保留 0.1.x 的读取、监听、停止和清理接口 |
平台支持
| 项目 | Android | iOS |
|---|---|---|
| 最低版本 | Android 5.0 / API 21 | iOS 12.0 |
| uni-app x | 支持 | 支持 |
| 网页、小程序、鸿蒙 | 不支持 | 不支持 |
| 系统入口 | 透明接收 Activity | 独立 Share Extension |
| 附件位置 | 应用 Cache | App Group 容器 |
| 记录索引 | 应用私有偏好 | App Group 共享偏好 |
| 拉起主应用 | 接收后尝试回到主应用 | 系统不保证自动拉起主应用 |
| 来源应用 | 尽力返回包名 | 当前返回 null |
| 网络与公共存储权限 | 不需要 | 不需要照片库权限 |
开发环境要求:HBuilderX 5.0 及以上、uni-app x 4.0 及以上。
使用前必须了解
- 标准基座不能验证新增的 Android Activity 或 iOS Extension。
- iOS
.appex不能跨开发者账号通用分发,必须由集成方签名。 - 插件路径是临时接收区,不是业务永久文件库。
- 启动监听会回放最新记录,业务要用
shareId幂等。 - 限制项会产生失败明细,不应只检查
files.length。 - iOS 分享完成后通常需要用户手动返回主应用。
安装与导入
将本目录放到业务工程:
uni_modules/xs-share-receiver/
推荐导入:
import {
acknowledgeSharedRecord,
clearSharedRecords,
configureShareReceiver,
getSharedRecords,
getShareReceiverCapabilities,
getShareReceiverStatus,
pruneSharedRecords,
ShareReceiverStatus,
SharedRecord,
startShareRecordReceiver,
stopShareReceiver
} from '@/uni_modules/xs-share-receiver'
不要从 utssdk 或平台子目录导入内部实现。
推荐接入示例
export default {
data() {
return {
records: [] as SharedRecord[],
ready: false,
message: ''
}
},
onLoad() {
configureShareReceiver({
maxHistoryCount: 20,
maxFileCount: 32,
maxFileSizeBytes: 104857600,
maxTotalSizeBytes: 314572800,
allowedMimeTypes: [] as string[],
retentionHours: 72
})
pruneSharedRecords()
this.reloadInbox()
startShareRecordReceiver((record : SharedRecord) => {
this.reloadInbox()
})
},
onUnload() {
stopShareReceiver()
},
methods: {
reloadInbox() {
this.records = getSharedRecords(20)
const status : ShareReceiverStatus = getShareReceiverStatus()
this.ready = status.ready
this.message = status.message ?? ''
},
finishRecord(record : SharedRecord) {
// 先完成业务复制、上传或入库,再删除插件附件。
const removed = acknowledgeSharedRecord(record.shareId, true)
if (removed) this.reloadInbox()
},
clearInbox() {
clearSharedRecords(true)
this.reloadInbox()
}
}
}
Android 进程刚启动时建议先调用 configureShareReceiver(),让原生层取得应用上下文,再读取状态和历史。
接收流程
Android
来源应用选择分享
↓
系统匹配接收 Activity
↓
读取文字与临时授权 URI
↓
应用接收策略并复制附件到 Cache
↓
保存 SharedRecord 历史
↓
回到主应用并通知当前监听者
iOS
来源应用打开系统分享面板
↓
用户选择已签名 Share Extension
↓
扩展读取 Provider、校验并复制附件
↓
记录写入 App Group
↓
用户打开或返回主应用
↓
宿主桥接检查变化并通知当前监听者
接口总览
| 接口 | 说明 |
|---|---|
configureShareReceiver(options) |
保存接收和保留策略 |
getSharedRecords(limit) |
倒序读取最多指定条数 |
getLatestSharedRecord() |
读取最新一条,不消费 |
startShareRecordReceiver(callback) |
监听完整记录并回放最新记录 |
stopShareReceiver() |
停止当前回调,保留数据 |
acknowledgeSharedRecord(shareId, deleteFiles) |
确认并移除指定记录 |
clearSharedRecords(deleteFiles) |
清空全部记录,返回移除数量 |
pruneSharedRecords() |
应用过期、数量和孤立文件清理 |
getShareReceiverCapabilities() |
查询平台能力 |
getShareReceiverStatus() |
查询就绪、监听和缓存状态 |
完整签名见 ../../docs/API.md。
记录结构
type SharedRecord = {
shareId: string
text: string | null
url: string | null
files: SharedFile[]
sourceApp: string | null
receivedAt: number
status: string
requestedCount: number
successCount: number
failedCount: number
failures: SharedItemFailure[]
}
典型部分成功结果:
{
"shareId": "4c468d19-8db1-4eec-a76d-5cb874c83620",
"text": "资料请查收",
"url": null,
"files": [
{
"name": "photo.jpg",
"path": "/private/path/xs-share-receiver/uuid-photo.jpg",
"mimeType": "image/jpeg",
"size": 286720
}
],
"sourceApp": null,
"receivedAt": 1788710400000,
"status": "partial",
"requestedCount": 2,
"successCount": 1,
"failedCount": 1,
"failures": [
{
"index": 1,
"name": "video.mp4",
"mimeType": "video/mp4",
"reason": "FILE_TOO_LARGE"
}
]
}
示例路径只说明数据结构,不能硬编码或跨设备复用。
接收策略
type ShareReceiverOptions = {
maxHistoryCount: number
maxFileCount: number
maxFileSizeBytes: number
maxTotalSizeBytes: number
allowedMimeTypes: string[]
retentionHours: number
}
| 参数 | 默认值 | 说明 |
|---|---|---|
maxHistoryCount |
20 | 配置范围 1~100 |
maxFileCount |
32 | 配置范围 1~32 |
maxFileSizeBytes |
0 | 0 表示不设置插件级限制 |
maxTotalSizeBytes |
0 | 0 表示不设置插件级限制 |
allowedMimeTypes |
空数组 | 空数组允许所有类型 |
retentionHours |
0 | 0 表示不过期,最大 8760 小时 |
白名单支持 image/* 这类类型族,也支持 application/pdf 这类精确值。限制只减少插件愿意复制的内容,不代替业务端的文件安全检查。
失败原因
| 原因码 | 建议提示 |
|---|---|
FILE_COUNT_EXCEEDED |
超过单次附件数量上限 |
MIME_NOT_ALLOWED |
文件类型不在允许范围 |
FILE_TOO_LARGE |
文件超过单文件大小限制 |
TOTAL_SIZE_EXCEEDED |
本次附件总量超过限制 |
READ_PERMISSION_DENIED |
来源未授予有效读取权限 |
SOURCE_UNAVAILABLE |
来源内容已不可读取 |
CACHE_DIRECTORY_UNAVAILABLE |
无法创建插件缓存目录 |
COPY_FAILED |
复制文件时发生其他错误 |
原因码用于程序判断;用户提示应根据业务语境翻译,不建议直接展示英文码。
回放、幂等与监听
- 只存在一个活动监听者;新旧监听接口会相互替换。
- 开始监听时会回放最新一条现有记录。
- 页面重建后可能再次收到同一条记录。
- 使用
shareId做幂等,而不是文件名、接收时间或来源应用。 stopShareReceiver()不影响系统继续写入本地收件箱。- 停止期间收到的内容,可在下次读取历史或开始监听时取得。
确认与清理
推荐业务顺序:
- 收到
SharedRecord。 - 检查状态和
failures,决定是否接受部分成功。 - 校验文件是否存在、大小和类型是否符合业务要求。
- 复制到业务持久目录,或完成上传与数据库提交。
- 使用同一个
shareId防止重复入库。 - 成功后调用
acknowledgeSharedRecord(shareId, true)。
deleteFiles = false 只是在当前调用中不删除附件。记录被移除后,这些文件失去引用,未来 pruneSharedRecords() 仍可能把它们视为孤立文件删除。需要长期保存必须先复制到插件目录之外。
Android 接入
插件 Manifest 已注册:
android.intent.action.SENDandroid.intent.action.SEND_MULTIPLE- MIME
*/*
必须使用重新制作的自定义基座或正式安装包。若分享面板没有入口,先检查最终合并 Manifest 是否包含 ShareReceiverActivity,再检查来源应用实际提供的 Intent 类型。
Android 会读取 EXTRA_TEXT、EXTRA_STREAM、ClipData 和文件型 data URI,对 URI 去重并在临时授权有效期间复制。透明 Activity 完成后会尝试通过宿主启动 Intent 返回主应用。厂商后台限制和任务栈差异需要真机验证。
iOS 接入
iOS 需要独立签名 Share Extension。发布者必须:
- 创建主应用和 Extension 两个 Bundle ID。
- 给两个 App ID 分配同一个 App Group。
- 重新生成两份包含 App Group 的描述文件。
- 用仓库 Swift 源码构建并签名
.appex。 - 将产物放入
utssdk/app-ios/Plugins/。 - 在业务工程配置
nativeResources/ios/ios-extension.json。 - 检查最终
.app/PlugIns/、嵌套签名和两端 entitlement。
完整步骤见 ios-extension-source/README.md 和 ../../docs/IOS_EXTENSION.md。
缓存与保留
| 场景 | 0.2.0 行为 |
|---|---|
| 新分享写入 | 追加到历史顶部,并按策略修剪 |
| 超过历史上限 | 移除最旧记录并删除其插件附件 |
| 超过保留时间 | 修剪时移除过期记录和附件 |
| 按条确认 | 移除指定记录,可同时删除附件 |
| 清空全部 | 移除全部记录,可同时删除附件 |
| 孤立文件 | 主动修剪时删除不被任何记录引用的插件附件 |
| 系统回收 | Android Cache 仍可能由系统主动回收 |
| 应用卸载 | 应用私有数据通常随应用删除 |
历史记录不等于永久归档。业务仍需对重要文件建立自己的持久化、校验、备份和删除流程。
0.1.x 升级说明
以下接口继续可用:
getInitialSharedPayload()
startShareReceiver(callback)
stopShareReceiver()
clearSharedPayload()
兼容读取和监听映射到最新一条记录。旧结构看不到 shareId、状态和失败明细。为了避免历史残留,0.2.0 的 clearSharedPayload() 会清空全部记录及插件附件。需要按条消费的新项目应迁移到 SharedRecord 接口。
常见问题
为什么监听一启动就收到已有内容?
这是冷启动回放。使用 shareId 判断业务是否已经处理;不要依赖回调次数。
为什么记录状态是“部分接收”?
本次至少有一个附件成功,也至少有一个失败。查看 failures 决定继续处理成功项,还是要求用户重新分享。
为什么记录状态是“接收失败”但仍保留?
0.2.0 会保存失败记录,便于页面给出明确原因和后续排错,而不是静默丢失。
为什么 sourceApp 为空?
来源标识不是稳定系统承诺。Android 仅在系统提供 calling package 或 referrer 时返回;iOS 当前为 null。它不能作为可信身份或权限依据。
路径能永久保存吗?
不能。Android Cache 可能被系统回收,iOS App Group 也受插件保留规则管理。需要长期使用时先复制到业务目录。
插件会上传内容吗?
不会。插件不联网、不上传、不内置广告、统计、账号或云服务。集成应用自己的网络行为需要单独说明。
更多排错见 ../../docs/FAQ.md。
当前限制
- 单次候选附件硬上限为 32 个。
- 不提供字节级复制进度、单项取消和超时接口。
- Android
sourceApp不保证存在,iOS 当前固定为null。 - iOS 分享完成后不保证自动拉起主应用。
- iOS
.appex必须使用集成应用自己的签名资产制作。 - 不提供分享发送、业务归档、文件预览、上传、同步、扫描或加密存储。
- 0.2.0 最新源码尚未完成当前轮次的模拟器、自定义基座和真机回归。
发布前验证
至少覆盖:
- Android 和 iOS 的冷启动、后台、前台路径。
- 文字、链接、中文、换行和表情符号。
- 单图、多图、PDF、文本、音频、视频和无扩展名文件。
- 1、配置上限和 33 个候选附件。
- 单文件大小、单次总量和 MIME 白名单边界。
- 完整、部分和失败三种状态及每个原因码。
- 连续分享、回放幂等、按条确认、全部清理和过期修剪。
- 不同 Android 厂商系统和至少一台 iPhone 真机。
完整矩阵见 ../../docs/TESTING.md,证据边界见 ../../docs/VERIFICATION.md。
隐私与安全
- 只处理用户通过系统分享面板主动发送给应用的内容。
- 插件本身不联网、不上传、不收集账号和设备标识。
- Android 不申请公共存储权限,iOS 不因分享接收申请照片库权限。
- 文件名、MIME 和来源应用都属于不可信元数据,不能直接用于鉴权或命令拼接。
- 插件限制不是内容安全检查;调用方仍应做扩展名、MIME、文件头、容量、恶意内容和访问控制校验。
- 调用方应在隐私政策中说明内容用途、保存期限、上传对象和删除方式。
插件不联网只代表插件实现本身不发送数据,不代表集成它的业务应用一定不上传。
更多文档
| 文档 | 内容 |
|---|---|
../../docs/API.md |
完整接口和字段语义 |
../../docs/IOS_EXTENSION.md |
iOS 标识、App Group、签名、打包和排错 |
../../docs/STORAGE_AND_PRIVACY.md |
存储生命周期、清理和隐私责任 |
../../docs/FAQ.md |
接入问题与故障排查 |
../../docs/TESTING.md |
双端 0.2.0 验收矩阵 |
../../docs/VERIFICATION.md |
已完成和待完成的验证证据 |

收藏人数:
下载插件并导入HBuilder
下载示例项目ZIP
赞赏(0)
下载 5
赞赏 0
下载 12660401
赞赏 1955
赞赏
京公网安备:11010802035340号