saving bitmap from arraylist to SD card - saved file unreadable - android

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);

Related

Android BitmapFactory decodeResource Out of Memory Exception

I'm new to android and developing an app that saves large images from drawable folder to phone storage. These files have resolution of 2560x2560 and I want to save these files without loosing image quality.
I use following method to save images and it gives me Out of Memory Exception. I have seen many answers how to load a large bitmap efficiently. But I cant really find an answer for this problem.
In my code, I use
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), imageId);
File file = new File(root.getAbsolutePath() + "/Pictures/" + getResources().getString(R.string.app_name) + "/" + timeStamp + ".jpg");
file.createNewFile();
FileOutputStream oStream = new FileOutputStream(file);
bitmap.compress(CompressFormat.JPEG, 100, oStream);
oStream.close();
bitmap.recycle();
Is there anything wrong with my code? This works without any exception for smaller images.
If I use android:largeHeap="true", this does not throw any exception. But I know it is not a good practice to use android:largeHeap="true".
Is there any efficient way to save large images from drawable folder without an exception?
Thank you in advance.
If you just want to copy the image file, you shouldn't decode it into a bitmap in the first place.
You can copy a raw resource file with this for example:
InputStream in = getResources().openRawResource(imageId);
String path = root.getAbsolutePath() + "/Pictures/" + getResources().getString(R.string.app_name) + "/" + timeStamp + ".jpg";
FileOutputStream out = new FileOutputStream(path);
try {
byte[] b = new byte[4096];
int len = 0;
while ((len = in.read(b)) > 0) {
out.write(b, 0, len);
}
}
finally {
in.close();
out.close();
}
Note that you have to store your image in the res/raw/ directory instead of res/drawable/.

How to Generate Random names for Images while storing in Internal Memory?

The Android Application which I am developing is basically a shopping application, which has a Cart option, where user can add items.
The Items has Image, Name, Price etc..
I get all these data from server.
When user click "Add to Cart " option then a sqlite database is created where I store the name, price and image path.
Basically Imgaes are stored in the internal memory when add to cart is clicked and only image path is stored in the database.
Problem:
To store images in the internal memory I use the below code where I will give the file name myself (In this case I give file name as profile.jpg).
SaveToMemory:
private String saveToInternalSorage(Bitmap bitmapImage){
ContextWrapper cw = new ContextWrapper(getApplicationContext());
// path to /data/data/yourapp/app_data/imageDir
directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
// Create imageDir
mypath=new File(directory,"profile.jpg");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(mypath);
// Use the compress method on the BitMap object to write image to the OutputStream
bitmapImage.compress(Bitmap.CompressFormat.PNG, 100, fos);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return directory.getAbsolutePath();
}
LoadFromMemory:
private Bitmap loadImageFromStorage(String path)
{
try {
File f=new File(path, "");
f.canRead();
b = BitmapFactory.decodeStream(new FileInputStream(f));
return b;
}
If I do so, latest image is overridden by the previous image. Iam not able to store multiple images in the internal memory.
For Example If I add two items inside the cart I dont know how to store those two images and get it.
Aim
Need to store any number of images with random file name in the internal memory
Store the file name in sqlite database.
Retrieve it back to display in Imageview.
Any help would be greatly thankfull.
Try
mypath=new File(directory,System.currentTimeMillis()+"_profile.jpg");
instead of
mypath=new File(directory,"profile.jpg");
System.currentTimeMillis() will returns the current time in milliseconds since January 1, 1970 00:00:00.0 UTC. so it is different each time
You can use UUID
new File(directory,"profile_" + UUID.randomUUID().toString() + ".jpg");
it would be
profile_e85c5115-eea6-4b0d-98e3-9e09c2d505b3.jpg
Use new Date().toString() instead of "profile.jpg"

Android saves image twice

I'm making a screenshot of my few programmatically but somehow the image is saved in the /TestProject/ folder but also in the normal picture folder. Does anyone have a clue why this is happening. (And is there a change that Android's normal picture folder shows all images all together?)
OutputStream out;
root.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(root.getDrawingCache());
root.setDrawingCacheEnabled(false);
/* Preparation ==================================== */
// Find the SD Card path
File path = Environment.getExternalStorageDirectory();
// Create a new folder in SD Card
File dir = new File(path.getAbsolutePath() + "/TestProject/");
dir.mkdirs();
/* ================================================= */
// Create a name for the saved image
File file = new File(dir, (new Date().getTime() + ".jpg"));
try {
out = new FileOutputStream(file);
// Compress into png format image from 0% - 100%
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.flush();
out.close();
MediaStore.Images.Media.insertImage(getContentResolver(), bitmap, (new Date().getTime() + ".jpg"), null);
Toast.makeText(this, "Farm art saved", Toast.LENGTH_LONG).show();
} catch (Exception e) {
e.printStackTrace();
}
The insertImage() method also creates a thumbnail for the inserted image. There is a probability that you're seeing the thumbnail and the inserted image.
If you want to force a scan of the image by the media store, you should use the scanFile()[0] method instead.
[0] http://developer.android.com/reference/android/media/MediaScannerConnection.html#scanFile%28java.lang.String,%20java.lang.String%29

