I'm sorry to ask an overly repeated question, but any of the answer here on stackoverflow really helped me.
I want to use a FileProvider to access file to a custom folder. My declaration in the manifest, inside the <application> tag:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="my.package.name.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths" />
</provider>
then, in provider_paths.xml
<paths>
<cache-path name="my_videos" path="MyFolderName/"/>
</paths>
(but I tried, instead of cache-path, files-path, external-path and external-files-path)
The creation of my files is:
public static Uri getUriFromFile(File file, Context context) {
int flags = Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
Uri uri = FileProvider.getUriForFile(context, context.getPackageName() + ".provider", file);
context.grantUriPermission(context.getPackageName(), uri, flags);
return uri;
}
public static File getMyDirectory() {
File root = new File(context.getCacheDir(), "MyFolderName");
if(root.mkdir()) Log.e(Consts.TAG, "Directory created");
return root;
}
...
File outputFile = new File(getMyDirectory(), filename + ".mp4");
videoUri = getUriFromFile(outputFile, this);
(and, instead of context.getCacheDir(), I tried context.getFilesDir(), Environment.getExternalStorageDirectory() and context.getExternalFilesDir(""))
and finally, I want to retrieve my file:
String pathToFile = "/my_videos/filename.mp4";
Uri file = getUriFromFile(new File(pathToFile), context);
tried with paths:
"/MyFolderName/filename.mp4"
"content://my.package.name.provider/my_videos/filename.mp4"
"content://my.package.name.provider/MyFolderName/filename.mp4"
ALL of this tries brought me to this error:
Failed to find configured root that contains /my_videos/filename.mp4
Any idea on what I am doing wrong? Thanks in advance!
I want to retrieve my file:
None of those are valid paths to the file.
You already have code that gives you a valid path to the file:
File outputFile = new File(getMyDirectory(), filename + ".mp4");
So, use the code that you already wrote.
Related
This question already has answers here:
how to fix an authority error in android studio
(2 answers)
Couldn't find meta-data for provider with authority
(16 answers)
Closed 3 years ago.
I am trying to develop an app that takes photos, and later that uploads them to a database. Right now I am stucked at taking a good quality photo. As I read before, to get a better quality photo you need to save it in your directories. I am following the Google Take Photos
from developers instructions, and after adding all the methods and provider and so on, I get the error :
Couldn't find meta-data for provider with authority com.example.navigationdrawerfinal.
I've left the name of my app so everyone can see that I changed it in manifest too.
Manifest:
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.example.navigationdrawerfinal.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths" />
</provider>
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="#string/google_maps_key" />
file_paths.xml :
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="my_images" path="Android/data/com.example.navigationdrawerfinal/files/Pictures" />
</paths>
and the code where I use it:
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(this,
"com.example.navigationdrawerfinal",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
poza_neincarcata.setVisibility(View.GONE);
poza_tick.setVisibility(View.VISIBLE);
}
}
}
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
currentPhotoPath = image.getAbsolutePath();
return image;
}
As indicated by the error (emphasis is mine):
Couldn't find meta-data for provider with authority com.example.navigationdrawerfinal.
This is because you've specified the incorrect FileProvider needed for the photoURI variable you've defined - it should exactly be the same as the FileProvider you've defined in your manifest file, case-sensitive:
Uri photoURI = FileProvider.getUriForFile(this,
"com.example.navigationdrawerfinal.fileprovider", // Over here
photoFile);
By the way, it's a good idea to follow the Java guidelines by naming your classes in PascalCase format.
For e.g.:
FileProvider vs fileprovider
MainActivity vs mainActivity
etc.
in our manifest change like this
<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/file_paths"></meta-data>
</provider>
This is a part of my manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.asd"
android:versionCode="118"
android:versionName="118" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="19" />
<application
android:name="com.example.asd.AsdApplication"
android:allowBackup="true"
android:allowTaskReparenting="true"
android:theme="#style/AsdTheme" >
...
<provider
android:name="com.example.asd.database.hq.ContentProviderDB"
android:authorities="ourContentProviderAuthorities" >
</provider>
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.example.asd.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/filepaths" />
</provider>
...
</application>
</manifest>
This is the filepaths file in raw/xml/filepaths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="media"/>
</paths>
I download a video from internet and save it to internal storage this way:
public static boolean saveInputStreamToInternalStorageFile(Context context, String filename, byte[] dataToWrite, Context ctx) {
FileOutputStream fos;
try {
fos = new FileOutputStream(context.getFilesDir() + File.separator + filename);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(dataToWrite);
oos.close();
return true;
} catch (FileNotFoundException e) {
e.printStackTrace();
return false;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
I try to use it like so:
private void playVideoFromDeviceWithWorkaround(String fileName) {
File newFile = new File(getFilesDir(), fileName);
Uri contentUri = FileProvider.getUriForFile(getApplicationContext(), "com.example.asd", newFile);
try {
vvVideoFullscreen.setVideoURI(contentUri);
showMediaControls = true;
playVideo();
} catch (Exception e) {
playVideoFromNetwork();
}
}
At this line:
Uri contentUri = FileProvider.getUriForFile(getApplicationContext(), "com.example.asd", newFile);
I get the following error:
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.XmlResourceParser android.content.pm.ProviderInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)' on a null object reference
at android.support.v4.content.FileProvider.parsePathStrategy(FileProvider.java:560)
at android.support.v4.content.FileProvider.getPathStrategy(FileProvider.java:534)
at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:376)
The problem was that in Manifest I had this line:
android:authorities="com.example.asd.fileprovider"
and when calling getUriForFile I was passing:
Uri contentUri = FileProvider.getUriForFile(getApplicationContext(), "com.example.asd", newFile);
So changed from "com.example.asd" to "com.example.asd.fileprovider" and it worked
You can do this without hardcoding the package name with an additional benefit of being able to run multiple variants on the same device (think release and debug with applicationIdSuffix, see these issues):
Based on FileProvider.java:560
final ProviderInfo info = context.getPackageManager()
.resolveContentProvider(authority, PackageManager.GET_META_DATA);
final XmlResourceParser in = info.loadXmlMetaData( //560
context.getPackageManager(), META_DATA_FILE_PROVIDER_PATHS);
you were using the wrong authority and it didn't find the ContentProvider (info == null).
Change your manifest to (${applicationId} will be replaced by Manifest Merger)
android:authorities="${applicationId}.share"
and
Uri uri = FileProvider.getUriForFile(context, context.getPackageName() + ".share", result);
The .share suffix is optional, in case you have a real ContentProvider which is better to have the package name as the authority.
In my case, I got the error because the
BuildConfig.APPLICATION_ID
was being imported from
import android.support.v4.BuildConfig;
So the string it returned was "android.support.v4" instead of my project package name. Check out the import file is from your import project.Buildconfig and not another. Example:
import com.example.yourProjectName.BuildConfig;
Finally, in <provider> tag in Manifest I have android:authorities="${applicationId}" to always get my project package name as the authority
<manifest>
..
..
<application>
..
..
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/ruta_fileprovider" />
</provider>
</application>
</manifest>
First, be sure that you provider android:authorities does not conflict with your other providers. Besides that you may choose any name for the last part of its name: "provider", "fileprovider" etc., but app crashes when there are more than one android:authorities listed, while documentation states that it allows multiple values listed.
file:// scheme is now not allowed to be attached with Intent on targetSdkVersion >= 24 (Android N 7.0), only content:// is always passed for all devices (Android 5, 6 and 7). But we encountered that Xiaomi breaks this Google convention and sends file://, hence data.getData().getAuthority() gives empty string.
final String uriScheme = currentUri.getScheme();
if ("content".equals(uriScheme)) {
// getting full file path (works with some providers, i.e. Gallery)
path = FileUtils.getPath(getContext(), currentUri);
if (path != null) {
currentFile = new File(path);
}
} else if ("file".equals(uriScheme)) {
// in a rare case we received file:// in currentUri, we need to:
// 1. create new File variable from currentUri that looks like "file:///storage/emulated/0/download/50044382b.jpg"
// 2. generate a proper content:// Uri for it
currentFile = new File(currentUri.getPath());
String authority = data.getData().getAuthority();
if (authority != null && !authority.isEmpty()) {
currentUri = FileProvider.getUriForFile(getActivity(), authority, currentFile);
}
} else {
// throw exception
}
Also, the bug when FileProvider.getUriForFile() resulted in crash java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Android/data/com.example/files/attachments/image.jpg was fixed in Android Support Library v24.2.0. The problem was that FileProvider.java did not see external-path folders.
If you're building your AUTHORITY at runtime using BuildConfig make sure you use the full class name including your package name.
Bad:
final String AUTHORITY = BuildConfig.APPLICATION_ID + ".provider";
Good:
final String AUTHORITY = com.mycompany.myapp.BuildConfig.APPLICATION_ID + ".provider";
Following worked for me.
mUri = FileProvider.getUriForFile(this,
BuildConfig.APPLICATION_ID + ".provider",
fileObject);
Here is what i did to fix the issue. I gave fully qualified name in android:name. It works in android 6,7,8
<provider android:authorities="${applicationId}.opener.provider"
android:exported="false" android:grantUriPermissions="true"
android:name="io.github.pwlin.cordova.plugins.fileopener2.FileProvider">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="#xml/provider_paths" />
</provider>
You should try it:
Context context = PostAdapter.this.activity;
StringBuilder stringBuilder2 = new StringBuilder();
stringBuilder2.append(PostAdapter.this.activity.getPackageName());
stringBuilder2.append(".provider");
Uri uri;
uri = FileProvider.getUriForFile(context,stringBuilder2.toString(), newFile);
This is what you need to do:
Uri fileURI = FileProvider.getUriForFile(getActivity(), getActivity().getPackageName() + ".fileprovider", file);
I am capturing images from android application and saving images in external storage using Fileprovider. But it is giving me an exception as follow
java.lang.IllegalArgumentException:
Failed to find configured root that contains /data/data/com.rocketstove/files/SAMS/JMC-R-1256655/application_form_first.jpg
I have configured provider in androidManifest like this
<provider
android:name="android.support.v4.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>
I have also add following line in file_paths
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="external_files"
path="." />
</paths>
In java code
if (Build.VERSION.SDK_INT >= 23) {
File imagePath = new File(getActivity().getFilesDir(), "SAMS");
if (!imagePath.exists()) {
imagePath.mkdir();
}
imagePath = new File(getActivity().getFilesDir() + "/SAMS", rocketId);
if (!imagePath.exists()) {
imagePath.mkdir();
}
File imageFile = new File(imagePath.getPath(), filename);
intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
String authority = getActivity().getApplicationContext().getPackageName() + ".fileprovider";
Uri uri = FileProvider.getUriForFile(getActivity(), authority, imageFile);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivity(intent);
}
Edit
file_paths
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-files-path name="external_files" path="Android/data/com.rocketstove.files/"/>
</paths>
Java code
if (Build.VERSION.SDK_INT >= 23) {
File file
=getActivity().getExternalFilesDir(null);
File imagePath = new File(file , rocketId);
if (!imagePath.exists()) {
imagePath.mkdir();
}
File imageFile = new File(imagePath.getPath(), filename);
intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
String authority = getActivity().getApplicationContext().getPackageName() + ".fileprovider";
Uri uri = FileProvider.getUriForFile(getActivity(), authority, imageFile);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivity(intent);
}
Error
ava.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Android/data/com.rocketstove/files/JMC-R-4555555/application_form_first.jpg
at android.support.v4.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.java:719)
at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:404)
I have also add following line in file_paths
You have external-path. The documentation states that this:
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().
That is not where your File points to.
Change external-path to files-path, since your Java code uses getFilesDir().
I am creating a PDF file and saving it in local storage. When trying to open it, it is working perfect in all devices except in Android N. I am able to open PDF file in Android N using FileProvider, but it is displaying as blank.
This is my URI
content://com.products.provider/external_storage_root/Android/data/com.products/in_17052017_170502_1_1001.pdf
This is my code
Uri path;
File pdfFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/"
+ "Android" + "/" + "data" + "/" + "com.products" + "/" + file);
if (Build.VERSION.SDK_INT >= 24) {
path = FileProvider.getUriForFile(getActivity(), "com.products.provider", pdfFile);
} else {
path = Uri.fromFile(pdfFile);
}
// Setting the intent for pdf reader
Intent pdfIntent = new Intent(Intent.ACTION_VIEW);
pdfIntent.setDataAndType(path, "application/pdf");
pdfIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
pdfIntent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
try {
startActivity(pdfIntent);
} catch (ActivityNotFoundException e) {
Toast.makeText(getActivity(), "Can't read pdf file", Toast.LENGTH_SHORT).show();
}
The problem is with how you are setting the flags on the intent
pdfIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
pdfIntent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
Instead, try this:
pdfIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
pdfIntent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
Grzegorz Matyszczak's solution worked for my case. I had a very similar setup to Sabya Sachi. More specifically this line allowed me to see the PDF file (URI from FileProvider.getURIForFile call):
pdfIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
More info on grantUriPermissions here, under android:grantUriPermissions section.
As I can see that you have used FileProvider for Nougat.
You have to add a FileProvider tag in AndroidManifest.xml.
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.mydomain.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
</provider>
A FileProvider can only generate a content URI for files in directories that you specify beforehand.To link this file to the FileProvider, add a element as a child of the element that defines the FileProvider.
<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/file_paths"/>
</provider>
You must specify a child element of for each directory that contains files for which you want content URIs. You can add them to a new file called res/xml/file_paths.xml. For example ,these XML elements specify two directories:
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="my_images" path="images/"/>
<files-path name="my_docs" path="docs/"/>
</paths>
->you have to set your PDF directory path in file_paths.xml
For more detail refer this
Replace FileProvider class with MyFileProvider class:
path = MyFileProvider.getUriForFile(getActivity(), "com.products.provider", pdfFile);
where MyFileProvider should be a generic class which extends FileProvider:
public class MyFileProvider extends FileProvider {
}
Modify AndroidManifest by setting your MyFileProvider class location to android:name attribute in your provider section:
android:name=".utils.MyFileProvider"
This is a part of my manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.asd"
android:versionCode="118"
android:versionName="118" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="19" />
<application
android:name="com.example.asd.AsdApplication"
android:allowBackup="true"
android:allowTaskReparenting="true"
android:theme="#style/AsdTheme" >
...
<provider
android:name="com.example.asd.database.hq.ContentProviderDB"
android:authorities="ourContentProviderAuthorities" >
</provider>
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.example.asd.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/filepaths" />
</provider>
...
</application>
</manifest>
This is the filepaths file in raw/xml/filepaths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="media"/>
</paths>
I download a video from internet and save it to internal storage this way:
public static boolean saveInputStreamToInternalStorageFile(Context context, String filename, byte[] dataToWrite, Context ctx) {
FileOutputStream fos;
try {
fos = new FileOutputStream(context.getFilesDir() + File.separator + filename);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(dataToWrite);
oos.close();
return true;
} catch (FileNotFoundException e) {
e.printStackTrace();
return false;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
I try to use it like so:
private void playVideoFromDeviceWithWorkaround(String fileName) {
File newFile = new File(getFilesDir(), fileName);
Uri contentUri = FileProvider.getUriForFile(getApplicationContext(), "com.example.asd", newFile);
try {
vvVideoFullscreen.setVideoURI(contentUri);
showMediaControls = true;
playVideo();
} catch (Exception e) {
playVideoFromNetwork();
}
}
At this line:
Uri contentUri = FileProvider.getUriForFile(getApplicationContext(), "com.example.asd", newFile);
I get the following error:
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.XmlResourceParser android.content.pm.ProviderInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)' on a null object reference
at android.support.v4.content.FileProvider.parsePathStrategy(FileProvider.java:560)
at android.support.v4.content.FileProvider.getPathStrategy(FileProvider.java:534)
at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:376)
The problem was that in Manifest I had this line:
android:authorities="com.example.asd.fileprovider"
and when calling getUriForFile I was passing:
Uri contentUri = FileProvider.getUriForFile(getApplicationContext(), "com.example.asd", newFile);
So changed from "com.example.asd" to "com.example.asd.fileprovider" and it worked
You can do this without hardcoding the package name with an additional benefit of being able to run multiple variants on the same device (think release and debug with applicationIdSuffix, see these issues):
Based on FileProvider.java:560
final ProviderInfo info = context.getPackageManager()
.resolveContentProvider(authority, PackageManager.GET_META_DATA);
final XmlResourceParser in = info.loadXmlMetaData( //560
context.getPackageManager(), META_DATA_FILE_PROVIDER_PATHS);
you were using the wrong authority and it didn't find the ContentProvider (info == null).
Change your manifest to (${applicationId} will be replaced by Manifest Merger)
android:authorities="${applicationId}.share"
and
Uri uri = FileProvider.getUriForFile(context, context.getPackageName() + ".share", result);
The .share suffix is optional, in case you have a real ContentProvider which is better to have the package name as the authority.
In my case, I got the error because the
BuildConfig.APPLICATION_ID
was being imported from
import android.support.v4.BuildConfig;
So the string it returned was "android.support.v4" instead of my project package name. Check out the import file is from your import project.Buildconfig and not another. Example:
import com.example.yourProjectName.BuildConfig;
Finally, in <provider> tag in Manifest I have android:authorities="${applicationId}" to always get my project package name as the authority
<manifest>
..
..
<application>
..
..
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/ruta_fileprovider" />
</provider>
</application>
</manifest>
First, be sure that you provider android:authorities does not conflict with your other providers. Besides that you may choose any name for the last part of its name: "provider", "fileprovider" etc., but app crashes when there are more than one android:authorities listed, while documentation states that it allows multiple values listed.
file:// scheme is now not allowed to be attached with Intent on targetSdkVersion >= 24 (Android N 7.0), only content:// is always passed for all devices (Android 5, 6 and 7). But we encountered that Xiaomi breaks this Google convention and sends file://, hence data.getData().getAuthority() gives empty string.
final String uriScheme = currentUri.getScheme();
if ("content".equals(uriScheme)) {
// getting full file path (works with some providers, i.e. Gallery)
path = FileUtils.getPath(getContext(), currentUri);
if (path != null) {
currentFile = new File(path);
}
} else if ("file".equals(uriScheme)) {
// in a rare case we received file:// in currentUri, we need to:
// 1. create new File variable from currentUri that looks like "file:///storage/emulated/0/download/50044382b.jpg"
// 2. generate a proper content:// Uri for it
currentFile = new File(currentUri.getPath());
String authority = data.getData().getAuthority();
if (authority != null && !authority.isEmpty()) {
currentUri = FileProvider.getUriForFile(getActivity(), authority, currentFile);
}
} else {
// throw exception
}
Also, the bug when FileProvider.getUriForFile() resulted in crash java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Android/data/com.example/files/attachments/image.jpg was fixed in Android Support Library v24.2.0. The problem was that FileProvider.java did not see external-path folders.
If you're building your AUTHORITY at runtime using BuildConfig make sure you use the full class name including your package name.
Bad:
final String AUTHORITY = BuildConfig.APPLICATION_ID + ".provider";
Good:
final String AUTHORITY = com.mycompany.myapp.BuildConfig.APPLICATION_ID + ".provider";
Following worked for me.
mUri = FileProvider.getUriForFile(this,
BuildConfig.APPLICATION_ID + ".provider",
fileObject);
Here is what i did to fix the issue. I gave fully qualified name in android:name. It works in android 6,7,8
<provider android:authorities="${applicationId}.opener.provider"
android:exported="false" android:grantUriPermissions="true"
android:name="io.github.pwlin.cordova.plugins.fileopener2.FileProvider">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="#xml/provider_paths" />
</provider>
You should try it:
Context context = PostAdapter.this.activity;
StringBuilder stringBuilder2 = new StringBuilder();
stringBuilder2.append(PostAdapter.this.activity.getPackageName());
stringBuilder2.append(".provider");
Uri uri;
uri = FileProvider.getUriForFile(context,stringBuilder2.toString(), newFile);
This is what you need to do:
Uri fileURI = FileProvider.getUriForFile(getActivity(), getActivity().getPackageName() + ".fileprovider", file);