Nov 19, 2011

Android :: google maps (MapView) hacks, tricks, workarounds

MapView isn't very developer friendly now is it?

Here are some hacks I've had to work with:

1) When tapping on the overlay, the app crashes if you're trying to display the dialog.
Unable to add window -- token null is not for an application
Yes, this is due to context. Especially if you're trying to do this in a seperate thread or AsyncTask.
Turns out the context you need to pass to your dialog is mapView.getContext();
AlertDialog.Builder dialog = new AlertDialog.Builder(mapView.getContext());




2) Displaying only the overlays which are within map bounds
Oh yeah, several problems here. You've probably come across at least one of these:

  • Wrong map bounds in onCreate (0, 360000000),
    Yeah, in onCreate those haven't been calculated yet. onStart doesn't help either. Try this:
Runnable waitForMapTimeTask = new Runnable() {
  public void run() {
    if(mapView.getLatitudeSpan()==0||mapView.getLongitudeSpan()== 360000000) {
      mapView.postDelayed(this, 100);
    } else {
      redrawMarkers(); // draw here
    }
  }
};
mapView.postDelayed(waitForMapTimeTask, 100);

You create a new thread and wait until you get the right bounds. Recursively call it again.
  • Map bounds ???
    Don't worry, it's simple.
public Rect getMapBounds() {
return new Rect(
mapView.getMapCenter().getLongitudeE6() - mapView.getLongitudeSpan()/2,
mapView.getMapCenter().getLatitudeE6() - mapView.getLatitudeSpan()/2,
mapView.getMapCenter().getLongitudeE6() + mapView.getLongitudeSpan()/2,
mapView.getMapCenter().getLatitudeE6() + mapView.getLatitudeSpan()/2
);
}

...
if(!s.drawn && rect.contains(point.getLongitudeE6(), point.getLatitudeE6())) {


  • Yeah, okay, but what about panning / zooming?
    Well, there are no methods, like onPan or onZoom, but some people found their way around this problem. There is no perfect solution, you'll see.
    Check these links out:
  1. http://stackoverflow.com/questions/2328650/how-can-i-detect-if-an-android-mapview-has-been-panned-or-zoomed
  2. http://bricolsoftconsulting.com/2011/10/31/extending-mapview-to-add-a-change-event/
  3. http://stackoverflow.com/questions/3567420/how-to-catch-that-map-panning-and-zoom-are-really-finished
  • Zoom in on double tap?
    Click here: http://dev.kafol.net/2011/11/how-hard-is-it-to-make-simple-zoom-in.html.
  • Overlays don't get drawn immediately!
    Try this:
    mapView.postInvalidate();
    or this:
    mapView.invalidate();

    But keep in mind, that invalidate() needs to be called from an UI! If you're trying to get it working from a thread, use postInvalidate()!
  • MapView java.util.ConcurrentModificationException when adding new overlays
    Not sure if I solved this one, but it seems to work now. I read somewhere that this could happen if you add overlays in a non UI thread. I moved the 
    Nope, sorry, this one was my bad. I was doing some crazy async sorting and all hell broke loose.
itemizedOverlay.populateNow();
mapOverlays.add(itemizedOverlay);
mapView.postInvalidate();

From doInBackground to  onPostExecute in  AsyncTask.


You could also run something in a UI thread like this:

runOnUiThread(new Runnable() {
      @Override
       public void run() {
           //do stuff here
       }
});



No comments: