| name | android-file-provider |
| description | Best practices for configuring Android FileProvider. Invoke when setting up file sharing, fixing exposed file uri exceptions, or configuring file_paths.xml. |
Android FileProvider Configuration Guide
This skill provides a secure and comprehensive configuration guide for Android FileProvider, ensuring compliance with Android 7.0+ (API 24+) strict file sharing policies and Android 10+ (API 29+) Scoped Storage requirements.
🚀 Core Principles
- Least Privilege: Only expose necessary subdirectories, avoid exposing the entire root (
.).
- Explicit Mapping: Map specific paths (e.g.,
Download/, Pictures/) instead of broad wildcards.
- Scoped Storage: Respect Android 10+ storage isolation; prefer
Context.getExternalFilesDir() over raw SD card paths.
📁 Recommended res/xml/file_paths.xml
Use this structure to balance security and compatibility.
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path name="internal_shared" path="shared/" />
<files-path name="internal_root" path="." />
<cache-path name="internal_cache" path="." />
<external-files-path name="external_files" path="." />
<external-cache-path name="external_cache" path="." />
<external-media-path name="external_media" path="." />
<external-path name="external_download" path="Download/" />
<external-path name="external_pictures" path="Pictures/" />
<external-path name="external_dcim" path="DCIM/" />
<external-path name="external_documents" path="Documents/" />
<external-path name="external_root" path="." />
</paths>
⚙️ Manifest Configuration
Ensure your AndroidManifest.xml correctly references the XML file.
<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>
💻 Usage Examples (Kotlin)
1. Sharing a File (Common Scenario)
This is the standard way to share a file (e.g., PDF, Image) with another app.
fun shareFile(context: Context) {
val sharedDir = File(context.filesDir, "shared")
if (!sharedDir.exists()) sharedDir.mkdirs()
val file = File(sharedDir, "report.pdf")
val uri = FileProvider.getUriForFile(
context,
"${context.packageName}.fileprovider",
file
)
val intent = Intent(Intent.ACTION_SEND).apply {
type = "application/pdf"
putExtra(Intent.EXTRA_STREAM, uri)
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
context.startActivity(Intent.createChooser(intent, "Share File"))
}
2. Installing an APK (Android 7.0+)
Installing an APK requires REQUEST_INSTALL_PACKAGES permission and FileProvider.
fun installApk(context: Context, apkFile: File) {
val intent = Intent(Intent.ACTION_VIEW)
val uri = FileProvider.getUriForFile(
context,
"${context.packageName}.fileprovider",
apkFile
)
intent.setDataAndType(uri, "application/vnd.android.package-archive")
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(intent)
}
3. Taking a Photo (Camera Intent)
Pass a FileProvider URI to the camera app to save the captured image.
fun dispatchTakePictureIntent(activity: Activity, photoFile: File, requestCode: Int) {
val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
val photoURI: Uri = FileProvider.getUriForFile(
activity,
"${activity.packageName}.fileprovider",
photoFile
)
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI)
takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
if (takePictureIntent.resolveActivity(activity.packageManager) != null) {
activity.startActivityForResult(takePictureIntent, requestCode)
}
}
⚠️ Common Pitfalls
IllegalArgumentException: Failed to find configured root:
- Cause: The file you are trying to share is located in a path not declared in
file_paths.xml.
- Fix: Ensure the file's parent directory matches one of the
<*-path> entries.
SecurityException: Permission Denial:
- Cause: Forgetting
FLAG_GRANT_READ_URI_PERMISSION.
- Fix: Always add this flag to your Intent.
- Root Path Exposure:
- Risk:
<external-path path="."/> allows access to any file on the SD card if the attacker guesses the path.
- Fix: Use specific subdirectories (e.g.,
Download/) as shown above.