0

I am drawing some overlays on google map. If i move around the map too much, I get this error :

10-15 14:43:43.020: ERROR/dalvikvm-heap(299): 32768-byte external allocation too large for this process. 10-15 14:43:43.020: ERROR/GraphicsJNI(299): VM won't let us allocate 32768 bytes 10-15 14:43:43.260: ERROR/AndroidRuntime(299): FATAL EXCEPTION: main 10-15 14:43:43.260: ERROR/AndroidRuntime(299): java.lang.OutOfMemoryError: bitmap size exceeds VM budget 10-15 14:43:43.260: ERROR/AndroidRuntime(299): at android.graphics.Bitmap.nativeCreate(Native Method) 10-15 14:43:43.260: ERROR/AndroidRuntime(299): at android.graphics.Bitmap.createBitmap(Bitmap.java:468)

In my heap, I can see that less than 30% has been used.

Can anyone help me out ? Is there a way out ? Thanks.

///////////////////////////////////////////////

public void draw(Canvas canvas, MapView mapv, boolean shadow){

    BusLoc.myMapView.destroyDrawingCache ();
    super.draw(canvas, mapv, shadow);

    Paint mPaint = new Paint();
    mPaint.setDither(true);
    mPaint.setColor(Color.RED);
    mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
    mPaint.setStrokeJoin(Paint.Join.ROUND);
    mPaint.setStrokeCap(Paint.Cap.ROUND);
    mPaint.setStrokeWidth(2);

    /////////////////////////////get the lat/long info/////////////////////////////////////

    BusLoc.mapCenter= BusLoc.myMapView.getMapCenter();
    int latCenter = BusLoc.mapCenter.getLatitudeE6();
    int longCenter = BusLoc.mapCenter.getLongitudeE6();
    int latSpan = BusLoc.myMapView.getLatitudeSpan();
    int longSpan = BusLoc.myMapView.getLongitudeSpan();
    int latMax = latCenter + (latSpan / 2);
    int latMin = latCenter - (latSpan / 2);
    int longMax = longCenter + (longSpan / 2);
    int longMin = longCenter - (longSpan / 2);

    ///////////////////////////////////////////////////////////////////////////////////////


    Log.d("MyOverlay","OnDraw");

    int in=0;
    for(in=0;in<ind-1;in++)
    {
        if (ah1[in][0] ==0 ||(ah1[in+1][0]==0)) break;
        if((ah1[in][0] !=0) &&(ah1[in+1][0]!=0))
        {
            GeoPoint gP1 = new GeoPoint((int)(ah1[in][0]*1e6),(int)(ah1[in][1]*1e6)); //lat,lng
            GeoPoint gP2 = new GeoPoint((int)(ah1[in+1][0]*1e6),(int)(ah1[in+1][1]*1e6));



            Point p1 = new Point();
            Point p2 = new Point();

            Path path = new Path();

            Projection projection = BusLoc.myMapView.getProjection();
            projection.toPixels(gP1, p1);
            projection.toPixels(gP2, p2);

            path.moveTo(p2.x, p2.y);
            path.lineTo(p1.x,p1.y);

            if((((ah1[in][0]<=latMax)&&(ah1[in][0]>=latMin))&&((ah1[in][1]<=longMax)&&(ah1[in][1]>=longMin))) || (((ah1[in+1][0]<=latMax)&&(ah1[in+1][0]>=latMin))&&((ah1[in+1][1]<=longMax)&&(ah1[in+1][1]>=longMin))) )
            {
                canvas.drawPath(path, mPaint);
            }

            Log.d("MyOverlay","drawn: "+gP1.toString()+":"+gP2.toString());
        }
    }
   // BusLoc.myMapView.destroyDrawingCache ();
}
Ahsan
  • 2,964
  • 11
  • 53
  • 96
  • how do you see that 30% of your heap is used only? bitmaps don't use jvm heap, but native heap. See my reply at http://stackoverflow.com/questions/3238388/android-out-of-memory-exception-in-gallery/3238945#3238945 – Mathias Conradt Oct 15 '10 at 16:37
  • thanks @Mathias Lin ..will try out your idea too.. and let you know how it helps... btw...just so that you know.. I was excited about the heap thingy because, previosuly i had inefficient sparse array coding which meant a heap usage of 90% or more...and now with only 30% I was expecting it to be better ! – Ahsan Oct 15 '10 at 16:51
  • @ Mathias Lin: this is what I get before the error !! – Ahsan Oct 16 '10 at 13:34
  • 10-16 13:33:10.548: INFO/System.out(1596): alloc: 6.912223815917969 : available: 7.0703125 Please suggest as to what I can do. Thanks. – Ahsan Oct 16 '10 at 13:37
  • and this ...10-16 13:40:01.658: INFO/System.out(1661): alloc: 7.0171661376953125 : available: 7.10546875 – Ahsan Oct 16 '10 at 13:40
  • so, around 50% of the native heap is being used..how to reduce the usage ? – Ahsan Oct 16 '10 at 13:40
  • On a side-note: don't draw `Path`s, you won't get any hardware acceleration from that. use `drawLines()` instead. It uses a `float` array instead of `Path`s and is much faster performance wise. – ubuntudroid Mar 05 '13 at 10:43

1 Answers1

2

You should explicitly only the draw the overlays that are visible on your screen, if not all the overlays are drawn whether you see them or not, this not only cause trouble with memory but makes moving the map very slow on the not so good devices.

MapController mapControl = map.getController();
        GeoPoint mapCenter = map.getMapCenter();
        int latCenter = mapCenter.getLatitudeE6();
        int longCenter = mapCenter.getLongitudeE6();
        int latSpan = map.getLatitudeSpan();
        int longSpan = map.getLongitudeSpan();
        int latMax = latCenter + (latSpan / 2);
        int latMin = latCenter - (latSpan / 2);
        int longMax = longCenter + (longSpan / 2);
        int longMin = longCenter - (longSpan / 2);

Write some code to detect whether your point of interest is within that viewing range, if it is draw it, if not dont.

I also would asume you are using a small overlay indicator, they can be really tiny and low dpi without loosing quality.

blindstuff
  • 18,298
  • 10
  • 47
  • 48
  • thanks a lot @blindstuff ..I really appreciate the help. I will be working on this idea right now and try to see if this helps or not. Thanks. – Ahsan Oct 15 '10 at 16:48
  • Hi... Sorry its not working..it holds off the error till much further..but after sometimes it has the same problem. I am attaching the draw code to the problem. ! – Ahsan Oct 15 '10 at 18:00
  • Thats odd, your code looks fine. I would try to draw a drawable instead of a line, just any random image, if you want a drawable on the start and end point to see if the error is in the creation of the line using paint or on the map it self. – blindstuff Oct 15 '10 at 18:56
  • @ Blindstuff: the code is not very convenient for me...i mean...because, i am drawing lines...even if the two points are not in the view..the line might be inside the view...and since the line drawing is very important...so....I cant use your code.... but thanks for the code sample, I may use it for overlaying ...stuffs..(and not drawing lines).. :) – Ahsan Oct 16 '10 at 15:44
  • 1
    Did you figure out what the problem was? You should only draw if at least one of the points is in the screen then, but dont draw the line when neither point is on the screen. I have an app overlaying about 7000 points and it went from been unsable to perfect just by that change. – blindstuff Oct 18 '10 at 16:12