diff --git a/app/src/main/java/com/stevesoltys/seedvault/plugins/saf/DocumentsStorage.kt b/app/src/main/java/com/stevesoltys/seedvault/plugins/saf/DocumentsStorage.kt index ce1b7dd3..c44b9cd1 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/plugins/saf/DocumentsStorage.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/plugins/saf/DocumentsStorage.kt @@ -158,13 +158,14 @@ internal suspend fun DocumentFile.createOrGetFile( if (this.name != name) { throw IOException("File named ${this.name}, but should be $name") } - } ?: throw IOException() + } ?: throw IOException("could not find nor create") } catch (e: Exception) { // SAF can throw all sorts of exceptions, so wrap it in IOException. // E.g. IllegalArgumentException can be thrown by FileSystemProvider#isChildDocument() // when flash drive is not plugged-in: // http://aosp.opersys.com/xref/android-11.0.0_r8/xref/frameworks/base/core/java/com/android/internal/content/FileSystemProvider.java#135 - throw IOException(e) + if (e is IOException) throw e + else throw IOException(e) } } diff --git a/app/src/main/java/com/stevesoltys/seedvault/transport/backup/BackupCoordinator.kt b/app/src/main/java/com/stevesoltys/seedvault/transport/backup/BackupCoordinator.kt index d0358877..59213eb4 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/transport/backup/BackupCoordinator.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/transport/backup/BackupCoordinator.kt @@ -360,6 +360,9 @@ internal class BackupCoordinator( onPackageBackedUp(packageInfo, BackupType.KV, size) } catch (e: Exception) { Log.e(TAG, "Error calling onPackageBackedUp for $packageName", e) + if (e is IOException && + e.message?.contains("No space left on device") == true + ) nm.onInsufficientSpaceError() result = TRANSPORT_PACKAGE_REJECTED } } diff --git a/app/src/main/java/com/stevesoltys/seedvault/ui/notification/BackupNotificationManager.kt b/app/src/main/java/com/stevesoltys/seedvault/ui/notification/BackupNotificationManager.kt index 5d100d78..f08bea79 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/ui/notification/BackupNotificationManager.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/ui/notification/BackupNotificationManager.kt @@ -17,6 +17,7 @@ import android.text.format.Formatter import android.util.Log import androidx.core.app.NotificationCompat.Action import androidx.core.app.NotificationCompat.Builder +import androidx.core.app.NotificationCompat.CATEGORY_ERROR import androidx.core.app.NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE import androidx.core.app.NotificationCompat.PRIORITY_DEFAULT import androidx.core.app.NotificationCompat.PRIORITY_HIGH @@ -36,9 +37,10 @@ private const val CHANNEL_ID_RESTORE_ERROR = "NotificationRestoreError" internal const val NOTIFICATION_ID_OBSERVER = 1 private const val NOTIFICATION_ID_SUCCESS = 2 private const val NOTIFICATION_ID_ERROR = 3 -private const val NOTIFICATION_ID_RESTORE_ERROR = 4 -private const val NOTIFICATION_ID_BACKGROUND = 5 -private const val NOTIFICATION_ID_NO_MAIN_KEY_ERROR = 6 +private const val NOTIFICATION_ID_SPACE_ERROR = 4 +private const val NOTIFICATION_ID_RESTORE_ERROR = 5 +private const val NOTIFICATION_ID_BACKGROUND = 6 +private const val NOTIFICATION_ID_NO_MAIN_KEY_ERROR = 7 private val TAG = BackupNotificationManager::class.java.simpleName @@ -214,6 +216,20 @@ internal class BackupNotificationManager(private val context: Context) { nm.cancel(NOTIFICATION_ID_ERROR) } + fun onInsufficientSpaceError() { + val notification = Builder(context, CHANNEL_ID_ERROR).apply { + setSmallIcon(R.drawable.ic_cloud_error) + setContentTitle(context.getString(R.string.notification_space_error_title)) + setContentText(context.getString(R.string.notification_space_error_text)) + setWhen(System.currentTimeMillis()) + setOnlyAlertOnce(true) + setAutoCancel(true) + setPriority(PRIORITY_HIGH) + setCategory(CATEGORY_ERROR) + }.build() + nm.notify(NOTIFICATION_ID_SPACE_ERROR, notification) + } + @SuppressLint("RestrictedApi") fun onRemovableStorageNotAvailableForRestore(packageName: String, storageName: String) { val appName = try { diff --git a/app/src/main/java/com/stevesoltys/seedvault/worker/ApkBackupManager.kt b/app/src/main/java/com/stevesoltys/seedvault/worker/ApkBackupManager.kt index 00f707e0..1471d16f 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/worker/ApkBackupManager.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/worker/ApkBackupManager.kt @@ -110,6 +110,9 @@ internal class ApkBackupManager( } ?: false } catch (e: IOException) { Log.e(TAG, "Error while writing APK for $packageName", e) + if (e.message?.contains("No space left on device") == true) { + nm.onInsufficientSpaceError() + } false } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8b02e9d8..b7e98f47 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -160,6 +160,9 @@ <string name="notification_error_text">A device backup failed to run.</string> <string name="notification_error_action">Fix</string> + <string name="notification_space_error_title">Insufficient backup space</string> + <string name="notification_space_error_text">Your backup location is running out of space. Free up space, so backups can run.</string> + <string name="notification_restore_error_channel_title">Auto restore flash drive error</string> <string name="notification_restore_error_title">Could not restore data for %1$s</string> <string name="notification_restore_error_text">Plug in your %1$s before installing the app to restore its data from backup.</string>