I'm getting quite a few OutOfMemoryError reports from my users and every single report is from the same Activity, which contains a MapView. I'm thinking that it's an isolated exception with just this one place in my app, and I can't figure out what the problem is. Can anybody give me some pointers as to why this is happening?
I've removed some unneeded code for this question, so if somebody thinks the issue could potentially be in that, I'll post it.
Stack Traces
Stack Trace #1
java.lang.OutOfMemoryError: bitmap size exceeds VM budget
at android.graphics.Bitmap.nativeCreate(Native Method)
at android.graphics.Bitmap.createBitmap(Bitmap.java:677)
at com.google.android.maps.ZoomHelper.createSnapshot(ZoomHelper.java:444)
at com.google.android.maps.ZoomHelper.beginZoom(ZoomHelper.java:194)
at com.google.android.maps.MapView$2.onScaleBegin(MapView.java:371)
at android.view.ScaleGestureDetector.onTouchEvent(ScaleGestureDetector.java:216)
at com.google.android.maps.MapView.onTouchEvent(MapView.java:646)
at android.view.View.dispatchTouchEvent(View.java:3778)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:920)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:959)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:959)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:959)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1716)
at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1124)
at android.app.Activity.dispatchTouchEvent(Activity.java:2125)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1700)
at android.view.ViewRoot.handleMessage(ViewRoot.java:1822)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:143)
at android.app.ActivityThread.main(ActivityThread.java:5068)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
at dalvik.system.NativeStart.main(Native Method)
Stack Trace #2
java.lang.OutOfMemoryError: bitmap size exceeds VM budget
at android.graphics.Bitmap.nativeCreate(Native Method)
at android.graphics.Bitmap.createBitmap(Bitmap.java:468)
at com.google.android.maps.ZoomHelper.createSnapshot(ZoomHelper.java:444)
at com.google.android.maps.ZoomHelper.doZoom(ZoomHelper.java:151)
at com.google.android.maps.ZoomHelper.doZoom(ZoomHelper.java:140)
at com.google.android.maps.MapView.doZoom(MapView.java:1478)
at com.google.android.maps.MapView.doZoom(MapView.java:1487)
at com.google.android.maps.MapController.zoomOut(MapController.java:439)
at com.hookedroid.fishingcompanion.GoogleMaps$3.onClick(GoogleMaps.java:133)
at android.view.View.performClick(View.java:2405)
at android.view.View$PerformClick.run(View.java:8813)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4627)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
at dalvik.system.NativeStart.main(Native Method)
Stack Trace #3
java.lang.OutOfMemoryError: bitmap size exceeds VM budget
at android.graphics.Bitmap.nativeCreate(Native Method)
at android.graphics.Bitmap.createBitmap(Bitmap.java:468)
at android.graphics.Bitmap.createBitmap(Bitmap.java:435)
at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:340)
at android.graphics.BitmapFactory.finishDecode(BitmapFactory.java:488)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:462)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:323)
at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:346)
at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:372)
at com.hookedroid.fishingcompanion.maps.CrosshairOverlay.draw(CrosshairOverlay.java:32)
at com.google.android.maps.OverlayBundle.draw(OverlayBundle.java:45)
at com.google.android.maps.MapView.onDraw(MapView.java:494)
at android.view.View.draw(View.java:6742)
at android.view.ViewGroup.drawChild(ViewGroup.java:1640)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)
at android.view.ViewGroup.drawChild(ViewGroup.java:1638)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)
at android.view.View.draw(View.java:6745)
at android.widget.FrameLayout.draw(FrameLayout.java:352)
at android.view.ViewGroup.drawChild(ViewGroup.java:1640)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)
at android.view.View.draw(View.java:6745)
at android.widget.FrameLayout.draw(FrameLayout.java:352)
at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1913)
at android.view.ViewRoot.draw(ViewRoot.java:1407)
at android.view.ViewRoot.performTraversals(ViewRoot.java:1163)
at android.view.ViewRoot.handleMessage(ViewRoot.java:1727)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4646)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
at dalvik.system.NativeStart.main(Native Method)
Activity
public class GoogleMaps extends MapActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.googlemaps_layout);
intent = getIntent();
currentMode = intent.getIntExtra("MAP_MODE", 0);
initControls();
initMembers();
currentOverlayMode = prefs.getInt("map_viewmode", 0);
populateMap();
}
private void initMembers() {
mDbHelper = new FishingCompanionDB(this);
mDbHelper.open();
catchList = new ArrayList<FishEntry>();
prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefsEditor = prefs.edit();
}
private void initControls() {
mMaps = (MapView)findViewById(R.id.google_maps);
mMaps.setClickable(true);
mMaps.setLongClickable(true);
mapController = mMaps.getController();
mOverlayModeBtn = (Button)findViewById(R.id.googlemaps_overlay_btn);
mOverlayModeBtn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (currentOverlayMode < 1)
currentOverlayMode++;
else
currentOverlayMode = 0;
switch (currentOverlayMode) {
case OVERLAY_STREET:
mMaps.setSatellite(false);
mMaps.setStreetView(true);
prefsEditor.putInt("map_viewmode", OVERLAY_STREET);
break;
case OVERLAY_SAT:
mMaps.setStreetView(false);
mMaps.setSatellite(true);
prefsEditor.putInt("map_viewmode", OVERLAY_SAT);
break;
}
prefsEditor.commit();
mMaps.invalidate();
}
});
mZoomInBtn = (Button)findViewById(R.id.googlemaps_btn_zoomin);
mZoomInBtn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mapController.zoomIn();
}
});
mZoomOutBtn = (Button)findViewById(R.id.googlemaps_btn_zoomout);
mZoomOutBtn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mapController.zoomOut();
}
});
}
private void populateMap() {
overlays = mMaps.getOverlays();
overlays.clear();
overlays.add(new CrosshairOverlay(this, R.drawable.mapcenter));
mSelectPos = (Button)findViewById(R.id.googlemaps_select_location);
mSelectPos.setVisibility(View.VISIBLE);
mSelectPos.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
GeoPoint centerGp = mMaps.getMapCenter();
double lat = centerGp.getLatitudeE6()/1E6;
double lng = centerGp.getLongitudeE6()/1E6;
Intent i;
if (currentMode == SELECT_POS_WEATHER) {
i = new Intent(GoogleMaps.this, WeatherLookup.class);
i.putExtra("WEATHER_LAT", lat);
i.putExtra("WEATHER_LNG", lng);
}
else {
i = new Intent(GoogleMaps.this, AddLocation.class);
i.putExtra("LOCATION_LAT", lat);
i.putExtra("LOCATION_LNG", lng);
}
i.putExtra("MODE", 1);
startActivity(i);
finish();
}
});
mMaps.invalidate();
}
@Override
protected boolean isRouteDisplayed() {
return false;
}
}
Crosshair Overlay
public class CrosshairOverlay extends Overlay {
private Context mContext;
private int resourceId;
public CrosshairOverlay(Context context, int resId) {
this.mContext = context;
this.resourceId = resId;
}
public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when) {
super.draw(canvas, mapView, shadow);
GeoPoint centerGp = mapView.getMapCenter();
Projection projection = mapView.getProjection();
Point centerPoint = projection.toPixels(centerGp, null);
Paint p = new Paint();
Bitmap bmp = BitmapFactory.decodeResource(mContext.getResources(), resourceId);
canvas.drawBitmap(bmp, (centerPoint.x - (bmp.getWidth()/2)), (centerPoint.y - (bmp.getHeight()/2)), p);
return true;
}
}
DUMPSYS MEMINFO
** MEMINFO in pid 25493 [com.hookedroid.fishingcompanion] **
native dalvik other total
size: 10036 7495 N/A 17531
allocated: 9955 3965 N/A 13920
free: 80 3530 N/A 3610
(Pss): 3717 1480 6703 11900
(shared dirty): 668 1512 8056 10236
(priv dirty): 3696 804 5024 9524
Objects
Views: 0 ViewRoots: 0
AppContexts: 0 Activities: 0
Assets: 3 AssetManagers: 3
Local Binders: 19 Proxy Binders: 21
Death Recipients: 1
OpenSSL Sockets: 0
SQL
heap: 527 MEMORY_USED: 527
PAGECACHE_OVERFLOW: 62 MALLOC_SIZE: 50
DATABASES
pgsz dbsz Lookaside(b) Dbname
1 16 260 FishingCompanion
1 18 63 google_analytics.db