Skip to content

安卓文件访问(shared 模式)

系统概览

安卓端文件访问已废弃 Storage Access Framework(SAF,ACTION_OPEN_DOCUMENT_TREE / content:// 树 URI),改为 shared 模式:在 MANAGE_EXTERNAL_STORAGE 权限授权后,Go 后端用标准 os.* 直读 /sdcard/... 真实路径(如 /sdcard/Download/sdcard/MMD)。网页端则使用 FSA(File System Access API),二者是不同平台、不同机制,检索与讨论时务必区分——"SAF"仅指安卓,"FSA"仅指网页。

核心职责

  • fileaccess_android.go — 安卓文件读写全走 os.*;对 content:// 直接返回 ErrContentUriNotSupported(SAF 产物对后端已无意义)。
  • go-adapter.ts fsSelectDir: !isAndroidPlatform() — 能力矩阵声明安卓无目录选择能力,是唯一真相源。
  • library-setup.ts — 资源根/覆盖路径已按 fsSelectDir 守卫,安卓直接 androidDirNotSupported 返回,不调 SelectDir()
  • WailsBridge.java openDocumentTree + MainActivity.java SAF_TREE_REQUEST死代码,Go 侧无调用者;真正弹 SAF 的是 Wails v3 框架目录对话框在安卓后端出的 ACTION_OPEN_DOCUMENT_TREE

当前主流选择(决策演变)

阶段选择状态
早期(ADR-017 原案)Wails v3 SAF 目录选择(CanChooseDirectories❌ 已放弃(2026-07-22 修订)
当前安卓shared 模式MANAGE_EXTERNAL_STORAGE + os.ReadDir 直读 /sdcard主流、已落地
网页FSAgetFsaAuthState / reauthorizeFsaRoot,ADR-180/183)活跃、预期内
安卓 SAF 建树SelectDir() 在安卓被框架翻译成 ACTION_OPEN_DOCUMENT_TREE⚠️ 应避免(见下)

Google Play 政策提示MANAGE_EXTERNAL_STORAGE 受商店政策限制,仅 sideload 分发无影响(ADR-017)。上架需申请豁免或降级为 SAF/MediaStore。

已知缺陷(待 ADR-194 修复)

前端两处 SelectDir() 未做 fsSelectDir 守卫,在安卓(!isWebPlatform()→go-adapter→Wails v3 安卓对话框)会被强制翻译成 SAF 建树:

  • settings-downloads.ts:63 pickStagingDirDesktop()(line 344 !isWebPlatform() 分支命中安卓)
  • settings-resources.ts:473 SetDownloadWatchDirSelectDir()

ADR-194 落地时,安卓下载/监听目录应直接走系统 /sdcard/Download(shared 模式授权下 os.ReadDir 直读),两处 SelectDir() 加安卓分支或同 library-setupfsSelectDir 守卫;WailsBridge.openDocumentTree 死代码可一并清理。

与其他子系统关系

  • 能力矩阵 go-adapter.ts 是平台能力的唯一真相源;fsSelectDir 决定前端是否弹目录选择。
  • 网页 FSA 见 browser-adapter.ts + docs/web-data-origin-isolation.md,与安卓 shared 模式正交。

UI 入口

  • 菜单层级 / 入口函数 / 快捷键统一由 menu-map.md 机器生成(勿手改)。
  • 运行时动态生成的菜单项(renderCustom / slideRow 等)无法静态提取,缺口由本卡正文说明。

不变量

  • 安卓读文件必须走真实 /sdcard 路径,禁止引入 content:// 依赖(后端已 ErrContentUriNotSupported 兜底)。
  • fsSelectDir=false 时,任何 SelectDir() 调用在安卓都会落到框架 SAF,属缺陷而非预期

验证入口

  • 后端单测:internal/app/*_test.go(fileaccess_android 相关)
  • 前端契约:frontend/src/__tests__/bindings/app.contract.test.ts
  • 手动复现:安卓 apk 设下载暂存目录,确认是否弹 SAF(当前会弹 → 缺陷复现)