Android picture has red tint after decoding and pulling the .png file from the emulator to pc

I am transferring some data from a server ( java app ) to client ( android app ).
The data gets Base64 encoded, sent, received correct, decoded ( correct ? ) and stored to the device ( correct ? )
I am using android studio and an AVD to simulate it. I take the pictures via DDMS from the virtual device folder to my computers harddisk in order to take a look at them. Is maybe there the problem?
now in the following code sections the picture files get decoded and stored to the device.
Cant figure out where the mistake is.
Would be glad about any hint.
byte[] imageBackToByt = Base64.decode(parts[9], Base64.DEFAULT);
Bitmap bitmapImage = BitmapFactory.decodeByteArray(imageBackToByt, 0, imageBackToByt.length);
File mediaStorageDir = new File(Environment.getExternalStorageDirectory()
+ "/Android/data/"
+ ctx.getApplicationContext().getPackageName()
+ "/Files");
File imageFile = new File(mediaStorageDir.getPath() + File.separator + voReceived.name + ".png");
try {
FileOutputStream fos = new FileOutputStream(imageFile);
bitmapImage.compress(Bitmap.CompressFormat.PNG, 90, fos);
fos.close();
} catch (FileNotFoundException e) {
Log.d(ctx.getString(R.string.SLDMP), "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(ctx.getString(R.string.SLDMP), "Error accessing file: " + e.getMessage());
}
This is how i encode it on the server in JAVA:
BufferedImage originalPicture = null;
ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
byte[] pictureInByte = null;
String pictureEncoded = null;
try {
// load the original picture from the filepath
originalPicture = ImageIO.read(picturFile);
// Convert the original picture from .png format to byte array (byte []) format
ImageIO.write(originalPicture, "jpg", byteArrayOS );
pictureInByte = byteArrayOS.toByteArray();
// Encode the byte array pictureInByte to String based on Base64 encoding
pictureEncoded = Base64.getEncoder().encodeToString(pictureInByte);
} catch (IOException e) {
e.printStackTrace();
// If picture failed to load / encode store string "PICTUREERROR" as an error code
pictureEncoded = "PICTUREERROR";
}
The server puts the bytes of the image file in a buffer and sends the contents of the base 64 encoded buffer to the client. Now on client side you should directly decode base 64 all bytes and write all the resulting bytes to file. In this way you have exactly the same file. All bytes are the same and file size would be equal too.
Instead you use BitmapFactory to construct a Bitmap and then compress it to PNG. That all makes no sense.
If you want to transfer a file then do not use BitmapFactory and Bitmap.
Having said that.. Mmmmm nice filter! The result is wonderfull!

Can't see the bitmap I saved to new directory

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

Categories

Resources