SuperThomasLab SuperThomasLab - 2 months ago 371x
Android Question

android.os.FileUriExposedException: file:///storage/emulated/0/test.txt exposed beyond app through Intent.getData()

The app crashes when trying to open a file. It work below Android N, but on Android N it crashes. It only crashes when I try to open a file from the SD card, not from the system partition. Some permission problem?

Sample code:

File file = new File("/storage/emulated/0/test.txt");
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "text/*");
startActivity(intent); // Crashes on this line


android.os.FileUriExposedException: file:///storage/emulated/0/test.txt exposed beyond app through Intent.getData()


When targeting Android N,
URIs are not allowed anymore. We should use
URIs instead. However, my app needs to open files in root directories. Any ideas?


The current answers do not really answer my question. My app also needs to be able to open files in root directories (like /data or /system).

It is not possible to use FileProvider in those cases, because you can't give permission to a file you normally can't access.
Even if it is possible to use a content:// URI it will not work, because to edit files in root directories, you need the actual path. (So you can use it in a 'terminal command').

A possible workaround:

  • If you have 'read and write' permissions: Use FileProvider like in the other answers.

  • If you only have 'read' permissions: Open file the old way (with file:// URI).

  • If you don't have 'read' or 'write' permissions, this is a file in a root directory you shouldn't be able to access. However, the file can be opened with a workaround. Just execute the following terminal command with su (root) access within your app:

    File file = new File("/data/test.txt");
    String s = "am start -a 'android.intent.action.VIEW' -d " + getCmdPath("file://" + file.getAbsolutePath()) + " -t " + getCmdPath(mime) + " " + getCmdPath(componentName.getPackageName() + "/" + componentName.getClassName())

    (getCmdPath(String path) is just a method that puts the filename between quotation marks: '/your/path')

If you have any other or better suggestions, please let me know.