2

Since Android is enforcing the use of storage access framework by scoped storage accessing, app cannot use direct java.io.file operation to move files.

The purpose is to move some specific media item which is queried from the mediastore database to another specific directory (same partition of the source file), which user has already granted rw permissions to the app.

However, when I try to create a DocumentFile instance using method

DocumentFile fromTreeUri(@NonNull Context context, @NonNull Uri treeUri)

The parent DocumentFile of the created instance is null in this case. And the method

Uri moveDocument(@NonNull ContentResolver content, @NonNull Uri sourceDocumentUri, @NonNull Uri sourceParentDocumentUri, @NonNull Uri targetParentDocumentUri)

requires the source parent to move the Document file. I know I can after all copy the source to target by reading/writing IO streams, but that is not efficient. So, how can I accomplish this in a recommended manner?

An additional question is if there is a way to move the content from mediastore to another place, how can I delete it from the database without delete the underlying file entity?

Robin
  • 10,052
  • 6
  • 31
  • 52
  • "I know I can after all copy the source to target by reading/writing IO streams, but that is not efficient" -- you don't have a choice AFAIK. A `DocumentFile` would not help, as it does not have a move operation, because two documents are not necessarily on the same filesystem or managed by the same documents provider. – CommonsWare Mar 08 '20 at 14:09
  • Thanks for the comment, let's just assume that the target is just a simple file on the internal sdcard partition, is there a shortcut to do this via DocumentsContract.moveDocument() method? – Robin Mar 08 '20 at 14:12
  • "is there a shortcut to do this via DocumentsContract.moveDocument() method?" -- none that I know of. Even that might use streams, if the source and target parents are not from the same provider, or if the provider has a sub-optimal implementation of `DocumentsProvider#moveDocument()`. But, I had forgotten that `DocumentsContract` had a `moveDocument()` method, so my apologies for not mentioning that in my original comment. Looking at the `DocumentFile` source code, it does not have any functions that use `moveDocument()`. – CommonsWare Mar 08 '20 at 14:20

1 Answers1

1

DocumentContract.moveDocument() is only available since API 24. Hence, to support older versions you can use this library. It could help you to move and copy files like this:

val file: DocumentFile = // from tree URI
file.moveFileTo(context, targetFolder, callback)
file.copyFileTo(context, targetFolder, callback)

// For media
val media = MediaFile(context, mediaUri)
media.moveTo(context, targetFolder, callback)
media.copyTo(context, targetFolder, callback)

moveTo() uses DocumentContract.moveDocument() when possible, considering its fast performance.

Anggrayudi H
  • 14,977
  • 11
  • 54
  • 87