Hong
Hong

Reputation: 18501

Is it possible to get a regular File from DocumentFile?

For Android, the following code returns a Uri that can be used to create DocumentFile corresponding to a directory.

Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, REQUEST_CODE_CUSTOM_FOLDER);

Since many methods of a library require a parameter to be java.io.File, I am wondering if one can get a java.io.File from a DocumentFile.

As an example, an returned document tree Uri treeUri is the following:

treeUri.getPath():/tree/primary:DCIM/deeper/evendeeper
treeUri.toString(): content://com.android.externalstorage.documents/tree/primary%3ADCIM%2Fdeeper%2Fevendeeper

The following is the directory shown in ADM: enter image description here

Upvotes: 9

Views: 11319

Answers (4)

Anggrayudi H
Anggrayudi H

Reputation: 15165

Yes, you can. For API 30+, you need full storage access. And for API 28-, you only need Manifest.permission.READ_EXTERNAL_STORAGE.

With SimpleStorage, you can convert DocumentFile to java.io.File:

val file: File? = documentFile.toRawFile(context)?.takeIf { it.canRead() }

Upvotes: 0

JMP M3dia
JMP M3dia

Reputation: 24

Yes, but it may be that the address is in ASCII and you must convert it to UTF-8 to avoid text strings like "%2F". I recommend using "val decoded = URLDecoder.decode (input," utf-8 ")"

Upvotes: 1

greenapps
greenapps

Reputation: 11224

I am wondering if one can get a java.io.File from a DocumentFile.

Yes mostly you can. If the user chooses a 'file' from primary or secondary storage you can as there is a one to one relationship between the content scheme and the file path of a file or directory.

But if you really need java.io.File you could better use a file picker.

[UPDATE]

content://com.android.externalstorage.documents/tree/primar%3ADCIM%2Fdeeper%2Fevendeeper 
content://com.android.externalstorage.documents/tree/primary:DCIM/deeper/evendeeper 

if that e.g. corresponds with

 /storage/emulated/0/DCIM/deeper/evendeeper. 

And

 content://com.android.externalstorage.documents/tree/primary%3AAndroid%2Fcom.aaaa.org%2Ffiles%2Fafile.txt
 content://com.android.externalstorage.documents/tree/primary:Android/com.aaaa.org/files/afile.txt

transforms in

/storage/emulated/0/Android/com.aaa.org/files/afil‌​e.txt

Then follows if you know one you know them all: there is a one to one relationship.

The only thing you have to do for conversion is replacing content://com.android.externalstorage.documents/tree/primary‌​: by /storage/emulated/0/

This reduces the problem to determining /storage/emulated/0/.

For that you once have to let the user choose the root of the file system path for the choosen content scheme. If it cannot be choosed that it often can be found with a file explorer app on the device. Finally you can let the path beeing typed in.

Precisely the opposite as done in Android SAF (Storage Access FrameWork): Get particular file Uri from TreeUri or in other posts with tag storage-acccess-framework.

Upvotes: -3

CommonsWare
CommonsWare

Reputation: 1006944

the following code returns a Uri that can be used to create DocumentFile corresponding to a directory

No, it does not. It returns a Uri that can be used to create a DocumentFile corresponding to a tree of documents. There is no requirement for it to represent a directory on a filesystem. Where and how the document tree is represented is up to the DocumentsProvider that the user chose. That provider can do whatever it wants to represent the tree (e.g., use a database, use REST calls to a server).

I am wondering if one can get a java.io.File from a DocumentFile.

No, because there is no file.

Upvotes: 6

Related Questions