Can't see the bitmap I saved to new directory - android

I was looking for a way to save a bitmap to a folder (with my app's name), in such a way the default gallery will recognize it.
So I managed to save the image, but I can't see it either from the gallery or my PC (using explorer)
this is my code:
// Save bitmap to internal memory
private void savePhoto(Bitmap bmp){
String appName = "myApp";
String file_path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)+ File.separator + appName;
File dir = new File(file_path);
if(!dir.exists())
dir.mkdirs();
// Image file
File file = new File(dir, "IMG" + "_" + System.currentTimeMillis() + ".jpg");
FileOutputStream out = null;
try
{
out = new FileOutputStream(file);
bmp.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.flush();
out.close();
out = null;
} catch (Exception e)
{
e.printStackTrace();
}
}
I can see it using some File Manager installed on my galaxy, but it doesn't help a lot.
I know I should inform the gallery using a media scanner (which is another bridge I need to cross) but may someone help me understand way I can't even find the file..should I change its visibility somehow?
and one more thing: I read at another question regarding the issue, that I should add metadata to the image/folder so that the gallery would show it. Is it necessary?
Many thanks!!!

Apparently it did have something to do with the media scanner, I added this line
MediaScannerConnection.scanFile(this, new String[] { file.getAbsolutePath() }, null, null);
and now it works.
from the documentation:
MediaScannerConnection provides a way for applications to pass a newly created or downloaded media file to the media scanner service. The media scanner service will read metadata from the file and add the file to the media content provider.

try to replace this getExternalStoragePublicDirectory(....)
with this one getExternalStorageDirectory();

Related

How To Properly Save To The Pictures Folder

I am trying to save a bitmap that is created by the user to the default 'Pictures' folder on the device. I will start with the option that seems to be the more common method:
public void saveImageToExternalStorage(String filename, Bitmap image) {
String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator;
try {
File directory = new File(path);
if (!directory.exists()) {
directory.mkdirs();
}
File file = new File(directory, filename + ".jpeg");
file.createNewFile();
OutputStream outputStream = new FileOutputStream(file);
image.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
outputStream.flush();
outputStream.close();
} catch (IOException exception) {
exception.printStackTrace();
}
}
This is supposed to save to the 'Pictures' folder, but Environment.getExternalStorageDirectory().getAbsolutePath() seems to create a new file structure like this file://storage/emulated/11/Pictures/ and save the picture to that. I have also tried Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) with the same result. But this is not the default 'Pictures' folder on any of my test devices or emulators. Which led me to look for other methods, and I found this:
public void saveImageToExternalStorage(String filename, Bitmap image) {
try {
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, filename);
values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis());
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
Uri filepath = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
OutputStream outputStream = getContentResolver().openOutputStream(filepath);
image.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
outputStream.close();
} catch (IOException exception) {
exception.printStackTrace();
}
}
This actually saves to the default file structure, which apparently looks like this: content://media/external/images/media/4282. But there seems to be no way to specify the filename of the image (Media.TITLE just sets the title attribute, not the actual filename), it saves as a (seemingly) random string of numbers. I looked at the API Guide for MediaStore.Images.Media and there does not seem to be any other variable that would set the filename. This also does not seem to be the correct way of saving, according to the Android Developer Guides. I would like to know if there is any way of saving to this folder, while also setting my own filename. And if this method could produce unforeseen problems on other devices.
EDIT:
For anyone interested this is my current code, based on the answer by #CommonsWare:
public void saveImageToExternalStorage(Context context, String filename, Bitmap image) throws IOException {
File directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File file = new File(directory, filename + ".jpeg");
FileOutputStream outputStream = new FileOutputStream(file);
mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
outputStream.flush();
outputStream.getFD().sync();
outputStream.close();
MediaScannerConnection.scanFile(context, new String[] {file.getAbsolutePath()}, null, null);
}
This is supposed to save to the 'Pictures' folder
getExternalStorageDirectory() returns the root of external storage, not some location inside of it (e.g., Pictures/, DCIM/, Movies/).
I have also tried Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) with the same result
That will give you the proper directory, or whatever the device thinks the proper directory is (usually named Pictures/ in external storage for whoever the current user is).
but Environment.getExternalStorageDirectory().getAbsolutePath() seems to create a new file structure like this file://storage/emulated/11/Pictures/
The 11 is a bit unusual, and getAbsolutePath() does not return something with a file:// scheme, but otherwise that seems about right.
But this is not the default 'Pictures' folder on any of my test devices or emulators.
I do not know how you have determined this.
I would like to know if there is any way of saving to this folder, while also setting my own filename.
Start with your first sample, switching to DIRECTORY_PICTURES. Then:
have outputStream be a FileOutputStream
call outputStream.getFD().sync() after flush() and before close()
use MediaScannerConnection and its scanFile() method to arrange for the MediaStore to index the image, so it is available to on-device galleries, desktop OS file managers, etc.
With Android 6.0 Marshmallow (API >= 23), Google introduced a new permission model.
You have to request permission at run-time:
String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
requestPermissions(permissions, WRITE_REQUEST_CODE);
and handle the result in onRequestPermissionsResult(),
File path = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
File file = new File(path, "db.JPG");
try {
file.createNewFile();
}
catch (IOException e) {
Toast.makeText(this.getApplicationContext(),
"createNewFile:"+e.toString(),
Toast.LENGTH_LONG).show();
}
then
if (Build.VERSION.SDK_INT < 19) {
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,
Uri.parse("file://" + filename)));
}
else {
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
Uri.parse("file://" + filename)));
}
to show in the gallery.

