I am building an application in which I want to capture an image using intent (MediaStore.ACTION_IMAGE_CAPTURE) and want to save it to gallery.
Every thing is working fine but image is not being saved to gallery.
I have followed google documentation (https://developer.android.com/training/camera/photobasics) to perform my task.
But image is not being saved to gallery.
My manifest file :
.
.
.
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.kartik.translater"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths"></meta-data>
</provider>
.
.
my file_paths.xml file:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<!-- <external-files-path name="my_images" path="Pictures" />-->
<!-- <external-path name="external_files" path="." />-->
<external-path
name="external"
path="."/>
<external-files-path
name="external_files"
path="."/>
<cache-path
name="cache"
path="."/>
<external-cache-path
name="external_cache"
path="."/>
<files-path
name="files"
path="."/>
</paths>
This set of instruction will trigger image capturing process:
//Capture Input Image
camera.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
dispatchTakePictureIntent();
}
});
dispatchTakePictureIntent() definition :
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
Toast.makeText(MainActivity.this, "Failure", Toast.LENGTH_SHORT).show();
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(this,
"com.kartik.translater",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, CAMERA_REQUEST_CODE);
}
}
}
createImageFile() fn. definition:
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;
}
onActivityResult() defintion:
if(requestCode==CAMERA_REQUEST_CODE && resultCode==RESULT_OK)
{
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File(currentPhotoPath);
Uri contentUri = Uri.parse(currentPhotoPath);
mediaScanIntent.setData(contentUri);
this.sendBroadcast(mediaScanIntent);
Toast.makeText(MainActivity.this, contentUri+"", Toast.LENGTH_SHORT).show();
}
** I am using Android 11 to run the app.
***Toast message of onActivityResult() is getting executed but image is not getting saved in gallery.
In order to be able to write to external storage on android 10+, you need to have access to it. To provide this capability in your app, use the ACTION_OPEN_DOCUMENT_TREE intent action.
More details can be found here: https://developer.android.com/training/data-storage/shared/documents-files?hl=ru#grant-access-directory
Related
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>
The open camera intent is not working in android 11, the app is getting crashed everytime, but the same code is tested and working in Android 6,7,8.
Below is the code --
private void openCameraIntent() {
Intent pictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if(pictureIntent.resolveActivity(getActivity().getPackageManager()) != null){
//Create a file to store the image
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
Log.d("IOError", ex.getMessage());
} catch (Exception ex2) {
Log.d("Error", ex2.getMessage());
}
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(context.getApplicationContext(), getActivity().getPackageName()+".fileprovider", photoFile);
pictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(pictureIntent, 1);
}
}
}
String imageFilePath;
private File createImageFile() throws IOException {
String timeStamp =
new SimpleDateFormat("yyyyMMdd_HHmmss",
Locale.getDefault()).format(new Date());
String imageFileName = "IMG_" + timeStamp + "_";
File storageDir = getActivity().getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
imageFilePath = image.getAbsolutePath();
Log.d("imageFilePath", imageFilePath);
return image;
}
Android menifest file --
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true"
tools:replace="android:authorities">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths" />
</provider>
file_paths.xml --
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<!--change only the package name if you have change the package name of app-->
<external-path name="my_images" path="AppName/Temp/" />
<external-path name="external_files" path="."/>
</paths>
What might be the changes required which i am missing. Please guide me to achieve the solution. Thank you.
In my app, trying to capture images using the camera app.
I am updating my app to use FileProvider.getUriForFile when specifying the file path to save images to, as Uri.fromFile is deprecated.
It was working fine beforehand using Uri.fromFile. But I can't get it to work using FileProvider.getUriForFile.
I am creating the image file as follows:
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
mCurrentPhotoPath = "file:" + image.getAbsolutePath();
return image;
Then, depending on the target sdk, I get the image URI:
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
jobImageURI = Uri.fromFile(photoFile);
} else {
jobImageURI = FileProvider.getUriForFile(OrderDetails.this, BuildConfig.APPLICATION_ID + ".provider",photoFile);
}
I have updated the app manifest xml to include the provider, as per the android developer documentation.
I have a provider_paths.xml file which holds the path:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>
Then I launch the camera:
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, jobImageURI);
startActivityForResult(takePictureIntent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
However, after the photo is taken and it comes back to the onActivityResult function, I read back in the image file.
The image isn't saved to the Gallery, as I am reading back in the last file from the Gallery but it isn't there.
I can't access the file using the path from the jobImageURI above either.
Is the path I've provided the provider_paths.xml file incorrect, or why can't I access the images?
try this way
create a xml file under xml folder in res directory
provider_path.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/yourAppPackageName/files/Pictures" />
</paths>
Register Provider in AndroidManifest.xml
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="yourAppPackageName.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_path"/>
</provider>
add these permissions
<uses-feature android:name="android.hardware.camera"
android:required="true" />
<uses-permission android:name="android.permission.CAMERA"/>
on Camera Button Click call dispatchTakePictureIntent()
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(getActivity().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(getActivity(),
"com.arantico.servicepro.provider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
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 = getActivity().getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = image.getAbsolutePath();
return image;
}
here mCurrentPhotoPath will show the path of file where it got stored
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().
I'm trying to use the google's training section "Taking photos simply" and I'm facing an issue. I have copied the code, only changing my project related data:
In the manifest:
// inside application tag
<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>
In the 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/${applicationId}/files/Pictures" />
</paths>
Taking the picture:
static final int REQUEST_TAKE_PHOTO = 1;
private String mCurrentPhotoPath;
protected void takeAPic() {
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
ex.printStackTrace();
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(this, // here the exception is triggered.
BuildConfig.APPLICATION_ID + ".fileprovider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = presenter.getGtin() + "-" + 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
mCurrentPhotoPath = "file:" + image.getAbsolutePath();
return image;
}
The exception:
java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Android/data/my.package.name/files/Pictures/8712561249140-20160902_104505516416962.jpg
at android.support.v4.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.java:679)
at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:378)
at my.package.name.usecases.reviewdata.ReviewDataActivity.takeAPic(ReviewDataActivity.java:242)
at my.package.name.usecases.reviewdata.ReviewDataActivity.onOptionsItemSelected(ReviewDataActivity.java:118)
at android.app.Activity.onMenuItemSelected(Activity.java:2885)
at android.support.v4.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:421)
at android.support.v7.app.AppCompatActivity.onMenuItemSelected(AppCompatActivity.java:188)
at android.support.v7.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:103)
at android.support.v7.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:103)
at android.support.v7.app.ToolbarActionBar$2.onMenuItemClick(ToolbarActionBar.java:69)
at android.support.v7.widget.Toolbar$1.onMenuItemClick(Toolbar.java:202)
at android.support.v7.widget.ActionMenuView$MenuBuilderCallback.onMenuItemSelected(ActionMenuView.java:761)
at android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:810)
at android.support.v7.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:152)
at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:957)
at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:947)
at android.support.v7.widget.ActionMenuView.invokeItem(ActionMenuView.java:618)
at android.support.v7.view.menu.ActionMenuItemView.onClick(ActionMenuItemView.java:155)
at android.view.View.performClick(View.java:4789)
at android.view.View$PerformClick.run(View.java:19881)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5294)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
I've searched here and no answer helped me because they were different cases. What I'm doing wrong? I have clean the project, also uninstall it and try with the appID instead of with the values from gradle.
Thanks a lot!
Update Sept 5th: I created a new project to be sure nothing was interfering with it. Same error, also tried different phones and emulators with same results.
The value of path can be relative:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="my_images" path="Pictures/" />
</paths>