21

I want to do the following and am kind of stuck on these for a few days:

  1. I was trying to draw polylines (I have encoded polylines, but have managed to decode those) that move when I move the map.
    The only solution that I found was for Geopoints to be transformed into screen coordinates... which won't move if I move the map.

  2. I used HelloItemizedOverlay to add about 150 markers and it gets very very slow.
    Any idea what to do? I was thinking about threads (handler).

  3. I was looking for some sort of a timer function that executes a given function periodically, say, every 1 minute or so.

  4. I was also looking for ways to clear the Google map from all the markers/lines, etc.

Sk8erPeter
  • 6,899
  • 9
  • 48
  • 67
Ahsan
  • 2,964
  • 11
  • 53
  • 96
  • 1
    q 1 is solved...I found the answer while browsing through stackoverflow.com... :) The solve is posted here http://stackoverflow.com/questions/2176397/want-to-draw-a-line-or-path-on-google-map-in-hellomapview – Ahsan May 17 '10 at 11:56
  • 1
    q4 ...is solved, I found the answer at stackoverflow.com ...the solve is :..use this code if(!mapOverlays.isEmpty()) { mapOverlays.clear(); mapView.invalidate(); } – Ahsan May 18 '10 at 11:11
  • 3
    q2 solved, found on ostackoverflow.com ... ////////////////////////// createMarkers(){ for(elem:bigList){ GeoPoint geoPoint = new GeoPoint((int)(elem.getLat()*1000000), (int) (elem.getLon()*1000000)); OverlayItem overlayItem = new OverlayItem(geoPoint, elem.getName(), elem.getData()); itemizedOverlay.addOverlay(overlayItem); } itemizedOverlay.populateNow(); mapOverlays.add(itemizedOverlay); //outside of for loop } and in MyOverlay: public void addOverlay(OverlayItem overlay) { m_overlays.add(overlay); } public void populateNow(){ populate(); } – Ahsan May 19 '10 at 14:46
  • 1
    q 3 solved.... at stackoverflow.com http://stackoverflow.com/questions/1877417/how-to-set-a-timer-in-android – Ahsan May 19 '10 at 14:51
  • 1
    q3 --the better approach :) http://life.csu.edu.au/java-tut/essential/threads/timer.html – Ahsan May 19 '10 at 18:10
  • hi could you post where on stackoverflow you found the answer for Q2 I already dealing with the same issue, and I couldn't find to much information – Pedro Teran May 02 '12 at 20:03
  • @PedroTeran : I have given some code in the first answer. That should help. I have asked this question and researched the issues more than a year back. I dont have those links with me. If you want, you can let me know your approach (perhaps as an answer to this que and I will try to help). – Ahsan May 02 '12 at 21:06
  • Already solved partially I didn't noticed that your answer was the same that your posted as comment, so at first I thought it wasn't efficient enough to handle 400 overlay items. but at least for now is working fine, thanks a lot your post was really helpful – Pedro Teran May 02 '12 at 21:18
  • @PedroTeran : You welcome.... Am happy that my efforts paid off and somebody's life became a little easier. :) – Ahsan May 02 '12 at 23:41

5 Answers5

11

Answers given below :

1) Here's a solution that I used :

/** Called when the activity is first created. */
private List<Overlay> mapOverlays;

private Projection projection;  

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    linearLayout = (LinearLayout) findViewById(R.id.zoomview);
    mapView = (MapView) findViewById(R.id.mapview);
    mapView.setBuiltInZoomControls(true);

    mapOverlays = mapView.getOverlays();        
    projection = mapView.getProjection();
    mapOverlays.add(new MyOverlay());        

}

@Override
protected boolean isRouteDisplayed() {
    return false;
}

class MyOverlay extends Overlay{

    public MyOverlay(){

    }   

    public void draw(Canvas canvas, MapView mapv, boolean shadow){
        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);

        GeoPoint gP1 = new GeoPoint(19240000,-99120000);
        GeoPoint gP2 = new GeoPoint(37423157, -122085008);

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

    Path    path = new Path();

    Projection  projection.toPixels(gP1, p1);
        projection.toPixels(gP2, p2);

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

        canvas.drawPath(path, mPaint);
    }

courtesy: Drawing a line/path on Google Maps

2) Here's what worked for me :

createMarkers()
{ 
    for(elem:bigList)
    { 
        GeoPoint geoPoint = new GeoPoint((int)(elem.getLat()*1000000), (int) (elem.getLon()*1000000)); 
        OverlayItem overlayItem = new OverlayItem(geoPoint, elem.getName(), elem.getData()); 
        itemizedOverlay.addOverlay(overlayItem); 
    } 

    itemizedOverlay.populateNow(); 
    mapOverlays.add(itemizedOverlay); //outside of for loop 
} 

and in MyOverlay:

public void addOverlay(OverlayItem overlay) 
{ 
    m_overlays.add(overlay); 
} 

public void populateNow()
{
    populate(); 
}

courtesy: stackoverflow.com unknown link

3) The best way is to use a timer class. A very detailed description of the timer class and how to use it is given at this link :

http://life.csu.edu.au/java-tut/essential/threads/timer.html

4) I used this code :

if(!mapOverlays.isEmpty()) 
{ 
    mapOverlays.clear(); 
    mapView.invalidate(); 
} 

Hope these answers help atleast one other person. Thanks.

Community
  • 1
  • 1
