Unable to save file from FileProvider - android

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().

Related

how to share an video from one app to another using file Provider?

I am trying to share an video from one app to another, but show me an error that "failed to find configure root/data/data/app_name/cache/videos/external files". I can't understand why it's not passing the uri to another app.
can anyone help me to solve this problem
here is file provider path
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="external_files" path="videos/"/>
</paths>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.myapp.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_provider_paths" />
</provider>
here is my code
File video = null;
shareVideos(video);
private void shareVideos(File video) {
Uri uri = getVideoToShare(video);
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_STREAM, uri);
intent.setType("videos/mp4");
context.startActivity(Intent.createChooser(intent, "Share Via"));
}
private Uri getVideoToShare(File video) {
File imagefolder = new File(context.getCacheDir(), "videos");
Uri uri = null;
try {
imagefolder.mkdirs();
File file = new File(imagefolder, "external_files");
FileOutputStream outputStream = new FileOutputStream(file);
outputStream.flush();
outputStream.close();
uri = FileProvider.getUriForFile(context, "com.myapp.fileprovider", file);
} catch (Exception e) {
Toast.makeText(context, "" + e.getMessage(), Toast.LENGTH_LONG).show();
}
return uri;
}
File imagefolder = new File(context.getCacheDir(), "videos");
You are storing your file in getCacheDir(). That requires a <cache-path> element in the FileProvider XML metadata resource. That is not what you have. You have:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="external_files" path="videos/"/>
</paths>
Change that to:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<cache-path name="external_files" path="videos/"/>
</paths>

File from FileProvider can't be viewed

I'm struggling with FileProvider. I want to open a video in another app, but no matter what I try every single app says that the video can't be loaded.
private void passVideo2(String videoname) {
File videoPath = new File(Environment.getExternalStorageDirectory(), "video_folder");
File videoInternalPath = new File(this.getFilesDir(), videoname);
File newFile = new File(videoPath, videoname);
Uri uri = FileProvider.getUriForFile(this, "com.example.provider", newFile);
Intent viewIntent = new Intent(Intent.ACTION_VIEW, uri);
viewIntent.setDataAndType(uri, getContentResolver().getType(uri));
viewIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
this.startActivity(viewIntent);
}
I've tried getting the video from the external and from the internal storage and I've tried different video formats and other file types like e.g. pdf and nothing seems to work
This is my provider_paths.xml
<paths>
<files-path name="files" path="/"/>
<external-path name="external" path="video_folder"/>
</paths>
and this is from the manifest
<provider
android:authorities="com.example.provider"
android:name="androidx.core.content.FileProvider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths"/>
</provider>

File passed with FileProvider can't be viewed

I'm struggling with FileProvider. I want to open a video in another app, but no matter what I try every single app says that the video can't be loaded.
private void passVideo2(String videoname) {
File videoPath = new File(Environment.getExternalStorageDirectory(), "video_folder");
File videoInternalPath = new File(this.getFilesDir(), videoname);
File newFile = new File(videoPath, videoname);
Uri uri = FileProvider.getUriForFile(this, "com.example.provider", newFile);
Intent viewIntent = new Intent(Intent.ACTION_VIEW, uri);
viewIntent.setDataAndType(uri, getContentResolver().getType(uri));
viewIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
this.startActivity(viewIntent);
}
I've tried getting the video from the external and from the internal storage and I've tried different video formats and other file types like e.g. pdf and nothing seems to work
This is my provider_paths.xml
<paths>
<files-path name="files" path="/"/>
<external-path name="external" path="video_folder"/>
</paths>
and this is from the manifest
<provider
android:authorities="com.example.provider"
android:name="androidx.core.content.FileProvider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths"/>
</provider>
This is a repost from this question as it didn't get any answers

Failed to find configured root error in android 7.0

