Dramivio项目文档下载文档包 ↗
2026.10.03 · 设计实施与自动回退修订本地实现与复审进展 · 真实服务尚未发布Markdown

视觉按最新原型,业务按已确认PRD。现有代码为满足设计而改造。执行见按设计实施与任务卡;当前代码与验证范围见消费者功能页。

原生离线下载接入

本页目录已接入iOS验证下一阶段

本轮为 O00 的原生队列与缓存实现,尚未开放 O01 消费者下载入口。网站不写视频文件;以下缓存写入的是手机 App 沙盒。原生队列中的账号、assetId 和有效期属于任务数据,不能代替源方离线许可。

已接入

Android 复用 react-native-video 6.19.2 所用的 Media3 1.8.0:DownloadManager、DefaultDownloadIndex、SimpleCache、DownloadHelper 和 DownloadService。没有自写下载器。MP4 直接进入下载队列,HLS 由成熟内核准备轨道与下载分段。队列、进度和缓存索引由 Media3 持久化;并发下载为 1。

播放器接收 dramivio-offline://asset/<UUID>,原生层再次检查当前账号、有效期和完成状态,然后使用禁止上游回源的 CacheDataSource。已有媒体请求隔离实现仍负责 Android 下载请求的 cookie、网站凭据、DNS、TLS 和每次重定向检查。任务快照不暴露来源 URL 或头。

每个账号使用独立原生缓存目录,每个已签发 asset 使用其现有 UUID 区分缓存键。同一个视频网址可以用于两个任务,删除一个任务不会删除另一个的内容。未完成文件没有播放 URI。切换账号暂停其他账号任务并隐藏其内容;显式 clearOwner 才删除文件和队列。

删除等待 Media3 索引移除,并验证实际目录已不存在。同一账号的并发清理共用一个任务和结果,避免旧轮询删除重新创建的目录。取消后的旧准备回调先比较当前任务,再操作任务表,不能移除同 ID 的新任务。账号清理进行中禁止重新配置同一账号,避免新任务写进即将删除的目录;该状态使用已有原生偏好存储,失败或中断后保留,重试完成后清除。

JS 通过可导入函数 createNativeOffline() 调用原生 Promise 方法:configureOwner、enqueue、list、pause、resume、remove、clearOwner、playback。请求和返回的账号归属须相符;有效期使用毫秒;只接受来源 Referer/User-Agent;旧 App 没有原生模块时明确失败,不能把操作当作成功。SDK 改动需要重新构建 App,不能只发 OTA。现有 Expo runtimeVersion 已升为 3;正式安装包与 OTA 未发布。

iOS

MP4 使用 URLSessionDownloadTask,HLS 使用 AVAssetDownloadURLSession。原生 manifest 原子保存账号、asset、系统任务映射和状态;完成后检查真实本地资产可播,HLS 还检查 isPlayableOffline。播放器解析相同 asset 别名并检查注册的本地路径,不能由 JS 指定任意离线目录文件。

本机仅有 CommandLineTools/macOS SDK,没有 Xcode/iPhoneOS SDK。已检查共享原生代码及本地 Foundation/AVFoundation 夹具,不能据此声称完整 iOS 构建、真机下载或后台恢复通过。

Apple 后台 URLSession 自动跟随重定向,不调用前置重定向回调;最终 URL 和 metrics 检查不能撤销已经发生的请求。HLS 所有分段、密钥的 cookie 隔离和 DNS 目的地址还需实际设备网络夹具。离线 asset 使用系统下载,不另起自写播放器规避这些限制。Apple 后台重定向行为。

验证

项目 当前证据 证据范围
App 210/210 测试,类型检查通过 JS、React、官方认证客户端既有回归与新增适配层
Android 15/15 原生集成测试通过 实际 Media3 队列、SQLite 索引、文件缓存;仅媒体网络替换为合成夹具
Android 媒体请求 既有真实 HTTPS JVM 夹具通过 实际 OkHttp 来源/网关隔离、HLS 子请求、重定向、DNS、TLS;不等同真机播放
iOS 77 项本地真实 SDK 夹具通过 账号/来源规则、真实合成 MP4、持久记录、路径与删除;不是 iOS 后台执行

Android 覆盖实际新构建合并清单中的服务注册;MP4 与 HLS 分段/AES 密钥缓存;播放读取零上游请求;冷启动索引与缓存恢复;暂停继续;换账号中断;打开缓存后换账号/过期拒绝读取;文件与目录删除;清理等待期间禁止同账号重新入队;同网址两资产删除隔离;并发账号清理合并;取消后的旧准备回调不阻断替代任务;IPv6 本地开发账号兼容。AES 夹具是合成测试密钥,不是 DRM 离线许可证。Android 的 ready 表示 Media3 下载字节完成;独立 HTML200 负夹具证明这不等同解码可播,真实来源能力、解码与受保护媒体仍须按 O00 验证。

测试可通过普通函数调用:

const { runOfflineNativeTests } = require('./tests/offline-native.cjs');
const result = runOfflineNativeTests({ javaHome, androidHome, logPath });

遵循 Robolectric 官方配置;下载与离线读取采用 Media3 官方下载组件。安装的 1.8.0 API 已实际编译,不照搬其他版本示例。

下一阶段

先复用现有额度事务、标准渠道与实际媒体能力,完成离线 preview/order/asset 签发和账号设备绑定,再接详情页多选、确认、队列及缓存列表。签发必须使用可离线的真实来源能力;受保护媒体需要源方持久许可,不能把在线播放地址包装成许可证。

尚未完成:实际源方离线许可与设备证明;O01 后端签发及额度联动;消费者 UI 与账号生命周期对原生队列的接线;iOS 宿主 AppDelegate 后台事件转发;完整 Android/iOS 安装和真机飞行模式、seek、后台/强退、空间不足、字幕与系统逐出验收。下载失败后的转发与解码能力须沿用按需路线单独验证。消费者入口继续返回 offline_authorization_required,避免旧 viewer URL 被当作授权缓存。

本轮未提交或推送仓库,未发布真实 API、App 或 OTA。在线更新仅为静态文档与已有交互设计。