Found while testing the release APK (2026-09-22, Problem Log P-131): the Android app keeps its vault in the app’s private storage, and there is no way to get it out or back in from inside the app. Today the only route is adb exec-out run-as … tar -cf - files, which works on a debug build only — a release-signed build is not debuggable, so the same command cannot restore into it. Consequences:

  • Switching a phone from a debug-signed build to a release-signed one (which every user does once, when the signing key lands) destroys the vault: the install refuses, the user uninstalls, the private storage goes with it.
  • A user without adb cannot back up anything they typed on the phone, cannot move it to a desktop, and cannot recover it if the app is removed.
  • Notes typed on the phone are the least backed-up files in the project, and they are the ones a new user produces first.

What is wanted

  1. Export: File → Export vault… writes the whole vault as a single .zip (or .tar) through Android’s file picker (ACTION_CREATE_DOCUMENT), so it lands in Downloads, Drive, or wherever the user points it. No permissions needed — the picker grants the one URI.
  2. Import: File → Import vault… takes such an archive back (ACTION_OPEN_DOCUMENT), asking whether to merge or replace. A file that already exists is kept under name (imported).md rather than overwritten.
  3. Open a folder outside private storage (the bigger version): ACTION_OPEN_DOCUMENT_TREE gives the app a persistent URI for a real directory — the phone’s Documents, an SD card, a Syncthing folder — and Moonkale opens that as a source. Then the vault survives uninstalls by construction, and Syncthing or a git client can sync it. This is the proper fix; 1 and 2 are the cheap ones that unblock the signing switch.
  4. Single-file export for one note (share sheet) — small, and what someone actually wants when they typed a thought on the bus.

Notes on the implementation

  • The moonkale-project-fs source works on paths; a SAF (Storage Access Framework) tree is not a path. Either mirror the tree into private storage and write back on save, or add a source that speaks DocumentFile. The first is simpler and wrong in the long run; the second belongs next to Data Sources.
  • The JNI call surface is small (ACTION_* intents plus a result callback); dioxus-mobile exposes the Activity, so this does not need a fork (Android).
  • Until this exists, Install and packages/mobile/README.md tell users to copy anything important to a server (File → Connect to Server…) before the one-time reinstall.

Related: Android · Milestone 12 - Implementation Log (Connect to Server) · Problem Log P-131.