[Solved] – android.os.FileUriExposedException: file:///storage/emulated/0/942.jpg exposed beyond app through Intent.getData()
Today we see how to solve the android.os.FileUriExposedException Errro in android.
When we share or open any file from internal storage in android, we face this issue
android.os.FileUriExposedException: file:///storage/emulated/0/Android/data/package.name/files/Images/filename.jpg exposed beyond app through ClipData.Item.getUri()
How to Solve android.os.FileUriExposedException
In Android development, the targetSdkVersion is a parameter that specifies the highest API level that your app is aware of and designed to work with. Starting from API level 24 (Android 7.0, Nougat), if your app’s targetSdkVersion is 24 or higher, you need to use the FileProvider class to grant access to specific files or directories so that other apps can access them securely.
The FileProvider is a subclass of ContentProvider that facilitates secure sharing of files associated with your app. It generates a content URI for a file, which allows other apps to access that file while maintaining security and permissions.
To implement FileProvider, you create your own custom subclass that extends FileProvider. This custom FileProvider ensures that there are no conflicts between your app’s FileProvider and any other FileProvider instances declared in imported libraries or dependencies.
This is important because multiple libraries or dependencies might also use FileProvider, and conflicts can arise if they all define their own providers with the same authority. By creating your own FileProvider subclass and defining its unique authority, you prevent conflicts and ensure smooth interoperability between your app and any imported dependencies.
The process involves creating a file_paths.xml file in your app’s res/xml directory, where you define the paths to the files or directories that you want to share. Additionally, in the app’s manifest file, you declare your custom FileProvider class with the specified authority and file paths.
Overall, using FileProvider is necessary for apps with targetSdkVersion 24 or higher to securely share files with other apps, and creating a custom subclass helps avoid conflicts with similarly defined providers in imported dependencies.
Step 1: Add <provider> tag in android manifest
Add a FileProvider tag in AndroidManifest.xml under tag. Specify a unique authority for the android:authorities attribute to avoid conflicts, imported dependencies might specify ${applicationId}.provider and other commonly used authorities.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
...
<application
...
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
</application>
</manifest>
Step 2: Create provider_paths.xml file
Then create a provider_paths.xml file in res/xml folder. A folder may be needed to be created if it doesn’t exist yet. The content of the file is shown below. It describes that we would like to share access to the External Storage at root folder (path=”.”) with the name external_files.
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="external_files" path="."/>
</paths>
You have done it. Now you will replace our code
From
Uri uri = Uri.fromFile(fileImagePath);
To
Uri uri = FileProvider.getUriForFile(MainActivity.this, BuildConfig.APPLICATION_ID + ".provider",fileImagePath);
While you’re including the URI with an Intent make sure to add below line:
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Hope this will help you
Also read how to solve unexpected element queries found in manifest – Error