Why Your App is CrashingUpgraded your app's targetSdkVersion to 24 or higher only to find it crashing? You are likely hitting the FileUriExposedException. This happens most often when you try to open a PDF, share a JPEG, or trigger the camera. Android 7.0 (Nougat) tightened security by blocking file:// URIs from crossing app boundaries.
Your stack trace will typically look like this:
android.os.FileUriExposedException: file:///storage/emulated/0/Download/invoice.pdf exposed beyond app through Intent.getData()
The Security ShiftIn the early days of Android, sharing a file was like handing someone a physical key to a room in your house. You just passed a direct path on the disk. However, if the receiving app didn't have permission to read that specific folder, it would fail anyway. Starting with API 24, Android enforces a StrictMode policy that forbids this behavior. Now, you must use a content:// URI. This acts like a temporary guest pass, giving the other app specific, limited access to just that one file.
The Proper Fix: Implementing FileProviderThe FileProvider class in the AndroidX library is the gold standard for fixing this. It creates a secure, virtual bridge for your files.
1. Register the Provider in your ManifestFirst, tell the Android system that your app is now a file provider. Add this <provider> block inside the <application> tags of your AndroidManifest.xml.
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
Using ${applicationId}.fileprovider ensures the authority string is unique. This prevents your app from clashing with others on the user's device.
2. Map Your Shared FoldersNext, create a new file at res/xml/file_paths.xml. You must explicitly list which folders are safe to share. FileProvider won't touch anything you don't define here.
<?xml version="1.0" encoding="utf-8"?>
<paths>
<!-- Maps to context.getFilesDir() -->
<files-path name="internal_files" path="." />
<!-- Maps to context.getCacheDir() -->
<cache-path name="internal_cache" path="." />
<!-- Maps to Environment.getExternalStorageDirectory() -->
<external-path name="sd_card" path="." />
</paths>
3. Swap from File to Content URIsFinally, update your Java or Kotlin code. Replace Uri.fromFile(file) with the FileProvider version. Here is how to share a PDF securely:
// The old, crashing way:
// Uri uri = Uri.fromFile(invoiceFile);
// The secure way:
Uri contentUri = FileProvider.getUriForFile(
context,
context.getPackageName() + ".fileprovider",
invoiceFile
);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(contentUri, "application/pdf");
// Add this flag or the receiving app will still be blocked
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
context.startActivity(intent);
The "Lifeboat" Method (Not for Production)If you are maintaining a legacy codebase and need a 5-minute fix while you refactor, you can force the system to ignore the security check. Put this in your Activity.onCreate() method:
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
Use this sparingly. While it stops the crash, it doesn't solve the underlying permission issue. The receiving app might still fail to open the file because it lacks storage permissions.
How to Verify the FixBefore you ship, double-check these three points:
- Check the Logcat: Log your URI. It should now look like
content://com.example.app.fileprovider/internal_files/invoice.pdf.- Target API 24+: Always test on an emulator running Android 7.0 or newer. Older devices (API 23 and below) never cared aboutfile://URIs, so they won't reveal the bug.- Test the Handover: Open the file in a third-party app like Google Drive or VLC. If they show a "File Not Found" error, you likely missed theFLAG_GRANT_READ_URI_PERMISSIONflag.

