TooManyEduardos TooManyEduardos - 3 months ago 26
Android Question

FileProvider - Can't save file due to FileNotFoundException: /Download/TempFile.html (No such file or directory)

Seems like FileProvider is now required for Android N, so I'm trying to implement FileProvider to save a file from the network into a local temp location, and then I need to read this temp file.

I've done this to setup the FileProvider:

Manifest.xml:

</application>
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
</application>


Then I have a
provider_paths.xml
file in my
res/xml
folder, with this:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="Download" path="Download"/>
</paths>


Finally, this is the java code I have to create the temp file:

try {

final File imagePath = new File(getContext().getFilesDir(), "Download");
final File newFile = new File(imagePath, filename + "." + filePrefix);

final Uri contentUri = FileProvider.getUriForFile(getContext(), getContext().getApplicationContext().getPackageName() + ".provider", newFile);

final File tempFile = new File(contentUri.getPath());

tempFile.getParentFile().mkdirs();
final FileWriter writer = new FileWriter(tempFile);
writer.flush();
writer.close();
return tempFile;
} catch (IOException e) {
e.printStackTrace();
return null;
}


The line of
final FileWriter writer = new FileWriter(tempFile);
throws the exception
java.io.FileNotFoundException: /Download/TempFile.html (No such file or directory)


Any suggestions on what I'm doing wrong? Thank you!

Update/Edit:

The current approach to save the file places the file here:
/storage/emulated/0/Download/TempFile.html


This is fine until I try to consume it with an Intent, like this:

final Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), fileType.getMimeType());
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(intent);


This then throws this exception:

android.os.FileUriExposedException:file:///storage/emulated/0/Download/TempFile.html exposed beyond app through Intent.getData()

Answer

Seems like FileProvider is now required for Android N

It will be used commonly, but only for making content available to other apps. Your needs do not seem to include making content available to other apps.

I'm trying to implement FileProvider to save a file from the network into a local temp location

You have no code in your question that has anything to do with a network.

Any suggestions on what I'm doing wrong?

Calling getPath() on a Uri is generally useless. At best, it might be useful if the scheme of the Uri is file. FileProvider is designed specifically to not give you a Uri with a file scheme, but rather a content scheme. The path of that Uri will not directly represent a file on the device, any more than /questions/39296553/fileprovider-cant-save-file-due-to-filenotfoundexception-download-tempfile (the path of the URL of this Web page) represents a path to a file on your computer.

Beyond that, you do not need a FileProvider to make a temporary file, and you do need a FileProvider to download content over a network.


UPDATE (based upon question update)

First, replace Uri.fromFile(file) with FileProvider.getUriForFile(file) in your Intent logic.

Second, if you really are storing the file in /storage/emulated/0/Download/TempFile.html, you would need to use external-path in your FileProvider configuration, not files-path. files-path would be if you were storing your downloaded file in getFilesDir(). Your /storage/emulated/0/Download/TempFile.html path would appear to be off of Environment.getExternalStorageDirectory().