I am downloading images from the internet which I am displaying in my app. I am saving those images to file so that I can read them from disk instead of accessing the internet again.
On modern devices I am not getting any issues with this approach, but on an older device (which I am intending to target) I am getting an OutOfMemoryError when loading images from file.
The baffling thing is I do not have any issue if the image is downloaded from the internet, just when the bitmap is read in from file. It's like the image is getting much larger when I save it to file or something, but I don't know why.
This is the error I'm getting:
Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget(Heap Size=9607KB, Allocated=5143KB, Bitmap Size=24888KB)
at android.graphics.BitmapFactory.nativeDecodeFile(Native Method)
at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:355)
at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:434)
at scave.reforge.img.DBitmap.readBitmap(DBitmap.java:327)
at scave.reforge.img.DBitmap.updateBitmap(DBitmap.java:306)
This is my code:
/** Our bitmap object. */
protected Bitmap _bitmap;
public void updateBitmap(Context inContext)
{
// Reset the bitmap for good measure
if(_bitmap != null)
{
_bitmap.recycle();
_bitmap = null;
}
// Grab the cache file provided it exists
final File imageFile = new File(getBitmapCacheDir(inContext), getFilename());
// If we had a cache hit, load the bitmap from the cache
if(imageFile.exists())
this.readBitmap(imageFile);
// If we had a cache miss, download the bitmap from the internet and save it in our cache
else
this.downloadBitmap().saveBitmap(inContext);
}
private void readBitmap(File inFilePath)
{
_bitmap = BitmapFactory.decodeFile(inFilePath.getPath());
}
private void downloadBitmap()
{
// Our input stream
InputStream in = null;
try
{
// Open the URL stream
in = new java.net.URL(_url).openStream();
// Download the bitmap
_bitmap = BitmapFactory.decodeStream(in);
}
catch(Exception e)
{
// Log if there was an error
Log.e("TAG", "Error downloading image", e);
_bitmap = null;
}
finally
{
try
{
// Close the input stream if it is open
if(in != null)
in.close();
}
catch(IOException e)
{
// Log if there was an error
Log.e("TAG", "Error closing stream \"in\"", e);
}
}
}
private void saveBitmap(Context inContext)
{
if(_bitmap == null)
return;
// Open the cache directory
File imageFile = new File(getBitmapCacheDir(inContext), getFilename());
// Our output stream
FileOutputStream out = null;
try
{
// Open the output stream
out = new FileOutputStream(imageFile);
// Write the bitmap to the cache
_bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
}
catch(Exception e)
{
// Log if there was an error
Log.e("saveBitmap()", "Error while saving bitmap : ", e);
}
finally
{
try
{
// Close the output stream
if(out != null)
out.close();
}
catch(IOException e)
{
// Log if there was an error
Log.e("saveBitmap()", "Error while closing out : ", e);
}
}
}
None of the other questions I've found about this sort of error have been able to explain why the app works if I just download from the internet all the time but not if I read bitmaps from file. Any help is appreciated.