diff --git a/app/src/main/java/com/owncloud/android/ui/activity/ReceiveExternalFilesActivity.java b/app/src/main/java/com/owncloud/android/ui/activity/ReceiveExternalFilesActivity.java index 99e68a196af5..48c4e10a6a00 100755 --- a/app/src/main/java/com/owncloud/android/ui/activity/ReceiveExternalFilesActivity.java +++ b/app/src/main/java/com/owncloud/android/ui/activity/ReceiveExternalFilesActivity.java @@ -1062,7 +1062,11 @@ public void uploadFiles() { preferences.setLastUploadPath(mUploadPath); if (resultCode == UriUploader.UriUploaderResultCode.OK) { - finish(); + // While content:// URIs are copied to temporary files this Activity has to stay alive, otherwise its + // temporary read permission for those URIs is revoked. onTmpFilesCopied() finishes it once done. + if (!uploader.isTmpCopyInProgress()) { + finish(); + } } else { int messageResTitle = R.string.uploader_error_title_file_cannot_be_uploaded; diff --git a/app/src/main/java/com/owncloud/android/ui/asynctasks/CopyAndUploadContentUrisTask.kt b/app/src/main/java/com/owncloud/android/ui/asynctasks/CopyAndUploadContentUrisTask.kt index 981f5842be42..5ac9503f6756 100644 --- a/app/src/main/java/com/owncloud/android/ui/asynctasks/CopyAndUploadContentUrisTask.kt +++ b/app/src/main/java/com/owncloud/android/ui/asynctasks/CopyAndUploadContentUrisTask.kt @@ -26,7 +26,6 @@ import kotlinx.coroutines.withContext import java.io.File import java.io.FileNotFoundException import java.io.FileOutputStream -import java.io.InputStream import java.lang.ref.WeakReference @Suppress("TooGenericExceptionCaught") @@ -50,20 +49,8 @@ class CopyAndUploadContentUrisTask( behaviour: Int, contentResolver: ContentResolver ) { - val inputStreams: List = try { - sourceUris.map { contentResolver.openInputStream(it) } - } catch (e: FileNotFoundException) { - Log_OC.e(TAG, "Source file not found", e) - dispatchResult(ResultCode.LOCAL_FILE_NOT_FOUND) - return - } catch (e: SecurityException) { - Log_OC.e(TAG, "Insufficient permissions to open source URIs", e) - dispatchResult(ResultCode.FORBIDDEN) - return - } - scope.launch(Dispatchers.IO) { - val result = performCopy(user, sourceUris, remotePaths, behaviour, contentResolver, inputStreams) + val result = performCopy(user, sourceUris, remotePaths, behaviour, contentResolver) withContext(Dispatchers.Main) { dispatchResult(result) } @@ -75,8 +62,7 @@ class CopyAndUploadContentUrisTask( sourceUris: Array, remotePaths: Array, behaviour: Int, - contentResolver: ContentResolver, - inputStreams: List + contentResolver: ContentResolver ): ResultCode { val localPaths = arrayOfNulls(sourceUris.size) val resolvedRemotePaths = arrayOfNulls(sourceUris.size) @@ -95,7 +81,7 @@ class CopyAndUploadContentUrisTask( } Log_OC.d(TAG, "Cache file creation result: ${cacheFile.createNewFile()}") - inputStreams[index]?.use { input -> + contentResolver.openInputStream(uri)?.use { input -> FileOutputStream(currentTempPath).use { output -> input.copyTo(output) } diff --git a/app/src/main/java/com/owncloud/android/ui/helpers/UriUploader.kt b/app/src/main/java/com/owncloud/android/ui/helpers/UriUploader.kt index 7ff1d70cca16..42a63ea6d5f1 100644 --- a/app/src/main/java/com/owncloud/android/ui/helpers/UriUploader.kt +++ b/app/src/main/java/com/owncloud/android/ui/helpers/UriUploader.kt @@ -64,6 +64,16 @@ class UriUploader @JvmOverloads constructor( ERROR_SENSITIVE_PATH } + /** + * True when content:// URIs are being copied to temporary files in the background. + * + * The temporary read permission for those URIs belongs to the calling Activity and is revoked once that Activity is + * destroyed. Callers must therefore stay alive until [OnCopyTmpFilesTaskListener.onTmpFilesCopied] is invoked, + * otherwise opening the URIs fails with a SecurityException. + */ + var isTmpCopyInProgress: Boolean = false + private set + @Suppress("NestedBlockDepth") fun uploadUris(): UriUploaderResultCode { var code = UriUploaderResultCode.OK @@ -165,6 +175,7 @@ class UriUploader @JvmOverloads constructor( val taskRetainerFragment = fm.findFragmentByTag(TaskRetainerFragment.FTAG_TASK_RETAINER_FRAGMENT) as TaskRetainerFragment? taskRetainerFragment?.setTask(copyTask) + isTmpCopyInProgress = true copyTask.execute( user, sourceUris,