I was trying to create a file to save pictures from the camera, it turns out that I can't create the file.
But I really can't find the mistake. Can you have a look at it and give me some advice?
private File createImageFile(){
File imageFile=null;
String stamp=new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File dir= Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
String imageFileName="JPEG_"+stamp+"_";
try {
imageFile=File.createTempFile(imageFileName,".jpg",dir);
} catch (IOException e) {
Log.d("YJW",e.getMessage());
}
return imageFile;
}
And I have added the permission.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
The method always gives such mistakes:
open failed: ENOENT (No such file or directory)
The Pictures directory might not exist yet. It's not guaranteed to be there.
In the API documentation for getExternalStoragePublicDirectory(), the code ensures the directory exists using mkdirs:
File path = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
File file = new File(path, "DemoPicture.jpg");
try {
// Make sure the Pictures directory exists.
path.mkdirs();
...so it may be as simple as adding that path.mkdirs() to your existing code before you createTempFile.
when a user picks a file from the gallery, there is no guarantee that the file that was picked was added or edited by some other app. So, if the user picks on a file that let’s say belongs to another app we would run into the permission issues. A quick fix for that is to add this code in the AndroidManifest.xml file:
<manifest ... >
<application android:requestLegacyExternalStorage="true" ... >
...
</application>
</manifest>
Note: For Android 11 refer Scope storage Enforcement Policy https://developer.android.com/about/versions/11/privacy/storage
Replace:
Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES)
With:
private File createImageFile() throws IOException {
// Create an image file name
make sure you call:
mkdirs() // and not mkdir()
Here's the code that should work for you:
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = new File(Environment.getExternalStorageDirectory().toString(), "whatever_directory_existing_or_not/sub_dir_if_needed/");
storageDir.mkdirs(); // make sure you call mkdirs() and not mkdir()
File image = File.createTempFile(
imageFileName, // prefix
".jpg", // suffix
storageDir // directory
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = "file:" + image.getAbsolutePath();
Log.e("our file", image.toString());
return image;
}
I had a bad experience following the example given in Android Studio Documentation and I found out that there are many others experiencing the same about this particular topic here in stackoverflow, that is because even if we set
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
the problem persists in some devices.
My experience was that the example worked when I tried it in debug mode, after that 3 more tests it so happened that my SD suddenly was corrupted, but I don't think it has to do with their example (funny). I bought a new SD card and tried it again, only to realize that still both release and debug mode did the same error log: directory does not exist ENOENT. Finally, I had to create the directories myself whick will contain the captured pictures from my phone's camera. And I was right, it works just perfect.
I hope this helps you and others out there searching for answers.
A quick fix for that is to add this code in the AndroidManifest.xml file:
<manifest ... >
<application android:requestLegacyExternalStorage="true" ... >
...
</application>
</manifest>
Note: Applicable for API level 29 or Higher
I used the contentResolver with the URI and it worked for me. Saw it in another SO post which i can't find.
private String getRealPathFromURI(Uri contentURI) {
String result;
Cursor cursor = getContentResolver().query(contentURI, null, null, null, null);
if (cursor == null) {
result = contentURI.getPath();
} else {
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
result = cursor.getString(idx);
cursor.close();
}
return result;
}
hope it helps....
I have solved like this:
public Intent getImageCaptureIntent(File mFile) {
Intent mIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Uri photoURI = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".provider", mFile);
mIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
// The tip is this code below
List<ResolveInfo> resInfoList = getPackageManager().queryIntentActivities(mIntent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
String packageName = resolveInfo.activityInfo.packageName;
grantUriPermission(packageName, photoURI, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
return mIntent;
}
If you are using kotlin then use below function.
you have to provide a path for storing image, a Bitmap (in this case a image) and if you want to decrease the quality of the image then provide %age i.e 50%.
fun cacheLocally(localPath: String, bitmap: Bitmap, quality: Int = 100) {
val file = File(localPath)
file.createNewFile()
val ostream = FileOutputStream(file)
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, ostream)
ostream.flush()
ostream.close()
}
hope it will work.
Try this:
private File createImageFile() throws IOException {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName="JPEG_"+stamp+".jpg";
File photo = new File(Environment.getExternalStorageDirectory(), imageFileName);
return photo;
}
File dirPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File imageFile = new File(dirPath, "YourPicture.jpg");
try {
if(!dirPath.isDirectory()) {
dirPath.mkdirs();
}
imageFile.createNewFile();
} catch(Exception e) {
e.printStackTrace();
}
I got same error while saving Bitmap to External Directory and found a helpful trick
private void save(Bitmap bitmap) {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
String imageFileName = timeStamp + ".png";
String path = MediaStore.Images.Media.insertImage(activity.getContentResolver(), bitmap, imageFileName, null);
Uri uriimage = Uri.parse(path);
// you made it, make fun
}
But this have a drawback i.e. you cant change the Directory it always save images to Pictures directory but if you got it fixed fill free to edit my code:
Haa-ha-ha {I can't use emojis with my keyboard}, Good Day
Following are fixes i found
first add these two lines in your AndroidManifest file
Than add the below line just after setContentView method
ActivityCompat.requestPermissions(FullImageActivity.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_CODE);
and for saving the images in gallery use the below code
private void SaveImageToGallery() {
BitmapDrawable drawable = (BitmapDrawable) imageView.getDrawable();
Bitmap bitmap = drawable.getBitmap();
FileOutputStream outputStream = null;
File file = Environment.getExternalStorageDirectory();
File dir = new File(file.getAbsolutePath()+"/folderName");
dir.mkdirs();
String filename = String.format("%d.jpg",System.currentTimeMillis());
File outfile = new File(dir,filename);
try{
outputStream = new FileOutputStream(outfile);
bitmap.compress(Bitmap.CompressFormat.JPEG,100,outputStream);
outputStream.flush();
outputStream.close();
}catch(Exception e){
Log.d("SavingError", "SaveImageToGallery: "+e.getMessage());
}
Toast.makeText(this, "Image saved in folderName folder", Toast.LENGTH_SHORT).show();
}
I have a problem regarding onActivityResult not being called after opening camera from an intent:
Intent takeIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
With extra:
takeIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
On ZTE Blade III I am able to open camera, but then when I press 'tick' nothing happens, as if there was some exception in Camera itself, and the control doesn't return to calling activity - onActivityResult doesn't get called.
On other phones with never systems (ZTE is 4.0.4) everything works fine. I am also able to add "return-data" extra to the Intent but then I get thumbnail as result, which I don't want.
PS. photoFile was created the following way:
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 = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
photoPath = image.getAbsolutePath();
return image;
}
wanted to add a comment but i don't have enough reputation.
did you check for null-ness of the file? before using it
did you check if the file exists?
did you check for external storage state? to see whether media state is mounted.
also i suspect the way you are creating your file
can you try using new File('path/for/storage') or its sisters?
I'm currently trying to get image saving to happen using the device built in camera. This is the code I'm using:
PackageManager pm = getActivity().getPackageManager();
if (pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)) {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// * Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(pm) != null) {
// * Create the File where the photo should go
File photoFile = null;
try {
photoFile = ImageFileHelper.createImageFile();
} catch (IOException ex) {
// * Error occurred while creating the File
Timber.d("An error occurred while creating file: " + ex.getLocalizedMessage());
}
// * Continue only if the File was successfully created
if (photoFile != null) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
startActivityForResult(takePictureIntent, REQUEST_CODE_TAKE_PICTURE);
} else {
alertUserOfError(0);
}
}
} else {
// * Inform user that they need a camera
// * to use this feature
alertUserOfError(1);
}
And here is the ImageFileHelper.createImageFile() function:
public static File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyy-MM-dd.ss", Locale.getDefault()).format(new Date());
String imageFileName = "Original_Avatar_" + timeStamp;
// * Create MyApp folder if not exist
String path = Environment.getExternalStorageDirectory() + File.separator + Environment.DIRECTORY_PICTURES;
File dir = new File(path + "/MyApp/Originals/");
dir.mkdirs();
File image = File.createTempFile(
imageFileName, /* prefix */
".png", /* suffix */
dir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
filePath = "file:" + image.getAbsolutePath();
Timber.d("image created at: " + filePath);
return image;
}
My permissions & features:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:glEsVersion="0x00020000" android:required="true"/>
This seems to work just fine on my test devices and the majority of my beta tester devices. However, there is one guy who reports that he gets an error message generated by alertUserOfError(0) (you'll see that in the above code), essentially that the photoFile is null.
He is using a rooted HTC One (M8) (htc_m8). Could this be an issue due to the device being rooted?
Any help is appreciated.
UPDATE 2015-05-30
I haven't had a chance to add reporting to the catch statement yet, but I did add a method to test for valid paths/directories. Here is how it works:
StringBuilder build = new StringBuilder();
String path_1 = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + File.separator + "MyApp" + File.separator + "Cropped" + File.separator;
File dir_1 = new File(path_1);
dir_1.mkdirs();
if (dir_1.exists()) {
build.append("path 1 valid, ");
} else {
build.append("path 1 invalid, ");
}
Using this same setup I also tested the following dirs:
Environment.getExternalStorageDirectory() + File.separator + "MyApp" + File.separator + "Cropped" + File.separator;
Environment.getDataDirectory() + File.separator + "MyApp" + File.separator + "Cropped" + File.separator;
The StringBuilder.toString() is then used as the message in an alert for the tester to send the results back to us.
The above resulted in all paths being invalid:
path_1 invalid, path_2 invalid, path_3 invalid
So does this mean that those directories just don't exist on the HTC One (M8) (htc_m8) and cannot be created?
I had a similar situation. You are implementing the example given in the official docs. There is a problem implementing that example in some devices. This is how I solved it.
Replace:
Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES)
With:
private File createImageFile() throws IOException {
// Create an image file name
Finally, make sure you call:
mkdirs() // and not mkdir()
Here's the code that should work for you:
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = new File(Environment.getExternalStorageDirectory().toString(), "whatever_directory_existing_or_not/sub_dir_if_needed/");
storageDir.mkdirs(); // make sure you call mkdirs() and not mkdir()
File image = File.createTempFile(
imageFileName, // prefix
".jpg", // suffix
storageDir // directory
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = "file:" + image.getAbsolutePath();
Log.e("our file", image.toString());
return image;
}
I had a bad experience following the example given in Android Studio Documentation and I found out that there are many others experiencing the same about this particular topic here in stackoverflow, that is because even if we set
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
the problem persists in some devices.
My experience was that the example worked when I tried it in debug mode, after that 3 more tests passed, it so happened that my SD was suddenly corrupted, but I don't think it had to do with their example (funny). I bought a new SD card and tried it again (because I could not reformat my sd, however I tried), only to realize that still both release and debug mode did the same error log: directory does not exist ENOENT. Finally, I had to create the directories myself whick will contain the captured pictures from my phone's camera. And I was right, it works just perfect.
I hope this will help the ones out there searching for answers, because obviously, considering the age of your enquiry, you must have already solved this issue.
I am developing a simple gallery app in which I search for folders which contains images and then show images of that particular folder. First I am using Environment.getExternalStorageDirectory() and then recursively search for folders having images. It is working fine simulator and devices. When my client installed app on Nexus 4, nothing is being loaded. I have seen some posts which says that Nexus series don't have any external SD slot. I don't have Nexus 4 for debugging and client is also non-technical. He can troubleshoot on his own to find the cause of problem. Can anybody help in this regard? I think the problem is in Environment.getExternalStorageDirectory() call which is not applicable in Nexus. Any idea how I can tackle this issue?
Here is the code snipped I am using:
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File cacheDir = null;
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
cacheDir=new File(android.os.Environment.getExternalStorageDirectory().getAbsolutePath(), "MyImages");
}
else {
cacheDir = getCacheDir();
}
if(!cacheDir.exists()) {
cacheDir.mkdir();
}
// File storageDir = Environment.getExternalStoragePublicDirectory(
// Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
cacheDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = "" + image.getAbsolutePath();
return image;
}
public 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
ex.printStackTrace();
}
// Continue only if the File was successfully created
if (photoFile != null) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
And here the permissions I have added manifest:
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-feature
android:name="android.hardware.camera"
android:required="true" />
Thanks!
I think you should give a try to the MediaStore.Images component. Load the images using a cursor. See documentation: http://developer.android.com/reference/android/provider/MediaStore.html
I am adding a photo from the phones camera to a Fragment. I am including the file path to where I would like the pic to get saved in the camera intent(MediaStore.ACTION_IMAGE_CAPTURE).
My problem is that after launching the camera and taking the pic the I am not able to get back to my app. The screen stays in the part where the user gets the option to accept the pic or take another one. The phone doesn't hang or crash and I am able to get back to my app by hitting the back button, but when I get back to the app it is without the pic.
I hope I have made my problem clear, if not let me know and I will try to explain better. I have attached (what I think) are the relevant bits of code.Let me know if you need to see anymore of the code.
Launching the camera intent:
void takePic()
{
if(isExternalStorageWritable() && isExternalStorageReadable())
{
Log.w("Rakshak", "in the take pic");
File file = getPicStoragePath();
Uri uriSavedImage=Uri.fromFile(file);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uriSavedImage);
startActivityForResult(intent, CAMERA_IMAGE_ACTIVITY_REQUEST_CODE);
}
}
public File getPicStoragePath() {
Log.w("Rakshak", "in the get pic file");
File root = android.os.Environment.getExternalStorageDirectory();
File dir = new File (root.getAbsolutePath() + File.separator +"YAN");
if(!dir.exists())
dir.mkdirs();
File file = new File(dir,getPicName());
return file;
}
public String getPicName()
{
Log.w("Rakshak", "in the get pic name");
if(title.getText().toString().trim().length() == 0)
{
Log.w("Rakshak", "no title");
Calendar cal=Calendar.getInstance();//get an instance of the calendar
return String.format("%1$te %1$tB %1$tY,%1$tI:%1$tM:%1$tS %1$Tp",cal);// get the data/time when the note was created
}
else
{
return title.getText().toString().trim();
}
}
I have these permissions in the manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
The relavent bits from the onActivityResult:
case CAMERA_IMAGE_ACTIVITY_REQUEST_CODE:
Log.w("Rakshak", "in the camera case");
myBitmap = data.getExtras().getParcelable("data");
photo.setVisibility(View.VISIBLE);
photo.setImageBitmap(myBitmap);
update_pic = true;
return;
There are no error messages in the LogCat. And I could not find anything of note in there.
I get the pic inserted onto the image view just fine if I dont add a file path to the camera intent. It is only when I add the file path that the stays in the "accept pic" bit of the camera.
Your getPicStoragePath() might be the issue. Try something like this:
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 = Environment.getExternalStoragePublicDirectory(
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;
}