Android Question How to implement DocumentFile.exists()?

Inman

Well-Known Member
Licensed User
Longtime User
I want to check whether a file exists. Since the check could be on external SD card, I can't use File.Exists(). Instead I need to use DocumentFile.exists().

https://developer.android.com/reference/android/support/v4/provider/DocumentFile.html#exists()

When I tried DocumentFile.exists(), I always got True regardless of file's existence. Based on a DocumentFile example Erel posted, I then tried to implement the same using fromFile() and it worked. But it is too slow as it scans the entire list of files. I feel exists() could be faster. Please help.
 

OliverA

Expert
Licensed User
Longtime User
Code that you used to text the file existence? If possible, a stripped down application zipped and uploaded.
 
Upvote 0

Inman

Well-Known Member
Licensed User
Longtime User
This is the code
B4X:
Sub CheckIfFileExists(dirname As String,filename As String) As Boolean
   
    Dim dpickedDir As JavaObject
    Dim ret As Boolean
    
    dpickedDir=GetPickedFile(dirname,filename)
    ret=dpickedDir.RunMethod("exists",Null)
    Log(dpickedDir.RunMethod("getName",Null))
    Return ret

End Sub

Sub GetPickedFile(uri As String,filename As String) As JavaObject
    Dim ctxt As JavaObject
    ctxt.InitializeContext
    Dim DocumentFileStatic As JavaObject
    Dim treeUri,baseuri As Uri
    'treeUri.Parse(uri)
    baseuri.Parse(uri)
    treeUri.WithAppendedPath(baseuri,filename)
    Dim pickedDir As JavaObject = DocumentFileStatic.InitializeStatic("android.support.v4.provider.DocumentFile").RunMethod("fromTreeUri", Array(ctxt, treeUri))
    Return pickedDir
    
End Sub

And it is called like this
B4X:
CheckIfFileExists(TargetURIPath,"testfile.jpg")

Where TargetURIPath is
B4X:
(HierarchicalUri) content://com.android.externalstorage.documents/tree/primary%3ADCIM%2FCamera

Now there is nothing wrong with TargetURIPath as I use it for other functions and works perfectly.

The problem is here
B4X:
treeUri.WithAppendedPath(baseuri,filename)

When I tried dpickedDir.RunMethod("getName",Null), the output is just "Camera", which means it is not appending testfile.jpg to uri correctly. And since Camera folder exists, I always get True for dpickedDir.RunMethod("exists",Null) irrespective of filename.

I think what I should do is to call DocumentFile.fromFile(File file) first (passing the name of the file to be checked) and then call DocumentFile.exists(). But I can't figure out the javaobject code to call fromFile.
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
I can't use File.Exists()
Is B4A's File not based on Android's File class? If it is, I think you can check for a file's existence using File.Exists(). See http://www.raviyp.com/android/192-h...memory-in-android-lollipop-and-above-solution. Where (code fragment):
B4X:
String SDPATH = Environment.getExternalStorageDirectory().getPath();
File pathFile = new File(SDPATH+"/Valetron/", "ScanPath");
if(!pathFile.exists())
Please note, I'm just guessing here, I do not have a Android device with SD card support.
 
Upvote 0

Inman

Well-Known Member
Licensed User
Longtime User
FindFile is pretty slow for me in both debug and release modes. I guess it depends on the number of files in the folder. My app scans the DCIM/Camera folder and I have like thousands of photos which makes it pretty slow.

I am still using the Javaobject codes you shared in my thread. This was before you released the ExternalStorage class and I had already released an update to Play Store where users were asked to select the external SD folder. I then stored its URI value in a file, which I reuse in the background to copy files automatically. I am not sure if I can use this URI value with your new class and I prefer not to force the users to select a folder again as I already did that once. So I want to stick with the Javaobject code for the time being.

I almost finished an update by using FindFile to check if the file exists, before noticing it is slow on large folders. I wanted to try ListFiles but I noticed that it returns a list of DocumentFile. If it had returned a list of filenames, I could have performed a List.Indexof(filename) and that is usually fast even with long lists. But since here it is a list of DocumentFile, I will have to iterate the list and check the name of each file using getName(), which I guess will further slow it down.

And I can't call ListFiles once and store it locally as new files could come any time as it is the user's camera folder. So sadly only DocumentFile.exists() will work in my case.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
I almost finished an update by using FindFile to check if the file exists, before noticing it is slow on large folders. I wanted to try ListFiles but I noticed that it returns a list of DocumentFile. If it had returned a list of filenames, I could have performed a List.Indexof(filename) and that is usually fast even with long lists. But since here it is a list of DocumentFile, I will have to iterate the list and check the name of each file using getName(), which I guess will further slow it down.
You should try it. Finding an item in a list is a very quick operation. Note that List.IndexOf is not faster then going over each item yourself (in release mode).
 
Upvote 0

Inman

Well-Known Member
Licensed User
Longtime User
You should try it. Finding an item in a list is a very quick operation. Note that List.IndexOf is not faster then going over each item yourself (in release mode).

I tried it out. While there is a marginal improvement in speed compared to findfile, there is still noticeable delay.
 
Upvote 0
Top