Ofek Ron
Ofek Ron

Reputation: 8580

file.exists() returns false on Android

    String filename = "file:///android_asset/Help_ja.html";
    File f = new File(filename);
    if (!f.exists()) filename="file:///android_asset/Help_us.html";
    webView.loadUrl(filename);

i load an HTML out of the assests folder, both files are there, when i tried this code:

filename="file:///android_asset/Help_us.html";
webView.loadUrl(filename);

it worked, but for some reason f.exists() returns false, i was thinking maybe its because a URL, but then how do i check if the file exists before i load it to the webView?

Upvotes: 1

Views: 3490

Answers (3)

Gábor
Gábor

Reputation: 10224

Let's suppose you have two file paths:

String originalPath = "file:///android_asset/..."
String localizedPath = "file:///android_asset/..."

The following will test for the existence of the second and default to the first if not available:

String localizedAssetPath = localizedPath.replace("file:///android_asset/",  "");
try {
  InputStream stream = getResources().getAssets().open(localizedAssetPath);
  stream.close();
  return localizedPath;
}
catch (Exception e) {
  return originalPath;
}

So, basically, you remove the file:///android_asset/ base path and you try to open it as a stream. If this fails, you default to the original path.

Upvotes: 3

zapl
zapl

Reputation: 63955

In code a solution that works for me:

private static boolean assetExists(AssetManager assets, String name) {
    try {
        // using File to extract path / filename
        // alternatively use name.lastIndexOf("/") to extract the path
        File f = new File(name);
        String parent = f.getParent();
        if (parent == null) parent = "";
        String fileName = f.getName();
        // now use path to list all files
        String[] assetList = assets.list(parent);
        if (assetList != null && assetList.length > 0) {
            for (String item : assetList) {
                if (fileName.equals(item))
                    return true;
            }
        }
    } catch (IOException e) {
        // Log.w(TAG, e); // enable to log errors
    }
    return false;
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    // test for file:///android_asset/Help_ja.html
    boolean exists1 = assetExists(getAssets(), "Help_ja.html"));
    // and if assets are in subfolders
    // would be ./assets/www/test2.hml in your project
    boolean exists2 = assetExists(getAssets(), "www/test2.html");
}

Asset files are not physical files on the device, so you can't use File for them. The only way to read their content is through the AssetManager. Above example code uses the list() method to list the asset files and check the list for the one you search. You could also try to open an InputStream for example.

Upvotes: 3

Gabe Sechan
Gabe Sechan

Reputation: 93559

A file doesn't take a URL, it takes a path. So it should not start with File:///, it should start with / for an absolute path or the first directory name for a relative path.

If you need to check if it exists before loading it into a URL, strip the protocol from the string before passing to the File constructor. If you load the URL into a URL object you can use getPath() and getFile() as helpers

Upvotes: 1

Related Questions