FileUriExposed Exception?
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.