I have been going crazy with this android error and from browsing the previous posts about this error none of the solutions that were given helped me.
I am of course talking about the all powerful killer known as the 'android Out of memory on a (NUMBER)-byte allocation.' I am trying to create a photo uploader and after the 3rd maybe 4th image my app crashes. I know to stop the crash to use a catch exception however that is not my problem. I am here to ask the community is there any solution to fixing this byte allocation error ?
Here is a snippet of my code involving the bit map .
String post = editTextPost.getText().toString().trim();
// get the photo :
Bitmap image = ((BitmapDrawable)postImage.getDrawable()).getBitmap();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
// compress the image to jpg format :
image.compress(Bitmap.CompressFormat.JPEG, 45, byteArrayOutputStream);
byte[] imageBytes = byteArrayOutputStream.toByteArray();
String encodeImage = Base64.encodeToString(imageBytes,Base64.DEFAULT);
// Recycle bitmap :
image.recycle();
image=null;
// send data :
sendPost p = new sendPost(this);
p.execute(post, encodeImage);
imageBytes=null;
Im not using any libraries and would like to keep it that way however if using a library is the only option I will use one. Hopefully someone can help.
Bitmaps won't completely recycle if they are attached to a View, for example to a ImageView, if you do imageView.setImageBitmap(bitmap), you need to clear it before doing imageView.setImageBitmap(null) and clearing any other reference to any view.
After you finish uplloading the image release the memory occupied by the "postImage" -
postImage.setImageDrawable(null);
This will release any memory occupied by the bitmap associated with postImage
General Answer:
When you upload files you need to open a stream to your server and to
your file at same time. read and write chunk by chunk of 1 MB for
example. this way you will not get an out of memory exception.
Related
I have searched online for a tutorial on how to send a bitmap data over to another activity using the putExtra() method in kotlin, but nothing seems to pop up. I do not know how to code in java so all the tutorials and stack overflow threads that talk about converting to a byte array do not help much. Can someone please help me with maybe a solution?
What I did so far (My project is in no regards to this post) is I saved a image using my camera as a bitmap using the code:
val thumbnail : Bitmap = data!!.extras!!.get("data") as Bitmap
(the key word "data" is a intent inside the upper override function (onActivityResult))
This saves a bitmap of the image I took with the camera and now I tried to send it over, using the putExtra() command as so:
var screenSwitch2 = Intent(this#MainActivity,mlscreen::class.java)
screenSwitch2.putExtra("bitmap", thumbnail)
On the other screen "mlscreen" I tried to recover the data using a intent.getStringExtra("bitmap")
val thumbnail = intent.getStringExtra("bitmap")
and then I set my image view in the "mlscreen" using the setImageBitmap method as here:
iv_image.setImageBitmap(thumbnail)
I got the error that I was looking for a bitmap data and not a string data for the method. I knew this would occur though because I had to use intent.getSTRINGExtra which would mean its converting it to a string I presume.
Any help with this would be appreciated! Thanks.
There are 3 ways to do that :
1 - Using Intent (not recommended)
ByteArrayOutputStream baos = new ByteArrayOutputStream();
thumbnail.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] b = baos.toByteArray();
intent.putExtra("image", b);
startActivity(intent);
2 - Using static (not recommended)
public static Bitmap thumbnail;
3 - Using Path (recommended)
Save your Bitmap as an image file in specific folder (make it invisible to the users).
Get the path from the saved file.
Use intent.putExtrat("imagePath",path);.
Use BitmapFactory.decodeFile(filePath); to get the Bitmap from the path.
Remove the path.
i want to make images backup because of this i use sqlite DataBase for storing images my code is worked fine when i put 10 to 12 images but after that it shows OutOfMemoryError . i use android:largeHeap="true" it increase some amount of memory but this is not sufficient for my work.how can i solve this??please help me guys.
this is my code:
if(data==null){
Uri uri = data.getData();
try {
InputStream inputStream = getContentResolver().openInputStream(uri);
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
Bitmap bmp = BitmapFactory.decodeStream(bufferedInputStream);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, bos);
byte[] bArray = bos.toByteArray();
DataBase dataBase=new DataBase(getBaseContext());
dataBase.insertImage(bArray);
Toast.makeText(getBaseContext(),"single item ",Toast.LENGTH_LONG).show();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
This happens when the image is very large. You can save the image with paint in Jpg and reduce in this way the size. Try with different dimensions until one of them works.
You don't show us the code that surrounds this snippet, i.e. "how the retrieved data is managed." For instance, you might well find it impossible(!) to hold "10 or 12 images" in memory at the same time ... and-d-d each device will be different! (You, as a developer, naturally buy a "decked out" device, while your Actual Customer bought her phone at the grocery store.) You're going to have to design some kind of scheme that stores only recently-retrieved images in memory.
One possible strategy is to store these images in objects that are held in a collection that has "weak references" to the objects. If the memory manager is short of memory, it can harvest those objects. (A good discussion of this can be found at http://javapapers.com/core-java/java-weak-reference/ .) Your code must be prepared to check if the object has been reaped, but it's a fairly manageable way to handle not knowing how much memory you do have.
Also, your code must be graceful if it gets thrown an "out of memory" exception! Maybe in that case it voluntarily throws-away the oldest entry in its container, then tries the operation again. And, so on. In the mobile world, you don't have the luxury of "unlimited virtual memory." Memory is a real resource.
I use the following code to obtain a bitmap from an ImageView. This image is not saved anywhere else on my device. I want to upload this image into an online mysqli database. However, to do so I need to decrease the size of the file first. I found a lot of links about this, however they all require the file to be saved on the device and then use FileOutputStream. I am looking for a way to reduce the file size so that it can be comfortably transferred using the Volley API ( i am currently receiving either run out of memory exceptions or broken pipe errors). Hence I am looking for a way to modify this code to be able to significantly decrease the file size, whilst still maintaining a quality which can be comfortably shown on a mobile device. The original image is taken straight from the camera hence the size is quite large. Here is my code:
ImageView pic_holder = (ImageView) findViewById(R.id.picturedisplay);
Bitmap bitmap = ((BitmapDrawable)pic_holder.getDrawable()).getBitmap();
ByteArrayOutputStream stream=new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 90, stream);
byte[] image=stream.toByteArray();
String img_str = Base64.encodeToString(image, 0);
I would like to decrease the size of the img_str which is passed to my Volley method.
Simply put I need to capture image using camera and upload it to facebook via my android application. And I successfully did that. The problem is when the photo posted in facebook, it's just too small and in low resolution while the image I took is in high resolution.
I understand that: in order to upload to facebook, i need to convert the captured image which is in bitmap format into byte array. So i have method for that:
public static byte[] convertBitmapToByteArray(Bitmap bm){
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bm.compress(CompressFormat.PNG, 100, bos);
byte[] bitmapdata = bos.toByteArray();
return bitmapdata;
}
Then to upload the image to facebook, i have code below where byteData is byte array I converted from bitmap image using the method above.
parameters.putString("message", "Test");
parameters.putByteArray("source", byteData);
String facebookResponse = facebookInstance.request(albumId+"/photos",parameters,"POST");
return facebookResponse;
I am pretty sure the problem is my convertBitmapToByteArray method since the method is to compress the bitmap image and turn it into byte array, and this made my image into low resolution image. However I can't seem to find the way to upload the image without converting it into byte array first. Any solution for me?
Alright even this thread is old, i found out the answer. It's not the problem of CompressFormant.JPEG or CompressFormat.JPG. Simply put, intent in android isn't designed to carry big data like image from activity through activity. I need to save the image from intent to sd card first before able to pull it out from there. It's my solution.
I have a method called loadFromCache and it returns a bitmap if it is found in the cache. Long story short I have it narrowed down to this method, returning null at the end if the try/catch fails.
FileInputStream fis = new FileInputStream(getCacheDir()+(""+position));
ObjectInputStream ois = new ObjectInputStream(fis);
Bitmap temp = (Bitmap)ois.readObject();
fis.close();
return temp;
I have previously tried the Bitmap.compress(...) methods to save bitmaps but they were a little slow for my needs... Yes the bitmap has been written to these positions, but I don't know if it (Bitmap) is serializable so is it actually saving? And yes I remembered to flush when I wrote the file.
How is Bitmap.compress() too slow for you? The only faster(?) way would be to write the bitmap unchanged to disk, see below.
Using MappedByteBuffer together with Bitmap.copyPixelsToBuffer() may work. I haven't tested this but it seems like it could work. Note that you most likely will have to store image dimensions yourself.
Sharing an experience I just had with Bitmap.compress being very slow:
My source image was a jpeg, and I was passing Bitmap.CompressFormat.PNG to bitmap.compress. This caused the compress operation to take 10-15 seconds.
Once I changed it to JPEG (such that the source and destination file remain the same image format) then the operation takes less than a second. Perhaps the original question came about through a similar means, and maybe someone else finds this helpful.