Send Image via Intent by WhatsApp - Wrong Image

I thought that this is a popular problem, but I can't find anything related to it. So here is what I want:
I'm trying to send an Image by WhatsApp with the following code:
public static void shareImage(Context context,Bitmap bitmap, String text){
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("image/*");
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
File f = new File(Environment.getExternalStorageDirectory() + File.separator + "temporary_file.jpg");
try {
f.createNewFile();
FileOutputStream fo = new FileOutputStream(f);
fo.write(bytes.toByteArray());
fo.close();
} catch (IOException e) {
e.printStackTrace();
}
share.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(f));
share.setPackage("com.whatsapp");
context.startActivity(Intent.createChooser(share, "Share!"));
}
It works fine, for the first time I use the app.. the right image appear in WhatsApp. If I choose another Bitmap with my App, Whatsapp still shows the first Image.
What I did and what I thought caused the problem:
If the temporary file existed, I deleted it by f.delete()
Then I updated the Gallery with MediaScanner, because I thought, that the URI I put in Extra is not up to date...
Fyi: The temporary file contains the right Image: If I choose it with an FileExplorer it shows the right image.. if I try to send the Image.. still the old Image
Does anyone has an idea what the problem might be? Is the Uri wrong? If I print Uri.fromFile(f)it says file:///storage/sdcard0/temporary_file.jpg
Thank you!
Nico
Did you actually send the first image or did you cancel it? I have the same problem and i just realized that the correct image will be send if you continue. I guess the problem is caused by old thumbnail pictures. You could use different filenames.
File f = new File(Environment.getExternalStorageDirectory() + File.separator + "temporary_file"+ System.currentTimeMillis() +".jpg");
Later you can delete all files starting with "temporary_file"
for (File file : Environment.getExternalStorageDirectory().listFiles()) {
if (file.isFile() && file.getName().startsWith("temporary_file")) file.delete();
}

Android: write photo files on SD Card that are viewable in the gallery

