I have an app in which I read some gps data and I display them on the map and I also add an overlay at that position which is a small .png image.
I’m reading the data in an Async Task thread and in onProgressUpdate method I update my GUI by adding the overlay at a new position. Here is my code:
Drawable marker;
public void onCreate(Bundle savedInstanceState) {
marker=getResources().getDrawable(R.drawable.curent_loc);
marker.setBounds(0, 0, marker.getIntrinsicWidth(),
marker.getIntrinsicHeight());
}
In here I read the GPS data:
public class InitTask extends AsyncTask<Void, GeoPoint, Void> {
protected Void doInBackground(Void... voids) {
p = new GeoPoint(latitude, longitude);
publishProgress(p);
Thread.sleep(1500);
}
/*in here I update my GUI*/
protected void onProgressUpdate(GeoPoint... progress1) {
mapView.getOverlays().add(new SitesOverlay(marker,progress1[0]));
theRouteDraw(progress1[0]);
}
}
So I read a new location and I add an overlay at that position. For that I use my class SitesOverlay that extends Overlay.
Everything goes well until at some point where I receive the following exception:
java.lang.OutOfMemoryError: bitmap size exceeds VM budget
at android.graphics.BitmapFactory.nativeDecodeByteArray(Native Method)
at android.graphics.BitmapFactory.decodeByteArray(BitmapFactory.java:392)
at android.graphics.BitmapFactory.decodeByteArray(BitmapFactory.java:405)
at com.google.android.maps.StreetViewRenderer.getOverlay(StreetViewRenderer.java:149)
com.google.android.maps.StreetViewRenderer.renderTile(StreetViewRendere
at com.google.android.maps.AndroidTileOverlayRenderer.renderTile(AndroidTileOverlayRenderer.java:62)
at com.google.googlenav.map.Map.drawTile(Unknown Source)
at com.google.googlenav.map.Map.drawMapBackground(Unknown Source)
at com.google.googlenav.map.Map.drawMap(Unknown Source)
at com.google.android.maps.MapView.drawMap(MapView.java:1029)
at com.google.android.maps.MapView.onDraw(MapView.java:468)
at android.view.View.draw(View.java:6535)
at android.view.ViewGroup.drawChild(ViewGroup.java:1531)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1258)
at android.view.ViewGroup.drawChild(ViewGroup.java:1529)
I tried to recycle my drawable but still I get that error, and after a while I found this:
//decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f){
try {
//Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
//The new size we want to scale to
final int REQUIRED_SIZE=70;
//Find the correct scale value. It should be the power of 2.
int width_tmp=o.outWidth, height_tmp=o.outHeight;
int scale=1;
while(true){
if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
break;
width_tmp/=2;
height_tmp/=2;
scale*=2;
}
//Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {}
return null;
}
I found that in here:
Strange out of memory issue while loading an image to a Bitmap object
But I have a few problems in understanding it:
*First why is using a File f as a parameter? Is this the drawable I wanna use? Must this be done each time I use that drawable or only in onCreate()?
So if someone could explain how to use that I would be more than grateful, or if you have a simpler working solution it would be even better.
This has been a huge problem with Android for ages. The Bitmap class, getDrawable function etc relies on the underlying bitmap.h which is available as part of the NDK. Whenever a getDrawable returns a bitmap, due to some reason Android does not properly free the memory when we no longer need it.
One workaround I’ve used it to create a single static instance of the bitmap somewhere and weak reference it whenever you need to. This way atleast one instance of the bitmap is loaded onto the memory.
Hope this helps.