Android : Fix URI Restrictions 🔥
Safely Accessing URI in Android Without Restrictions

Senior Android Engineer from Bangladesh. Love to contribute in Open-Source. Indie Music Producer.
Search for a command to run...
Safely Accessing URI in Android Without Restrictions

Senior Android Engineer from Bangladesh. Love to contribute in Open-Source. Indie Music Producer.
No comments yet. Be the first to comment.
In this series, I will write about Android App Development.
Hello, and welcome to this article where we will delve into a Jetpack Compose function that is not only lifecycle-aware but also adept at checking internet connectivity using the most up-to-date APIs available. This function is designed to utilize th...
A practical guide to choosing the right coroutine primitive for your Android/Kotlin projects

This guide explains what Channels are, when to use them, how to use them correctly, and when NOT to use them — in simple, professional language. 1. What problem do Channels solve? In Kotlin coroutines, you often have multiple coroutines running at t...

Learn how to build preview-safe ViewModels in Jetpack Compose using Hilt.

HandlerInterceptor vs Filter in Spring Boot: A Practical Guide with JNDI Injection Prevention

Simple In-Memory Caching: A Tiny Trick with Massive Impact

When working with files in Android, we often come across content:// URIs from file pickers, downloads, or external storage. However, WebView, third-party libraries, or some APIs might not accept content:// URIs directly, which can cause errors such as:
java.lang.IllegalArgumentException: Uri lacks 'file' scheme
Android enforces strict scoped storage policies, so directly converting content:// to [file://](file://) is no longer allowed. Instead, we use a secure method to create a temporary file and provide access through FileProvider.
content:// Directly?Modern Android security policies prevent apps from accessing another app's files directly. If we try to use a content:// URI in WebView or share it externally, we'll often run into:
SecurityException (Permission Denied)
IllegalArgumentException (URI Lacks 'File' Scheme)
File Not Found Exception
To safely access and use content:// URIs, we convert them into a secure [file://](file://) URI using a FileProvider.
content:// to a Secure File URI→ Step 1: Add FileProvider to AndroidManifest.xml
First, register FileProvider inside <application>:
<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/provider_paths" />
</provider>
The
${applicationId}.fileProvidershould match our app's package.
→ Step 2: Define Secure File Paths
Create a new XML file res/xml/provider_paths.xml to specify which directories can be accessed:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<cache-path name="cache" path="." />
<external-files-path name="external_files" path="." />
</paths>
This ensures only files in cache or external storage can be shared securely.
→ Step 3: Convert content:// to a Secure URI
Now, use this Kotlin function to safely access any Uri:
class FailedToEnableAccessForURI(override val message: String = "Failed to provide access.") : Exception()
fun Uri.grantAppAccess(context: Context): Uri {
return try {
// Get the file extension from the original Uri
val fileExtension = context.contentResolver.getType(this)?.let { MimeTypeMap.getSingleton().getExtensionFromMimeType(it) }
?: "tmp" // Default to "tmp" if the extension cannot be determined
// Open an input stream for the URI (reads the content of the file)
val inputStream = context.contentResolver.openInputStream(this)
?: throw FailedToEnableAccessForURI("Input stream is null.")
// Create a temporary file in the app's cache directory with the correct extension
val tempFile = File(context.cacheDir, "upload_${System.currentTimeMillis()}.$fileExtension")
// Write the input stream's data to the temporary file
FileOutputStream(tempFile).use { output ->
inputStream.copyTo(output)
}
// Close the input stream after usage
inputStream.close()
// Generate a URI for the temp file using FileProvider
FileProvider.getUriForFile(context, "${context.packageName}.fileProvider", tempFile)
} catch (e: Exception) {
throw FailedToEnableAccessForURI().apply {
this.stackTrace = e.stackTrace
}
}
}
→ Step 4: How to Use It?
Use this function whenever you need a secure file URI:
val secureUri = selectedUri.grantAppAccess(context)
webView.loadUrl(secureUri.toString()) // ✅ No more URI access issues!
Bypasses restrictions on content:// URIs
Creates a temporary file for easy access
Works with WebView, File Uploads, and Third-party APIs
Follows Android security policies (Scoped Storage, FileProvider)
If our app is multi-modular, or each module has its own FileProvider, we need to be careful about URI authority conflicts. Here’s what we need to consider:
If each module registers its own FileProvider, the authority must be unique.
For example:
Main app (com.myapp.main) → "com.myapp.main.fileprovider"
Module A (com.myapp.modulea) → "com.myapp.modulea.fileprovider"
Module B (com.myapp.moduleb) → "com.myapp.moduleb.fileprovider"
If two modules use the same authority, the app might crash or fail to resolve URIs.
If we are calling FileProvider.getUriForFile(), we must use the correct authority for the module handling the file:
FileProvider.getUriForFile(context, "com.myapp.modulea.fileprovider", file)
Do not hardcode the main app’s authority unless the module explicitly shares its FileProvider.
When sharing a file URI between modules, we must grant temporary access permissions:
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
Otherwise, the receiving module won’t be able to read the file.
Instead of multiple FileProviders, we can define one FileProvider in the main app and let all modules use it:
Declare FileProvider in the Main App (com.myapp.main.fileprovider)
All modules use com.myapp.main.fileprovider instead of their own
This avoids confusion, duplicate authorities, and makes URI access easier across the app.
If we get an error like "Couldn't find meta-data for provider", check:
Does the module have its own FileProvider?
Are we using the correct authority?
Does provider_paths.xml exist in the correct module?
Use unique authorities for each module’s FileProvider
Use the correct authority when generating URIs
Grant read/write permissions when sharing URIs
Consider a single centralized FileProvider to simplify access
With these best practices, we can safely access Uri files in Android without security restrictions—even in multi-modular apps!
That’s for today. Happy Coding…