17

The file uri is known, such as

`file:///mnt/sdcard/Download/AppSearch_2213333_60.apk`

I want to check if this file can open or not in background, how to do?

Victor S
  • 4,021
  • 15
  • 43
  • 54

7 Answers7

29

Check if a file of a path exists like this:

File file = new File("/mnt/sdcard/Download/AppSearch_2213333_60.apk" );
if (file.exists()) {
 //Do something
}

Keep in mind to remove something like "file://" etc. otherwise use:

 File file = new File(URI.create("file:///mnt/sdcard/Download/AppSearch_2213333_60.apk").getPath());
 if (file.exists()) {
  //Do something
 }

Also you have to set proper permissions for your app in the AndroidManifest.xml to access the sdcard:

 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
alex
  • 5,516
  • 2
  • 36
  • 60
  • 1
    Is it safe to call `file.exists` on the UI thread? Maybe the result is cached by the OS, so it could be safe? Or does it really access the file system to check it, which means we should always do it on the background thread? – android developer Aug 13 '18 at 12:23
  • Basically `File(path).exists()` tries to open a file and file and catches exceptions like `FileNotFoundException`. So think e.g. about NFS network shares to check (rather uncommon for Android) with this function it would definetly block for a while. So calling on the UI thread might not be the best idea here. You can call it from another thread and publish the result async on the UI thread then. For more info check this: https://stackoverflow.com/questions/6321180/how-expensive-is-file-exists-in-java – alex Aug 21 '18 at 08:35
  • I see. Thank you! – android developer Aug 21 '18 at 08:52
9

I might be a little late to the party here, but I was looking for a solution to a similar problem and was finally able to find a solution for all possible edge cases. The solution is a follows:

boolean bool = false;
        if(null != uri) {
            try {
                InputStream inputStream = context.getContentResolver().openInputStream(uri);
                inputStream.close();
                bool = true;
            } catch (Exception e) {
                Log.w(MY_TAG, "File corresponding to the uri does not exist " + uri.toString());
            }
        }

If the file corresponding to the URI exists, then you will have an input stream object to work with, else an exception will be thrown.

Do not forget to close the input stream if the file does exist.

NOTE:

DocumentFile sourceFile = DocumentFile.fromSingleUri(context, uri);
boolean bool = sourceFile.exists();

does handle most edge cases, but what I found out was that if a file is created programmatically and stored in some folder, the user then visits the folder and manually deletes the file (while the app is running), DocumentFile.fromSingleUri wrongly says that the file exists.

mang4521
  • 742
  • 6
  • 22
  • Thank you, I have been working through this for days until I found your post! I have been experiencing the same scenario you described, in the case of the user manually deleting the file. It is frustrating that .exists() doesn't handle that, but your code works for all of my test cases. (Even more frustrating, in my tests I found that .exists worked for API 29 but not API 23.) – shagberg Sep 20 '21 at 18:25
  • You are welcome. Hope this post of mine helped you out. Cheers! – mang4521 Oct 29 '21 at 13:38
  • You may use [try-with-resources](https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html) to avoid the need to explicitly close the InputStream. – Clemens Mar 25 '23 at 16:00
8
DocumentFile sourceFile = DocumentFile.fromSingleUri(context, uri);
boolean bool = sourceFile.exists();
David Buck
  • 3,752
  • 35
  • 31
  • 35
Ihor
  • 81
  • 1
  • 1
  • 2
    Unlike most other responses, this is the closest to a solution that I was able to find. But, I did find a scenario were this deviates from the expected behavior. If a file from the external directory created for the app [/Android/Data/...] exists and is **recently deleted**, the above code return true when the existence of this file is checked. Anyway to fix this? – mang4521 Dec 16 '20 at 20:19
  • To use above method you should check the permission with that uri. This is guide: https://stackoverflow.com/a/29588566/5856328 – Zappy.Mans Oct 19 '21 at 10:07
  • @mang4521 cant you keep track of it at least in same actvity with shared preference – J. M. Feb 03 '22 at 00:50
1

Start by extracting the filename using URI:

final String path = URI.create("file:///mnt/sdcard/Download/AppSearch_2213333_60.apk")
    .getPath(); // returns the path segment of this URI, ie the file path
final File file = new File(path).getCanonicalFile();
// check if file.exists(); try and check if .canRead(), etc

It is advisable to use URI here, since it will take care of decoding all possible spaces/characters illegal in URIs, but legal in file names.

fge
  • 119,121
  • 33
  • 254
  • 329
0

I wrote a function that checks if a file exists on a given path. The path might me absolute path or Uri path.

fun localFileExist(localPathOrUri: String?, context:Context): Boolean {
    if (localPathOrUri.isNullOrEmpty()) {
        return false
    }

    var exists = File(localPathOrUri).exists()
    if (exists) {
        return exists
    }

    val cR = context.getContentResolver()
    val uri = Uri.parse(localPathOrUri)

    try {
        val inputStream = cR.openInputStream(uri)
        if (inputStream != null) {
            inputStream.close()
            return true
        }
    } catch (e: java.lang.Exception) {
        //file not exists
    }
    return exists
}
Sirojiddin Komolov
  • 771
  • 10
  • 17
0
import java.nio.file.Paths;
import java.nio.file.Files;

boolean exists = Files.exists(Paths.get(URI));

Much more concise..

dnim
  • 2,470
  • 4
  • 20
  • 19
-1

Above answers will not work for all versions of Android (see Get filename and path from URI from mediastore and Get real path from URI, Android KitKat new storage access framework), but there is an easy way using DocumentsContract:

DocumentsContract.isDocumentUri(context,myUri)
johnml1135
  • 4,519
  • 3
  • 23
  • 18
  • 10
    isDocumentUri doesn't test if the file actually exists but if the given URI represents a DocumentsContract.Document backed by a DocumentsProvider – Simon Oct 11 '18 at 01:06