I get this error: failed to find configured root that contains /storage/emulated/0/android/data/
There are some similar questions but they are using other location for storing files.
I am using:
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) method and this is the code I'm using to open camera:
private void TakePicture() {
photoFile = FileManager.generateFileStampedPhotoFile();
PicturesHelper.TryTakePictureWithAnIntent(this, photoFile, REQUEST_IMAGE_CAPTURE);
}
public static File generateFileStampedPhotoFile()
{
Uri photoFileUri=null;
File photoFile=null;
File outputDir=getPhotoDirectory();
if(outputDir!=null)
{
String timeStamp=new SimpleDateFormat("yyyyMMDD_HHmmss").format(new Date());
String photoFileName="IMG_"+timeStamp+".jpg";
photoFile=new File(outputDir,photoFileName);
// photoFileUri=Uri.fromFile(photoFile);
}
return photoFile;
}
public static void TryTakePictureWithAnIntent(Activity context,File
photoFile,int requestCode)
{
Intent takePictureIntent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if(takePictureIntent.resolveActivity(context.getPackageManager())!=null) //if user has camera?
{
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(context,
"com.myapp.fileprovider",
photoFile);
takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
takePictureIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
context.startActivityForResult(takePictureIntent, requestCode);
}
}
}
public static File getPhotoDirectory()
{
File outputDir=null;
String externalStorageState=Environment.getExternalStorageState();
if(externalStorageState.equals(Environment.MEDIA_MOUNTED)) {
File pictureDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
outputDir=new File(new File(pictureDir,"Adriagate"),"Online");
if(!outputDir.exists())//V.P. if directory/ies not exist/s it will be created. mksdrs method follows file structure and creates directory by direcory if needed
{
if(!outputDir.mkdirs())
{
return null;
}
}
}
return outputDir;
}
I have put provider inside AndroidManifest:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.myapp.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths"></meta-data>
</provider>
And this is file_paths.xml file:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-files name="Whatever_Nothing_Works"/>
You are storing your images in Environment.getExternalStoragePublicDirectory(). That is not one of the supported roots for FileProvider. Plus, your XML has <external-files>, and that is not a supported element for FileProvider (valid ones all end in -path).
Options include:
Changing the location of where you are storing the images to one of the locations supported by FileProvider and adjusting your XML to match
Switching to my StreamProvider and using <external-public-path dir="Pictures">
Changing your XML to <external-path name="whatever" path="Pictures"> and hope for the best
Add this in Menifest
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Replace in file_paths.xml with
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-files-path name="my_images" path="Android/data/com.example.package.name/files/Pictures" />
</paths>
Your file is stored under getExternalFilesDir(). That maps to <external-files-path>, not <files-path>

Getting Failed to find configured root that contains /storage/emulated/0/Pictures/NoteTaking/IMG_20170226_231007.jpg while trying to take a photo

I am trying to make an app that takes a photo and displays it using emulator instead of a device. I followed the steps from this android doc:
Part 1) Here is my code where it gets stucks : file = FileProvider.getUriForFile(this, "edu.android.notetakingapplication.provider", createFileDir());
This part is in the Mainxml
if (!mediaStorageDir.exists()){
if (!mediaStorageDir.mkdirs()){
Log.d("NoteTaking", "failed to create directory");
return null;
}
}
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
return new File(mediaStorageDir.getPath() + File.separator +
"IMG_"+ timeStamp + ".jpg");
}
Here is my app manifest file's provider section
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="edu.android.notetakingapplication.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths" />
</provider>
and 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="Android/data/edu.android.notetakingapplication/files/Pictures"/>
</paths>
Part 2) If i keep provider_paths as this
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>
I am able to open camera app, take photo and view it on the same page, but, here is the catch, I am storing the path into database and trying to retrieve all the images on a page. Here is when it gives an error:
Unable to decode stream: java.io.FileNotFoundException: /external_files/Pictures/NoteTaking/IMG_20170226_230608.jpg (No such file or directory)
Try this surely it will work:
Uri mImageCaptureUri;
private void operCamera() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
mImageCaptureUri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(),
"tmp_avatar_" + String.valueOf(System.currentTimeMillis()) + ".jpg"));
intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, mImageCaptureUri);
intent.putExtra("return-data", true);
startActivityForResult(intent, 1);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1 && mImageCaptureUri != null && resultCode != 0) {
if (mImageCaptureUri != null) {
String path1 = mImageCaptureUri.getPath();
if (path1 != null) {
File file1 = new File(path1);
Uri capturedUri = Uri.fromFile(file1);//here you get the URI
//you can easily get the path from URI if you need
}
}
}
}
Unable to decode stream: java.io.FileNotFoundException: /external_files/Pictures/NoteTaking/IMG_20170226_230608.jpg (No such file or directory). Of course you get that error as it is a non valid path for File object or a file stream. You are saving the uri in a wrong way to the database. You better save File:getAbsoluthePath() instead of Uri:getPath().

Categories

Resources