Ahsan
  • 2,964
  • 11
  • 53
  • 96
  • 1
    You should provide your solution in a separate answer and not in comments. It's better for everybody and it enables you to use formatting for the code. – Catalin Morosan Jul 14 '10 at 10:53
  • 1
    You are the man. I was having a task for plotting 200/300 pins on map, and i was having trouble of not having Smoothness. So during my R&D, i came across this article and you are the man. Thank you so much. **Solution for plotting multiple pins on MapView** is step-2 – Paresh Mayani Jul 18 '12 at 09:19
  • 1
    Thank you so much...freinds..i am was suffering last two days your solution is amazing – QuokMoon Sep 11 '12 at 06:07
2

I have the same problem. We are developing an iphone app and an android app at the same time. I have 2500 + map overlays. No problem on iphone; a huge performance hit on android when calling populate() after adding all overlays. (Of course, my first try was to call populate() every time after adding an overlay; a typical mistake due to google's tutorial. Now I am calling populate() just once, after all 2500+ overlays have been added to the ItemizedOverlay.)

So the single populate() call takes over 40 seconds to complete on an htc hero device. I had to put in a busy indicator; no progress bar is possible because we cannot get any information about the progress of populate().

I tried another solution: not use ItemizedOverlay but add overlays by hand, subclassing Overlay. Result: indeed it is much faster to add all those overlays to the map; however, the map becomes unusable due to constant calling of the draw() method on each overlay. In my draw method, I tried to optimize as much as possible; I do not create a bitmap every time. My draw() method looks like this:

public void draw(android.graphics.Canvas canvas, MapView mapView, boolean shadow)  {
// our marker bitmap already includes shadow.
// centerPoint is the geopoint where we need to put the marker.
 if (!shadow) {
  Point point = new Point();  
  mapView.getProjection().toPixels(centerPoint, point);
  canvas.drawBitmap(markerBitmap, point.x, point.y, null);
 }

}

Here markerBitmap is precomputed. I don't know what else I could optimize. Is there some kind of populate() call required if we are not using ItemizedOverlay??? I could not find any good answers for that.

Right now I resort to caching the ItemizedOverlay once it has been created in a background thread. This way at least the user does not have to wait every time.

winitzki
  • 3,179
  • 24
  • 32
  • Adding 2500 markers is practically impossible on Android. The solution in that project was, first, to find out the markers visible on the current portion of the map. (This has to be recomputed each time after panning/zooming.) Then we check that there are <100 markers, otherwise not all of them need to be shown. The 100 markers can be added to a map within a few seconds. All this, of course, is on a background thread, so the user looks at a rotating circle while we are waiting for populate() to finish. On iPhone, the analogous code is instantaneous (2500 markers were also a bit slow). – winitzki Dec 11 '12 at 09:19
0

For #2, I don't think you solved anything there. Your hard-to-read code is showing how to put markers on overlay and then, how to add that overlay to the map. That's exactly how I do it. I have map with around 300 hotels and it takes around 5 seconds for Android on my Nexus One to create markers. The whole thing is running inside thread and I guess I will have to do some sort of progress bar to let user know what's going on.

I am working on app that already exists on iPhone and it seems iPhone doesn't have any issues to almost instantaneously draw these 300+ markers. I'll have hard time to explain existence of progress bar to my bosses.

If anybody have idea how to optimize this process... I will be grateful.

Here is my code:

    ...
        for (int m = 0; m < ArrList.size(); m++) {
            tName = ArrList.get(m).get("name").toString();
            tId = ArrList.get(m).get("id").toString();
            tLat = ArrList.get(m).get("lat").toString();;
            tLng = ArrList.get(m).get("lng").toString();;
            try {
                lat = Double.parseDouble(tLat);
                lng = Double.parseDouble(tLng);
                p1 = new GeoPoint(
                        (int) (lat * 1E6), 
                        (int) (lng * 1E6));
                OverlayItem overlayitem = new OverlayItem(p1, tName, tId);
                itemizedoverlay.addOverlay(overlayitem);
            } catch (NumberFormatException e) {
                Log.d(TAG, "NumberFormatException" + e);    
            }
        } 

I know I could save some time by avoiding this String > Double conversion, but I don't feel that would give me significant saving.. or it would?

bobetko
  • 5,019
  • 14
  • 58
  • 85
-2

For your 4th question, simply use the mapOverlays.clear(); method and all the previous markers will be vanished.

if(!mapOverlays.isEmpty()) { 
    mapOverlays.clear();
    mapView.invalidate();
}
user16217248
  • 3,119
  • 19
  • 19
  • 37
bhejaFry
  • 715
  • 1
  • 7
  • 12
-3

Multiple number of drawable objects can be added to a single Overlay which can then be added to the map. Hence, drawing x number of overlay's for x number of objects wouldnt be necessary unless the objects are of different types. Code snippet.. .. Here, CustomPinPoint is my class which extends ItemizedOverlay<OverlayItem>

CustomPinPoint customPinPoint = new CustomPinPoint(drawable, Main.this);

OverlayItem tempOverLayItem = new OverlayItem(
    touchedPoint, "PinPoint", "PintPoint 2"); //Point One
customPinPoint.insertPinPoint(tempOverLayItem);
tempOverLayItem = new OverlayItem(new GeoPoint(
        (int)(-27.34498 * 1E6), (int)(153.00724 * 1E6)), "PinPoint",
    "PintPoint 2"); //Point Two
customPinPoint.insertPinPoint(tempOverLayItem);
overlayList.add(customPinPoint); //Overlay added only once
Sk8erPeter
  • 6,899
  • 9
  • 48
  • 67
Sudhir
  • 1