I'm trying to found a way (compatible with android kitkat and next) to write photos on the SD Card and make them visible to the gallery app.
If I use Environment.getExternalStoragePublicDirectory , samsung devices return a path in internal memory (/storage/emulated/0/ ... )
If I use Context.getExternalFilesDirs , there are two results : the first one on internal storage, and the second one on SD Card. Ok, I can write inside and the photo is on the SDCard. But I can't see it in the Galery app :'(
I have tried to write directly on /storage/externalSdCard/DCIM/ but of course I can't since I'm running kitkat.
Ok, I can write inside and the photo is on the SDCard. But I can't see it in the Galery app
First, when you are done writing to the file, call flush(), then getFD().sync(), then close(), all on your FileOutputStream.
Then, use MediaScannerConnection and its scanFile() method to get the newly-written file indexed by the MediaStore.
void saveImage() {
File filename;
try {
String path = Environment.getExternalStorageDirectory().toString();
new File(path + "/folder/subfolder").mkdirs();
filename = new File(path + "/folder/subfolder/image.jpg");
FileOutputStream out = new FileOutputStream(filename);
bitMapImg.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
MediaStore.Images.Media.insertImage(getContentResolver(), filename.getAbsolutePath(), filename.getName(), filename.getName());
Toast.makeText(getApplicationContext(), "File is Saved in " + filename, 1000).show();
} catch (Exception e) {
e.printStackTrace();
}
}

saving bitmap from arraylist to SD card - saved file unreadable

My situation is as follows: I'm saving multiple bitmaps from an arraylist to a specific folder in my devices SD Card (with success), however, the saved file- when clicked- prompts a message from the phone, stating: "Unable to find application to perform this action." The file size of this file is proportional to that of the bitmap image being saved, so I'm a bit confused, as the device has no problems opening image files, yet cannot open (or identifiy) these as a media file.
Question: What would cause the saved image file (presuming that I have saved it correctly) to exhibit this type of behavior in a device, and how should I resolve this issue?
Extra: the thumbnail of the file is the system provided thumbnail of the two papers on top of each other. The arraylist is being passed from one activity to its current one where the method provided is supplied.
Here is the method invoking the saving of the files to the specified folder /filesdestination:
private void saveImages(){
// to retrieve bitmaps
ArrayList<Bitmap> images = getIntent().getParcelableArrayListExtra("images key");
//to retrieve bitmaps and save in specific order, while also naming them in that order
int loopVal = 0;
int postVal = 9;
while ( loopVal < 9) {
Bitmap Image = images.get(loopVal);
try {
String filedestination = new String(Environment.getExternalStorageDirectory() + "/filedestination");
String timeStamp = new SimpleDateFormat("ddMMyyyy_HHmm").format(new Date());
File file = new File(filedestination, postVal + ".post_order" + ".jpg" + timeStamp);
File picfile = file;
FileOutputStream fos = new FileOutputStream(picfile);
Image.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.close();
} catch (Throwable e) {
e.printStackTrace();
}
postVal--;
loopVal++;
}
}
Any insight would be appreciated,
-Lucas
i think it cannot read the file type because the timestamp is after the file extension jpg and you are also compressing it as a png, so you might want to change either or, something like this
File file = new File(filedestination, postVal + timeStamp +".post_order" + ".png");
It seems that you are saving a .jpg file compressed as a PNG. That can make the image reader app to misbehave.
Either change Image.compress(Bitmap.CompressFormat.PNG, 100, fos);
to
Image.compress(Bitmap.CompressFormat.JPEG, 100, fos);
or change
File file = new File(filedestination, postVal + ".post_order" + ".jpg" + timeStamp);
to
File file = new File(filedestination, postVal + ".post_order" + ".png" + timeStamp);

Android delete all files starting with particular word

I have a problem and I hope you can help me out.
In my wallpaper app, I am saving an image to SDcard so the user can share it online via ActionBar share function.
Here is the code that does the saving:
Uri bmpUri = null;
try {
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOWNLOADS), "share_image_" + System.currentTimeMillis() + ".png");
file.getParentFile().mkdirs();
FileOutputStream out = new FileOutputStream(file);
bmp.compress(Bitmap.CompressFormat.PNG, 90, out);
out.close();
bmpUri = Uri.fromFile(file);
} catch (IOException e) {
e.printStackTrace();
}
return bmpUri;
Now, I am trying to delete that image when the user leaves the activity (which means he already shared the image or decided not to share. Either way, its not needed anymore.)
I am trying to delete it with this code (Its on button click method atm, but will change that later)
case R.id.btn_delete:
// File folder = (Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS));
File folder = new File(Environment.getExternalStorageDirectory() + Environment.DIRECTORY_DOWNLOADS);
File[] filenamestemp = folder.listFiles();
for (int i = 0; i < filenamestemp.length; i++) {
if (filenamestemp[i].getAbsolutePath().toString().contains("share_image_"))
filenamestemp[i].delete();
}
break;
The way I see it, this should work...but it doesn't.
I tried all sorts of things, but nothings works. No errors,nothing..but image is still present in Downloads directory.
Any help?
I think you are getting the wrong directory for the written files
You are reading the files by
File folder = new File(Environment.getExternalStorageDirectory() + Environment.DIRECTORY_DOWNLOADS);
instead of:
File folder = (Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS));
These directories are not the same.
Hope it helps, if you need anything else tell me ;)

Categories

Resources