diff --git a/app/src/main/java/org/oxycblt/auxio/music/extractor/CacheExtractor.kt b/app/src/main/java/org/oxycblt/auxio/music/extractor/CacheExtractor.kt
index e2d08c794..4fef918b9 100644
--- a/app/src/main/java/org/oxycblt/auxio/music/extractor/CacheExtractor.kt
+++ b/app/src/main/java/org/oxycblt/auxio/music/extractor/CacheExtractor.kt
@@ -26,6 +26,7 @@ import androidx.core.database.getStringOrNull
import androidx.core.database.sqlite.transaction
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.util.logD
+import org.oxycblt.auxio.util.logE
import org.oxycblt.auxio.util.queryAll
import org.oxycblt.auxio.util.requireBackgroundThread
import java.io.File
@@ -42,7 +43,12 @@ class CacheExtractor(private val context: Context) {
private var shouldWriteCache = false
fun init() {
- cacheMap = CacheDatabase.getInstance(context).read()
+ try {
+ cacheMap = CacheDatabase.getInstance(context).read()
+ } catch (e: Exception) {
+ logE("Unable to load cache database.")
+ logE(e.stackTraceToString())
+ }
}
/**
@@ -55,16 +61,21 @@ class CacheExtractor(private val context: Context) {
// If the entire library could not be loaded from the cache, we need to re-write it
// with the new library.
logD("Cache was invalidated during loading, rewriting")
- CacheDatabase.getInstance(context).write(rawSongs)
+ try {
+ CacheDatabase.getInstance(context).write(rawSongs)
+ } catch (e: Exception) {
+ logE("Unable to save cache database.")
+ logE(e.stackTraceToString())
+ }
}
}
/**
* Maybe copy a cached raw song into this instance, assuming that it has not changed
- * since it was last saved.
+ * since it was last saved. Returns true if a song was loaded.
*/
fun populateFromCache(rawSong: Song.Raw): Boolean {
- val map = requireNotNull(cacheMap) { "CacheExtractor was not properly initialized" }
+ val map = cacheMap ?: return false
val cachedRawSong = map[rawSong.mediaStoreId]
if (cachedRawSong != null && cachedRawSong.dateAdded == rawSong.dateAdded && cachedRawSong.dateModified == rawSong.dateModified) {
diff --git a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackViewModel.kt b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackViewModel.kt
index f82086459..bfc4fcb1d 100644
--- a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackViewModel.kt
+++ b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackViewModel.kt
@@ -248,26 +248,32 @@ class PlaybackViewModel(application: Application) :
// --- SAVE/RESTORE FUNCTIONS ---
- /** Force save the current [PlaybackStateManager] state to the database. */
- fun savePlaybackState(onDone: () -> Unit) {
+ /**
+ * Force save the current [PlaybackStateManager] state to the database. [onDone]
+ * will be called with true if it was done, or false if an error occurred.
+ */
+ fun savePlaybackState(onDone: (Boolean) -> Unit) {
viewModelScope.launch {
- playbackManager.saveState(PlaybackStateDatabase.getInstance(application))
- onDone()
+ val saved = playbackManager.saveState(PlaybackStateDatabase.getInstance(application))
+ onDone(saved)
}
}
- /** Wipe the saved playback state (if any). */
- fun wipePlaybackState(onDone: () -> Unit) {
+ /**
+ * Wipe the saved playback state (if any). [onDone] will be called with true if it was
+ * successfully done, or false if an error occurred.
+ */
+ fun wipePlaybackState(onDone: (Boolean) -> Unit) {
viewModelScope.launch {
- playbackManager.wipeState(PlaybackStateDatabase.getInstance(application))
- onDone()
+ val wiped = playbackManager.wipeState(PlaybackStateDatabase.getInstance(application))
+ onDone(wiped)
}
}
/**
* Force restore the last [PlaybackStateManager] saved state, regardless of if a library exists
* or not. [onDone] will be called with true if it was successfully done, or false if there was
- * no state or if a library was not present.
+ * no state, a library was not present, or there was an error.
*/
fun tryRestorePlaybackState(onDone: (Boolean) -> Unit) {
viewModelScope.launch {
diff --git a/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt b/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt
index 8eb0f202a..7992a1d82 100644
--- a/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt
+++ b/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt
@@ -29,6 +29,7 @@ import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.playback.state.PlaybackStateManager.Callback
import org.oxycblt.auxio.settings.Settings
import org.oxycblt.auxio.util.logD
+import org.oxycblt.auxio.util.logE
import org.oxycblt.auxio.util.logW
import kotlin.math.max
@@ -368,7 +369,13 @@ class PlaybackStateManager private constructor() {
val library = musicStore.library ?: return false
val internalPlayer = internalPlayer ?: return false
- val state = withContext(Dispatchers.IO) { database.read(library) }
+ val state = try {
+ withContext(Dispatchers.IO) { database.read(library) }
+ } catch (e: Exception) {
+ logE("Unable to restore playback state.")
+ logE(e.stackTraceToString())
+ return false
+ }
synchronized(this) {
if (state != null && (!isInitialized || force)) {
@@ -397,15 +404,32 @@ class PlaybackStateManager private constructor() {
}
/** Save the current state to the [database]. */
- suspend fun saveState(database: PlaybackStateDatabase) {
+ suspend fun saveState(database: PlaybackStateDatabase): Boolean {
logD("Saving state to DB")
+
val state = synchronized(this) { makeStateImpl() }
- withContext(Dispatchers.IO) { database.write(state) }
+ return try {
+ withContext(Dispatchers.IO) { database.write(state) }
+ true
+ } catch (e: Exception) {
+ logE("Unable to save playback state.")
+ logE(e.stackTraceToString())
+ false
+ }
}
- suspend fun wipeState(database: PlaybackStateDatabase) {
+ /** Wipe the current state. */
+ suspend fun wipeState(database: PlaybackStateDatabase): Boolean {
logD("Wiping state")
- withContext(Dispatchers.IO) { database.write(null) }
+
+ return try {
+ withContext(Dispatchers.IO) { database.write(null) }
+ true
+ } catch (e: Exception) {
+ logE("Unable to wipe playback state.")
+ logE(e.stackTraceToString())
+ false
+ }
}
/** Sanitize the state with [newLibrary]. */
diff --git a/app/src/main/java/org/oxycblt/auxio/settings/prefs/PreferenceFragment.kt b/app/src/main/java/org/oxycblt/auxio/settings/prefs/PreferenceFragment.kt
index 06ab07128..690448e5a 100644
--- a/app/src/main/java/org/oxycblt/auxio/settings/prefs/PreferenceFragment.kt
+++ b/app/src/main/java/org/oxycblt/auxio/settings/prefs/PreferenceFragment.kt
@@ -113,13 +113,21 @@ class PreferenceFragment : PreferenceFragmentCompat() {
when (preference.key) {
context.getString(R.string.set_key_save_state) -> {
- playbackModel.savePlaybackState {
- this.context?.showToast(R.string.lbl_state_saved)
+ playbackModel.savePlaybackState { saved ->
+ if (saved) {
+ this.context?.showToast(R.string.lbl_state_saved)
+ } else {
+ this.context?.showToast(R.string.err_did_not_save)
+ }
}
}
context.getString(R.string.set_key_wipe_state) -> {
- playbackModel.wipePlaybackState {
- this.context?.showToast(R.string.lbl_state_wiped)
+ playbackModel.wipePlaybackState { wiped ->
+ if (wiped) {
+ this.context?.showToast(R.string.lbl_state_wiped)
+ } else {
+ this.context?.showToast(R.string.err_did_not_wipe)
+ }
}
}
context.getString(R.string.set_key_restore_state) ->
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index a369b11f5..6c31654e1 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -251,7 +251,11 @@
No folders
This folder is not supported
- No state could be restored
+ Unable to restore state
+
+ Unable to clear state
+
+ Unable to save state