1

My Android app has to check whether a folder Uri is already present on the filesystem (the parent folder was selected by the user, so it is authorized). The following code is intendend to perform the check:

static public boolean folderExists(Activity activity,String folderUriString)
{
ContentResolver contentResolver;
contentResolver = activity.getContentResolver();

Log.d("folder name",folderUriString); // it's content://com.android.providers.downloads.documents/tree/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2Faccesspoint1/subfoldername
Uri folderUri = Uri.parse(folderUriString);
boolean isTreeUri=DocumentsContract.isTreeUri(folderUri);
boolean exists = DocumentFile.fromTreeUri (activity,folderUri).exists();

Log.d("is treeUri",String.valueOf(isTreeUri)); //true
Log.d("folder exists",String.valueOf(exists)); //true

return exists;
}

This code doesn't work because it yields true value if the folder doesn't exist (never created, or created and deleted) even if the parent folder itself doesn't exist.

Note that the uri doesn't exist yet for sure. I use the filesystem app on my device to inspect directories.

The uri string is created by means of this method:

public static String appendUriString(String originalUriString,String appendedUriPath)
{
    String result;
    Uri uri=Uri.parse(originalUriString);
    result=Uri.withAppendedPath(uri,appendedUriPath).toString();
Log.d("appendUri",result);    
    return result;
}

content://com.android.providers.downloads.documents/tree/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2Faccesspoint1/subfoldername

As you can see the resulting uri is a mixed form with encoded and non-encoded symbols, so it is legit because a SAF method created the complete uri.

A different version of the folderExists method split the uri strings to have the parent folder. But I think that a uri should be verified without this trick. Why does it not work? What is the right code?

P5music
  • 3,197
  • 2
  • 32
  • 81

3 Answers3

1

If you want to find out if a folder exists, declare the Uri and a DocumentFile, then use findFile() on the DocumentFile to see if it’s null (i.e., does not exist). If it is null, create the folder. Here’s an example:

Uri treeUri = muri;
DocumentFile root = DocumentFile.fromTreeUri(this, treeUri);
if (root.findFile("Foldername") == null) { //create folder }
Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77
J. M.
  • 115
  • 6
  • 1
    Remember that Stack Overflow isn't just intended to solve the immediate problem, but also to help future readers find solutions to similar problems, which requires understanding the underlying code. This is especially important for members of our community who are beginners, and not familiar with the syntax. Given that, **can you [edit] your answer to include an explanation of what you're doing** and why you believe it is the best approach? See the other answers for good examples. – Jeremy Caney Feb 01 '22 at 00:47
  • Its funny cus i mostly see the opposite, no code amd explanation. Im kind of new to coding also, and this is a partial from a code i got off here that i know works but ill try. – J. M. Feb 01 '22 at 01:13
  • 1
    Yeah, unfortunately, there are a lot of people who still post code-only answers, including some veteran members, and especially within some particular subject matters. We don’t delete those answers, but we definitely encourage more explanation—and when it’s between an answer with and without an explanation, the former generally gets far more community support over time. – Jeremy Caney Feb 01 '22 at 01:34
  • 1
    Understood, i will start explaining more. It would be nice if everybody also put exact detailed coding. I work only on Sketchware, i dont have and cant obtain Android Studio. So i use all java with no automatic code filling. – J. M. Feb 01 '22 at 02:07
0

Try using fromSingleUri instead of fromTreeUri. It might also be worth to check if the fetched DocumentFile isDirectory in fact.

static public boolean folderExists(Activity activity, String folderUriString) {
    Log.d("folder name",folderUriString); // it's content://com.android.providers.downloads.documents/tree/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2Faccesspoint1/subfoldername
    Uri folderUri = Uri.parse(folderUriString);
    DocumentFile pickedDir = DocumentFile.fromSingleUri(activity, folderUri);

    return pickedDir != null && pickedDir.exists();
}
Ernest Zamelczyk
  • 2,562
  • 2
  • 18
  • 32
  • I tested your code. Not only the pickedDir is not null (when it is not present on the filesystem) but I get also DocumentFile: Failed query: java.lang.UnsupportedOperationException: Unsupported Uri (I cannot say where, because there is no error) – P5music Oct 01 '19 at 09:50
  • That's because your uri is invalid. It's url encoded while it shouldn't be. It should look like that: ```content://com.android.providers.downloads.documents/tree/raw:/storage/emulated/0/Download/accesspoint1/subfoldername``` – Ernest Zamelczyk Oct 01 '19 at 09:53
  • That url is from the SAF filePicker+the foldername. It is legit, the encoded form is very common as result from SAF methods and calls – P5music Oct 01 '19 at 10:02
0

(I'm ignoring the debate about whether "/subfoldername" is valid or should be "%2Fsubfoldername")

I ran into this on raw: content URIs, and the only workaround I found was to use lastModified, which returns 0 when the file/folder doesn't exist

static public boolean fileExists(DocumentFile file) {
  return file.exists() && file.lastModified() > 0;
}

There's probably still a small chance that lastModified will return 0, if there's a storage system out there that doesn't provide date information, but I don't know of any.

TuxPaper
  • 1
  • 1