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?
ni know its a bit old, but @cgwylie is almost right..
you should call populate()
after updating overlays values... and then you can call the postInvalidate()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With