diff --git a/README.md b/README.md index 2ce6cad4..4dd2ad78 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,8 @@ It uses the same internal APIs as `adb backup` which is deprecated and thus need ## Permissions * `android.permission.BACKUP` to back up application data. -* `android.permission.MANAGE_DOCUMENTS` to retrieve the available storage roots. +* `android.permission.ACCESS_NETWORK_STATE` to check if there is internet access when network storage is used. +* `android.permission.MANAGE_DOCUMENTS` to retrieve the available storage roots. * `android.permission.MANAGE_USB` to access the serial number of USB mass storage devices. * `android.permission.WRITE_SECURE_SETTINGS` to change system backup settings and enable call log backup. * `android.permission.QUERY_ALL_PACKAGES` to get information about all installed apps for backup. diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2cb592db..71c760ca 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -9,6 +9,9 @@ android:name="android.permission.BACKUP" tools:ignore="ProtectedPermissions" /> + + + Unit)? = null ) { @@ -144,10 +146,11 @@ internal class StorageRootFetcher(private val context: Context, private val isRe if (!supportsCreate || !supportsIsChild) return null val rootId = cursor.getString(COLUMN_ROOT_ID)!! if (authority == AUTHORITY_STORAGE && rootId == ROOT_ID_HOME) return null + val documentId = cursor.getString(COLUMN_DOCUMENT_ID) ?: return null return StorageRoot( authority = authority, rootId = rootId, - documentId = cursor.getString(COLUMN_DOCUMENT_ID)!!, + documentId = documentId, icon = getIcon(context, authority, rootId, cursor.getInt(COLUMN_ICON)), title = cursor.getString(COLUMN_TITLE)!!, summary = cursor.getString(COLUMN_SUMMARY), @@ -155,7 +158,8 @@ internal class StorageRootFetcher(private val context: Context, private val isRe // AOSP 11 reports -1 instead of null if (bytes == -1L) null else bytes }, - isUsb = flags and FLAG_REMOVABLE_USB != 0 + isUsb = flags and FLAG_REMOVABLE_USB != 0, + requiresNetwork = flags and FLAG_LOCAL_ONLY == 0 // not local only == requires network ) } @@ -175,6 +179,7 @@ internal class StorageRootFetcher(private val context: Context, private val isRe summary = context.getString(R.string.storage_fake_drive_summary), availableBytes = null, isUsb = true, + requiresNetwork = false, enabled = false ) roots.add(root) @@ -216,6 +221,7 @@ internal class StorageRootFetcher(private val context: Context, private val isRe summary = context.getString(summaryRes), availableBytes = null, isUsb = false, + requiresNetwork = true, enabled = !isInstalled || isRestore, overrideClickListener = { if (isInstalled) context.startActivity(intent) diff --git a/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageViewModel.kt b/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageViewModel.kt index 72047d7c..e5e48b01 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageViewModel.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageViewModel.kt @@ -101,7 +101,7 @@ internal abstract class StorageViewModel( } else { root.title } - val storage = Storage(uri, name, root.isUsb) + val storage = Storage(uri, name, root.isUsb, root.requiresNetwork) settingsManager.setStorage(storage) if (storage.isUsb) { diff --git a/app/src/test/java/com/stevesoltys/seedvault/transport/backup/BackupCoordinatorTest.kt b/app/src/test/java/com/stevesoltys/seedvault/transport/backup/BackupCoordinatorTest.kt index 03967e66..f9d6a549 100644 --- a/app/src/test/java/com/stevesoltys/seedvault/transport/backup/BackupCoordinatorTest.kt +++ b/app/src/test/java/com/stevesoltys/seedvault/transport/backup/BackupCoordinatorTest.kt @@ -63,7 +63,7 @@ internal class BackupCoordinatorTest : BackupTest() { private val metadataOutputStream = mockk() private val fileDescriptor: ParcelFileDescriptor = mockk() private val packageMetadata: PackageMetadata = mockk() - private val storage = Storage(Uri.EMPTY, getRandomString(), false) + private val storage = Storage(Uri.EMPTY, getRandomString(), false, false) @Test fun `starting a new restore set works as expected`() = runBlocking {