SpotiFLAC v3.5.0
What's New
Highlights
- SAF Storage (Android 10+): Proper Storage Access Framework support for download destination (content URIs)
- Select download folder via SAF tree picker
- Downloads now write to SAF file descriptors (
/proc/self/fd/*) instead of raw filesystem paths - Works around Android 10+ scoped storage permission errors
- Modern Onboarding Experience: Completely redesigned Setup and Tutorial screens
Added
- Home feed disk caching via SharedPreferences for instant restore on app startup
- SAF display path resolver in native Android layer (converts tree URIs to readable paths)
- New settings fields for storage mode + SAF tree URI
- SAF platform bridge methods: pick tree, stat/exists/delete, open content URI, copy to temp, write back to SAF
- SAF library scan mode (DocumentFile traversal + metadata read)
- Incremental library scanning for filesystem and SAF paths (only scans new/modified files and detects removed files)
- Force Full Scan action in Library Settings to rescan all files on demand
- Downloaded files are now excluded from Local Library scan results to prevent duplicate entries
- Legacy library rows now support
file_mod_timebackfill before incremental scans (faster follow-up scans after upgrade) - Library UI toggle to show SAF-repaired history items
- Scan cancelled banner + retry action for library scans
- Android DocumentFile dependency for SAF operations
- Post-processing API v2 (SAF-aware, ready to replace v1)
- Donate page in Settings with Ko-fi and Buy Me a Coffee links
- Per-App Language support on Android 13+ (locale_config.xml)
- Interactive tutorial with working search bar simulation and clickable download buttons
- Tutorial completion state is persisted after onboarding
- Visual feedback animations for page transitions, entrance effects, and feature lists
- New dedicated welcome step in setup wizard with improved branding
Changed
- Download pipeline supports
output_path+output_extfor Go backend - Tidal/Qobuz/Amazon/Extension downloads use SAF-aware output when enabled
- Post-processing hooks run for SAF content URIs (via temp file bridge)
- File operations in Library/Queue/Track screens now SAF-aware (
open,exists,delete,stat) - Local Library scan defaults to incremental mode; full rescan is available via Force Full Scan
- Local library database upgraded to schema v3 with
file_mod_timetracking for incremental scan cache - Platform channels expanded with incremental scan APIs (
scanLibraryFolderIncremental) on Android and iOS - Android platform channel adds
getSafFileModTimesfor SAF legacy cache backfill - Android build tooling upgraded to Gradle 9.3.1 (wrapper)
- Android build path validated with Java 25 (Gradle/Kotlin/assemble debug)
- SAF tree picker flow in
MainActivitymigrated to Activity Result API (registerForActivityResult) MainActivityhost migrated toFlutterFragmentActivityfor SAF picker compatibility- Legacy
startActivityForResult/onActivityResultSAF picker path removed - Setup screen UI polish: smaller logo, thin outline borders on text fields
- Removed support section from About page (moved to Donate page)
- Qobuz squid.wtf region fallback for blocked regions
- Setup screen converted to PageView flow with animated progress bar and modern card layouts
- Tutorial screen aligned with Setup Screen design, updated typography and softened UI shapes
- Larger, more accessible navigation buttons for onboarding flow
- Reduced visual noise by removing unnecessary glow effects
Fixed
- Android 10+
permission deniedwhen writing to/storage/emulated/0(now handled via SAF) - SAF history repair: auto-resolve missing content URIs using tree + filename
- SAF download fallback: retry in app-private storage when SAF write fails
- Tidal DASH manifest writing when output path is a file descriptor (no invalid
.m4apath) - External LRC output in SAF mode
- Restored old-device renderer fallback while using
FlutterFragmentActivityby injecting shell args from a customFlutterFragment(--enable-impeller=falseon problematic devices) - Preserved Flutter fragment creation behavior (cached engine, engine group, new engine) while adding Impeller fallback support
- SAF tree picker result now consistently returns
tree_uripayload with persisted URI permission handling - SAF share file now copies to temp before sharing (fixes share from SAF content URI)
- Home feed not updating after installing extension with homeFeed capability (no longer requires app restart)
- Library scan hero card showing 0 tracks during scan (now shows scanned file count in real-time)
- Library folder picker no longer requires MANAGE_EXTERNAL_STORAGE on Android 10+ (uses SAF tree picker)
- One-time SAF migration prompt for users updating from pre-SAF versions
- Fixed
fileModTimepropagation across Go/Android/Dart so incremental scan cache is stored and reused correctly - Fixed SAF incremental scan key mismatch (
lastModifiedvsfileModTime) and normalized result fields (skippedCount,totalFiles) - Fixed incremental scan progress when all files are skipped (
scanned_filesnow reaches total files) - Removed duplicate
"removeExtension"branch in Android method channel handler (eliminates Kotlin duplicate-branch warning)
Downloads
Android
- arm64:
SpotiFLAC-v3.5.0-arm64.apk(recommended for modern devices) - arm32:
SpotiFLAC-v3.5.0-arm32.apk(older devices)
iOS
- iOS:
SpotiFLAC-v3.5.0-ios-unsigned.ipa(sideload required)
Installation
Android: Enable "Install from unknown sources" and install the APK iOS: Use AltStore, Sideloadly, or similar tools to sideload the IPA