FileUriExposed Exception?

Rishikesh Pathak
2 min readMay 8, 2017

--

Android may throw “ FileUriExposedException” in Android 7.0 (API level 24) and above,this exception will come when you will expose a file:// URIs outside your package domain through intent .

For apps targeting Android 7.0, the Android framework enforces the strict mode API policy that prohibits exposing file:// URIs outside your app. If an intent containing a file URI leaves your app, the app fails with a FileUriExposedException.

Your Exception will be like this:

08-05 17:30:00.476 22265-22265/ com.example.fileE/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.file, PID: 22265
android.os.FileUriExposedException: file:///storage/emulated/0/example/ profilePic.jpg exposed beyond app through ClipData.Item.getUri()
......

So wondering how to avoid this exception then follow below steps:

Note:Considering you already given Runtime Permission for Camera and Storage.

Step 1:

You have to define a FileProvider for your app for that you have to give <provider> element in your manifest see example.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.file">
<application
...>
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.example.file.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_provider_path"/>
</provider>
...
</application>
</manifest>

Here authorities name should be unique thats why i used package name +.provider.

And the <meta-data> child element of the <provider> points to an XML file that specifies the directories you want to share.

Step 2:

Create file_provider_path.xml in the res/xml/ subdirectory of your project.

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

Here i am giving file name “example” of external storage.if your file path is in internal storage then you can give <files-path> element in place of <external-path>

Step 3:

Now for sending file:// uri to other app i will take example to open Camera App ,

For getting URI earlier we used to do like this

Uri photoURI = Uri.fromFile(file);

So we have to do like this now

Uri photoUri =     FileProvider.getUriForFile(Context,"com.example.file.provider", file);

check below example:

String fileName = "profilePic";

String path = Environment.getExternalStorageDirectory().getAbsolutePath()+ "/example";

File file = new File(path,fileName+".jpg");

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//We have to check if it's nougat or not.if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M)
{
Uri photoUri = FileProvider.getUriForFile(Context,"com.example.file.provider", file);

intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
}
else
{
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));

}



intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);



if (intent.resolveActivity(getApplicationContext().getPackageManager()) != null) {

startActivityForResult(intent, REQUEST_CODE_CAMERA);

}

Ya that’s it,So FileProvider will return following URI

content://com.example.file.provider/image_capture/profilePic.jpg

that is nothing but combination of these:

content://”android:authorities you give to provider in manifest”/”<external-path name>, you given in file_provider_path.xml”/”your fileName”

Welldone ! Your application should now work perfectly fine on any Android version including Android Nougat.

--

--