Using the com.google.android.maps API, I've got a MapActivity
which uses ItemizedOverlay
to place several (up to about 1000) icons on a MapView
. I want to refresh (or perhaps just add to the list of) the icons when the LocationListener
detects the device has moved a certain distance (currently 5 meters, but that's just for testing).
I've added setLastFocusedIndex(-1)
and populate()
, but my ItemizedOverlay is still crashing. I think it's crashing when I add more items to the list, but sometimes it seems to crash even if I don't move my phone. It crashes on the first update. I can't tell from LogCat exactly what's triggering the error.
My MapActivity is based off various tutorials:
EDIT: tweaked code to do a batch update of items but it still crashes
public class NearbyActivity extends MapActivity implements VenueCatalogListener {
private final String TAG = this.getClass().getSimpleName();
List<Overlay> mapOverlays;
HelloItemizedOverlay itemizedOverlay;
private MapController mapController;
private MapView mapView;
private LocationManager locationManager;
private int latE6;
private int lonE6;
private Location current_location;
private VenuesFromServer venues_from_server;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
venues_from_server = new VenuesFromServer(this);
setupViews();
}
private void setupViews() {
setContentView(R.layout.nearby_view);
RelativeLayout linearLayout = (RelativeLayout) findViewById(R.id.mapMainLayout);
mapView = new MapView(this, PreferencesManager.CLUBBERIA_MAPS_API_KEY);
initializeMap();
linearLayout.addView(mapView);
}
private void initializeMap() {
mapView.setKeepScreenOn(true);
mapView.setClickable(true);
mapView.setBuiltInZoomControls(true);
mapController = mapView.getController();
mapController.setZoom(mapView.getMaxZoomLevel()-5); // Zoom 1 is world view
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, new GeoUpdateHandler());
mapOverlays = mapView.getOverlays();
if(itemizedOverlay == null) {
Drawable drawable = this.getResources().getDrawable(R.drawable.icon);
itemizedOverlay = new HelloItemizedOverlay(drawable);
mapOverlays.add(itemizedOverlay);
}
}
@Override
protected boolean isRouteDisplayed() {
return false;
}
public class GeoUpdateHandler implements LocationListener {
@Override
public void onLocationChanged(Location location) {
if(current_location == null) {
current_location = location;
}
int lat = (int) (location.getLatitude() * 1E6);
int lng = (int) (location.getLongitude() * 1E6);
GeoPoint point = new GeoPoint(lat, lng);
if(current_location.distanceTo(location) > 5) {
// this kicks off an async task that will call back to venueListUpdated() below
venues_from_server.getVenueJSONFromServer(location.getLatitude(), location.getLongitude(), 19);
}
mapController.animateTo(point); // mapController.setCenter(point);
}
@Override
public void onProviderDisabled(String provider) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
}
@Override
public void venueListUpdated() {
// Base.B.arrayVenuesMap is an ArrayList<Venue>
for(int i=0;i<Base.B.arrayVenuesMap.size();i++) {
Venue _venue = Base.B.arrayVenuesMap.get(i);
latE6 = (int) (_venue.latitude*1e6);
lonE6 = (int) (_venue.longitude*1e6);
GeoPoint point = new GeoPoint(latE6, lonE6);
OverlayItem overlayitem = new OverlayItem(point, _venue.name, "");
Drawable drawable = this.getResources().getDrawable(R.drawable.icon);
itemizedOverlay.addOverlay(overlayitem, drawable);
}
itemizedOverlay.batchPopulate();
}
}
My ItemizedOverlay looks like this:
public class HelloItemizedOverlay extends ItemizedOverlay<OverlayItem> {
private ArrayList<OverlayItem> mOverlays = null;
public HelloItemizedOverlay(Drawable defaultMarker) {
super(boundCenterBottom(defaultMarker));
mOverlays = new ArrayList<OverlayItem>();
setLastFocusedIndex(-1);
populate();
}
public void addOverlay(OverlayItem overlay, Drawable defaultMarker) {
if(!mOverlays.contains(overlay)) {
setLastFocusedIndex(-1);
overlay.setMarker(boundCenterBottom(defaultMarker));
mOverlays.add(overlay);
}
}
public void batchPopulate() {
setLastFocusedIndex(-1);
populate();
}
@Override
protected OverlayItem createItem(int i) {
return mOverlays.get(i);
}
@Override
public int size() {
return mOverlays.size();
}
}
Logcat features the following lines:
11-24 18:28:02.245: D/AsyncJSONClient(18382): starting connect with this many pairs: 0; thread 17
11-24 18:28:02.255: E/AndroidRuntime(18382): FATAL EXCEPTION: main
11-24 18:28:02.255: E/AndroidRuntime(18382): java.lang.ArrayIndexOutOfBoundsException
11-24 18:28:02.255: E/AndroidRuntime(18382): at com.google.android.maps.ItemizedOverlay.getIndexToDraw(ItemizedOverlay.java:211)
11-24 18:28:02.255: E/AndroidRuntime(18382): at com.google.android.maps.ItemizedOverlay.draw(ItemizedOverlay.java:240)
11-24 18:28:02.255: E/AndroidRuntime(18382): at com.google.android.maps.Overlay.draw(Overlay.java:179)
11-24 18:28:02.255: E/AndroidRuntime(18382): at com.google.android.maps.OverlayBundle.draw(OverlayBundle.java:42)
11-24 18:28:02.255: E/AndroidRuntime(18382): at com.google.android.maps.MapView.onDraw(MapView.java:530)
11-24 18:28:02.255: E/AndroidRuntime(18382): at android.view.View.draw(View.java:6918)
11-24 18:28:02.255: E/AndroidRuntime(18382): at android.view.ViewGroup.drawChild(ViewGroup.java:1646)
11-24 18:28:02.255: E/AndroidRuntime(18382): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
11-24 18:28:02.255: E/AndroidRuntime(18382): at android.view.ViewGroup.drawChild(ViewGroup.java:1644)
11-24 18:28:02.255: E/AndroidRuntime(18382): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
11-24 18:28:02.255: E/AndroidRuntime(18382): at android.view.View.draw(View.java:6921)
11-24 18:28:02.255: E/AndroidRuntime(18382): at android.widget.FrameLayout.draw(FrameLayout.java:357)
11-24 18:28:02.255: E/AndroidRuntime(18382): at android.view.ViewGroup.drawChild(ViewGroup.java:1646)
11-24 18:28:02.255: E/AndroidRuntime(18382): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
11-24 18:28:02.255: E/AndroidRuntime(18382): at android.view.ViewGroup.drawChild(ViewGroup.java:1644)
11-24 18:28:02.255: E/AndroidRuntime(18382): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
11-24 18:28:02.255: E/AndroidRuntime(18382): at android.view.ViewGroup.drawChild(ViewGroup.java:1644)
11-24 18:28:02.255: E/AndroidRuntime(18382): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
11-24 18:28:02.255: E/AndroidRuntime(18382): at android.view.ViewGroup.drawChild(ViewGroup.java:1644)
11-24 18:28:02.255: E/AndroidRuntime(18382): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
11-24 18:28:02.255: E/AndroidRuntime(18382): at android.view.ViewGroup.drawChild(ViewGroup.java:1644)
11-24 18:28:02.255: E/AndroidRuntime(18382): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
11-24 18:28:02.255: E/AndroidRuntime(18382): at android.view.View.draw(View.java:6921)
11-24 18:28:02.255: E/AndroidRuntime(18382): at android.widget.FrameLayout.draw(FrameLayout.java:357)
11-24 18:28:02.255: E/AndroidRuntime(18382): at android.view.ViewGroup.drawChild(ViewGroup.java:1646)
11-24 18:28:02.255: E/AndroidRuntime(18382): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
11-24 18:28:02.255: E/AndroidRuntime(18382): at android.view.View.draw(View.java:6921)
11-24 18:28:02.255: E/AndroidRuntime(18382): at android.widget.FrameLayout.draw(FrameLayout.java:357)
11-24 18:28:02.255: E/AndroidRuntime(18382): at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1947)
11-24 18:28:02.255: E/AndroidRuntime(18382): at android.view.ViewRoot.draw(ViewRoot.java:1539)
11-24 18:28:02.255: E/AndroidRuntime(18382): at android.view.ViewRoot.performTraversals(ViewRoot.java:1275)
11-24 18:28:02.255: E/AndroidRuntime(18382): at android.view.ViewRoot.handleMessage(ViewRoot.java:1876)
11-24 18:28:02.255: E/AndroidRuntime(18382): at android.os.Handler.dispatchMessage(Handler.java:99)
11-24 18:28:02.255: E/AndroidRuntime(18382): at android.os.Looper.loop(Looper.java:123)
11-24 18:28:02.255: E/AndroidRuntime(18382): at android.app.ActivityThread.main(ActivityThread.java:3728)
11-24 18:28:02.255: E/AndroidRuntime(18382): at java.lang.reflect.Method.invokeNative(Native Method)
11-24 18:28:02.255: E/AndroidRuntime(18382): at java.lang.reflect.Method.invoke(Method.java:507)
11-24 18:28:02.255: E/AndroidRuntime(18382): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:864)
11-24 18:28:02.255: E/AndroidRuntime(18382): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:622)
11-24 18:28:02.255: E/AndroidRuntime(18382): at dalvik.system.NativeStart.main(Native Method)
11-24 18:28:02.255: W/ActivityManager(308): Force finishing activity com.clubberia.android/.ClubberiaMain
How can I occasionally add items to ItemizedOverlay without crashes?