Currently, FileProvider getUriForFile method generates IllegalArgumentException when the file is on an external SD
When the file is in the device memory (under /storage/emulated/0), it works fine.
Uri videoUri = FileProvider.getUriForFile(this,
getApplicationContext().getPackageName() + ".provider",
new File(videoPath));
here videoPath had the following value :
videoPath = /storage/extSdCard/Android/data/com.podcastcutter.debug/files/episodeMp3/TEDTalks (video)/Why you should love statistics - Alan Smith.mp4
My Manifest file contains :
<provider
android:name="android.support.v4.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>
and here the provider_paths :
<external-path name="external_files" path="."/>
How can I modify the FileProvider configuration to solve this problem?
Thanks in advance.
Exception generated:
java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/extSdCard/Android/data/com.podcastcutter.debug/files/episodeMp3/TEDTalks (video)/Why you should love statistics - Alan Smith.mp4
android.support.v4.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.java:711)
android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:400)
Additional Configuration information:
compileSdkVersion 25
buildToolsVersion "23.0.3"
minSdkVersion 16
targetSdkVersion 25
support libraries version : 25.1.1
I added in my provider.xml this line and works fine to get file URI from SD card:
<root-path name="external_files" path="/storage/" />
Complete xml file:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="external_files"
path="." />
<root-path
name="external_files"
path="/storage/" />
</paths>
How can I modify the FileProvider configuration to solve this problem?
You can't. FileProvider does not support removable storage.
Your provider path is the wrong type. Your videoPath shows a path to your app's external storage but your provider path is using external-path which links to the device root external storage. (/storage/emulated/0)
Change your provider path to be <external-files-path>...</external-files-path>
Related
I am using FileProvider to install apk from my app. Followed many stackoverflow questions but still facing this issue
java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Android/data/com.tssi.myapptour/files/download/myapp_newSigned.apk
My provider in manifest
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.tssi.myapptour.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths" />
</provider>
my file_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="download" path="download/" />
<!-- <external-path name="download" path="Android/data/com.tssi.myapptour/files/download/" />-->
</paths>
And my code for calling apk
String strApkToInstall = "myapp_newSigned.apk";
File fileApkToInstall = new File(getExternalFilesDir("download"), strApkToInstall);
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri fileUri = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".provider",
fileApkToInstall);
intent.setDataAndType(fileUri, "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);
Your file is in getExternalFilesDir(). That does not match files-path in your FileProvider metadata. Either:
Switch to getFilesDir() (a much better solution from a security standpoint), or
Switch to external-files-path
See the FileProvider documentation for more about the mapping between filesystem locations and metadata entries.
I have an Image File stored in sd card with an Absolute path as - storage/4469-0C17/DCIM/... and another image stored in internal storage with an absolute path - /storage/emulated/0/
I am using FileProvider to share it with external apps.
Now, I am able to share images stored in internal-storage but for the image stored in external storage, it throws an error as -
java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/4469-0C17/DCIM/....
My Manifest -
<manifest>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application>
.....
<provider
android:name="android.support.v4.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>
provider_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>
Code -
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("image/*");
File imageFileToShare = new File(filePath);
Uri imageURI = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", imageFileToShare);
share.putExtra(Intent.EXTRA_STREAM, imageURI);
share.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
context.startActivity(Intent.createChooser(share, "Share Image"));
and another image stored in internal storage with an absolute path
That is what the Android SDK refers to as external storage.
but for the image stored in external storage, it throws an error as -
java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/4469-0C17/DCIM/....
First, that is removable storage, not external storage.
Second, FileProvider does not support removable storage.
Instead of using FileProvider which as you have seen yourself is very limited you better derive your own provider from ContentProvider.
Then you can serve any file you want.
CommonsWare has a nice example how to set up such a file provider.
Add to your provider_paths.xml this:
<root-path path="." name="external_files" />
I'm trying to set up a fileprovider for sharing file. My files are saved in a folder "AppName" in the external storage (same level as Android, Movies and Pictures folders).
Here is my file provider config :
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.mydomain.appname.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths"/>
</provider>
and the file_paths.xml :
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="mypath" path="AppName" />
</paths>
When i try to access my file with :
Uri fileUri = FileProvider.getUriForFile(activity, "com.mydomain.appname.fileprovider",
new File("/storage/emulated/0/AppName/IMG_20160419_095211.jpg"));
It returns an error:
java.lang.IllegalArgumentException:
Failed to find configured root that contains /storage/emulated/0/AppName/IMG_20160419_095211.jpg
at android.support.v4.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.java:678)
at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:377)
It worked fine before when I was using built-in directory like Pictures or Movies, my file_paths.xml was define like this :
<external-path name="photos" path="Pictures" />
<external-path name="videos" path="Movies" />
But now I want to store my file in my own folder. Did I miss something with the FileProvider config ?
<files-path name="name" path="path" />
Represents files in the files/ subdirectory of your app's internal storage area. This subdirectory is the same as the value
returned by Context.getFilesDir().
<external-path name="name" path="path" />
Represents files in the root of the external storage area. The root
path of this subdirectory is the same as the value returned by
Environment.getExternalStorageDirectory().
<external-files-path name="name" path="path" />
Represents files in the root of your app's external storage area. The
root path of this subdirectory is the same as the value returned by
Context#getExternalFilesDir(String) Context.getExternalFilesDir(null).
for more details please check Android's doc of FileProvider.
some configuration like following picture,com.view.asim.enterprise is my package name.
First, I know this is an old post but it's the closest question posted that was similar to my problem so I'll post my solution.
The reason for that error is because the path you're supplying in the provider file is either
a) Spelled incorrectly and doesn't exist in the external-path
b) Using the /storage/emulated/0 absolute path
It returns Failed to find configured root that contains ... because it can't find that folder. So make sure you write only the directory you want to share, and ensure it's spelled correctly. Remember that when you declare external-path it is the equivelant of calling Enviornment.getExternalStorageDirectory() Since you write the name of the directory when you create your file, you don't need to provide a path in your provider file as all it does is mask whatever value is in the path with the name.
So your provider path would be:
<external-path name="my_files" />
and your code would be:
File file = new File(new File(Environment.getExternalStorageDirectory(), "myfolder"), "file.ext");
Uri uri = FileProvider.getUriForFile(context, fileProvider, file);
Your uri path would then yield the following
content://fileprovider/my_files/myfolder/file.ext
If you had supplied a path in your provider file then your uri path would look like this:
content://fileprovider/my_files/file.ext
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="external_files"
path="." />
<external-files-path
name="external_files"
path="." />
<!-- FOR SD CARD-->
<root-path
name="sdcard1"
path="." />
</paths>
I fixed it
<!--THIS IS EVIL-->
<root-path
name="sdcard1"
path="." />
File Provider
java.lang.IllegalArgumentException: Failed to find configured root that contains
It is due to path is configured correctly in fileprovider_path.xml declared in manifest.
whether it may be image path external-file path etc so declare as mentioned.
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="external"
path="." />
<external-files-path
name="external_files"
path="." />
<files-path
name="files"
path="." />
</paths>
I had the same thing. In my case I had to clean the build in Android Studio (Build > Clean Project) every time I modified the path of the fileprovider in 'file_paths.xml'.
In <external-path name="mypath" path="AppName" />
name="mypath" - mypath must be a specific piece from your image file name, say name="IMG" would work if all your image files have "IMG" in their name, judging by your sample code it is the case here.
path="AppName" is a folder name that you created in external for your images and it needs "/" at the end, i.e. path="AppName/"
so, <external-path name="IMG" path="AppName/" /> should do it and FileProvider should find and let other apps access your images when you request Uri with FileProvider.getUriForFile().
Hope it helps.
Replace your xml path with
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-files-path
name="extfiles" path="."/> </paths>
I am trying to use FileProvider to play a video from private path.Facing
java.lang.IllegalArgumentException: Failed to find configured root that contains /data/data/XXXXX(Package)/files/Videos/final.mp4
Code:
<paths>
<files-path path="my_docs" name="Videos/" />
</paths>
Java code:
File imagePath = new File(getFilesDir(), "Videos");
File newFile = new File(imagePath, "final.mp4");
Log.d(TAG, "-------------newFile:"+newFile.exists());//True here
//Exception in below line
Uri contentUri = FileProvider.getUriForFile(this,"com.wow.fileprovider", newFile);
Manifest.xml
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.wow.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths" />
Any clues on this?
Thanks
Nitz
You have your name and your path flipped. name is what goes in the Uri, and path is the relative location within the root on the filesystem.
Go with:
<paths>
<files-path name="my_docs" path="Videos/" />
</paths>
change your provider XML to this.
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="external_files" path="." />
<root-path name="external_files" path="/storage/" />
</paths>
I had the very same basic situation. I defined everything correctly (files-path in xml) but there is one more thing which leads to the same exception. I add another answer just as an addition and a comment would not be well readable.
I created/read the directory where i store the files like:
context.getDir("Documents", Context.MODE_PRIVATE)
This leads to a path like:
/data/user/0/ch.myapp/app_Documents/6c3c70d5-af66-48ef-8dfc-f4341de4e1bd.docx
Then i changed creating the directory to:
File directory = new File(context.getFilesDir(), "Documents");
if (!directory.exists()) {
directory.mkdir();
}
This leads to a path like:
/data/user/0/ch.myapp/files/Documents/6c3c70d5-af66-48ef-8dfc-f4341de4e1bd.docx
According to the documentation Open a directory the two methods should be equivalent as far as i understand it. But it creates a different path... Maybe the formulation is just not clear for me in the documentation, but for me its wrongly written.
getDir(name, mode)
Creates a new directory (or opens an existing directory) within your
app's unique file system directory. This new directory appears inside
the directory provided by getFilesDir().
I am trying to implement a FileProvider to allow me to share local, private images with email and other apps. I have been following the instructions of the Android Developers Guide and get down to where I have to use the "getUriForFile" function and Eclipse tells me I have to create the method. I was under the impression this should be in the android.support.v4.content package and it is in the Referenced Libraries for the app, but it is not there.
I have added the following to my Manifest:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.gelbintergalactic.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/my_paths" />
</provider>
I have created this xml file:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="files" path="." />
</paths>
But when I get to this point in my code I am stymied:
Uri contentUri = getUriForFile(this, "com.gelbintergalactic.fileprovider", newfile);
What step am I missing?
Yes, instructions in dev guide are not the greatest. getUriForFile() is a static method of the FileProvider class so you need to do:
Uri contentUri =
FileProvider.getUriForFile(this, "com.gelbintergalactic.fileprovider", newfile);