Support a lack of MANAGE_DOCUMENTS permission

When `android.permission.MANAGE_DOCUMENTS` is not granted, Seedvault
prompts to select a storage location. Do not insist on resolving the
storage's actual root, as it will likely (or perhaps always) fail.
Use a fake storage root as is done for USB and app-based options.

Known issues:
* Selected location is assumed not to be USB and not to require
  network access in its storage options.

Change-Id: I357b4c68673d71c087be41e9c94c2841c1d6658e
This commit is contained in:
t-m-w 2022-11-28 00:08:14 -05:00 committed by Steve Soltys
parent da5205c0e9
commit 208dbd6a60
3 changed files with 21 additions and 1 deletions

View file

@ -35,7 +35,9 @@ class StorageActivity : BackupActivity() {
val authority = uri.authority ?: throw AssertionError("No authority in $uri")
val storageRoot = StorageRootResolver.getStorageRoots(this, authority).getOrNull(0)
if (storageRoot == null) {
viewModel.onUriPermissionResultReceived(null)
viewModel.onSafOptionChosen(
StorageRootResolver.getFakeStorageRootForUri(this, uri))
viewModel.onUriPermissionResultReceived(uri)
} else {
viewModel.onSafOptionChosen(storageRoot)
viewModel.onUriPermissionResultReceived(uri)

View file

@ -3,6 +3,7 @@ package com.stevesoltys.seedvault.ui.storage
import android.content.Context
import android.database.Cursor
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.UserHandle
import android.provider.DocumentsContract
import android.provider.DocumentsContract.Root.COLUMN_AVAILABLE_BYTES
@ -57,6 +58,21 @@ internal object StorageRootResolver {
return roots
}
fun getFakeStorageRootForUri(context: Context, uri: Uri): SafOption {
return SafOption(
authority = AUTHORITY_STORAGE,
rootId = "fake",
documentId = "fake",
// TODO: Use something other than the USB icon?
icon = getIcon(context, AUTHORITY_STORAGE, "usb", 0),
title = context.getString(R.string.storage_user_selected_location_title),
summary = context.getString(R.string.storage_user_selected_location_summary),
availableBytes = null,
isUsb = false, // TODO: Check this if possible instead of forcing false
requiresNetwork = false, // TODO: Check this if possible instead of forcing false
)
}
private fun getStorageRoot(context: Context, authority: String, cursor: Cursor): SafOption? {
val flags = cursor.getInt(COLUMN_FLAGS)
val supportsCreate = flags and FLAG_SUPPORTS_CREATE != 0

View file

@ -58,6 +58,8 @@
<string name="storage_fragment_restore_title">Where to find your backups?</string>
<string name="storage_fragment_warning">People with access to your storage location can learn which apps you use, but do not get access to the apps\' data.</string>
<string name="storage_fragment_warning_delete">Existing backups in this location will be deleted.</string>
<string name="storage_user_selected_location_title">User-chosen location</string>
<string name="storage_user_selected_location_summary">Chosen using the folder browser</string>
<string name="storage_fake_drive_title">USB flash drive</string>
<string name="storage_fake_drive_summary">Needs to be plugged in</string>
<string name="storage_available_bytes"><xliff:g example="1 GB" id="size">%1$s</xliff:g> free</string>