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 {