Stash v0.9.31 — Backup/restore + offline-playback fix
Backup and restore (PR #70 — @winstriker)
- Settings → Backup card with Export / Import buttons. Bundles the
Room database + every DataStore preference file into a single
ZIP archive. - Export uses a wal_checkpoint(FULL) first so the .db file is
consistent before zipping. - Import validates a manifest entry (dbSchemaVersion, exportTimestamp,
appVersionName) before touching any state, refuses ZIPs that aren't
Stash backups, and refuses backups from a newer app version. - Zip Slip guard rejects entries that would escape the target dirs.
- After restore, if the backup had an external SAF library folder,
prompts the user to re-grant tree permission, then restarts the
app process so all singletons re-init against the restored data. - Spotify / YouTube cookies are encrypted with a device-bound master
key — cross-device restore requires re-auth to those services.
Offline-playback regression fix (closes #75 — @winstriker)
- v0.9.30 added a file-existence check in the new setQueue path that
used java.io.File.exists() — that returns false for content:// URIs,
which is what SAF-backed paths (SD card / USB-OTG library folders)
look like. Result: every track was dropped from the queue in offline
mode and nothing played. - The check now handles three path formats consistently:
content://... → DocumentFile.exists() via ContentResolver
file://... → strip prefix, then File.exists()
plain absolute → File.exists() - Same fix applied to deleteTrackFile and the orphan-cleanup query
so removal and integrity sweeps work for external-storage rows too.
Install
Download the .apk below and open it on your Android device. If you've got a previous Stash release installed, this upgrades in place — your library, sync history, and settings are preserved.
Requires: Android 8.0 (API 26) or newer.
See the README for first-time setup.
What's Changed
- Backup and Restore internal database and settings by @winstriker in #70
Full Changelog: v0.9.30...v0.9.31