Redraw/refresh Itemizedoverlay? (android/google maps api)

AndroidNoob picture AndroidNoob · May 16, 2011 · Viewed 11.3k times · Source

I am making a GPS tracker using google maps API and displaying the users current position on a map using ItemizedOverylay. As the users position changes regularly, I've set up a CountDownTimer to delete the current Itemizedoverlay and add a new one at the new position every 5 seconds (there is no way of changing an itemizedOverlay's position) but the screen isn't drawing the new positions unless i physically touch the screen! Here is the code for my itemized overlay:

import java.util.ArrayList;
import java.util.List;

import android.app.AlertDialog;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.widget.Toast;

import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.OverlayItem;

public class HelloItemizedOverlay extends ItemizedOverlay{
private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
Context mContext;

public HelloItemizedOverlay(Drawable defaultMarker) {
    /*This passes the defaultMarker up to the default constructor 
     * to bound its coordinates and then initialize mContext with the given Context.*/
    super(boundCenterBottom(defaultMarker));
}
public HelloItemizedOverlay(Drawable defaultMarker, Context context) {
    /*This passes the defaultMarker up to the default constructor 
     * to bound its coordinates and then initialize mContext with the given Context.*/
    super(boundCenterBottom(defaultMarker));
      mContext = context;
}
@Override
protected boolean onTap(int index) {
/*This uses the member android.content.Context to create 
 * a new AlertDialog.Builder and uses the tapped OverlayItem's title 
 * and snippet for the dialog's title and message text. (You'll see the 
 * OverlayItem title and snippet defined when you create it below.)*/

  OverlayItem item = mOverlays.get(index);
  AlertDialog.Builder dialog = new AlertDialog.Builder(mContext);
  dialog.setTitle(item.getTitle());
  dialog.setMessage(item.getSnippet());
  dialog.show();
  return true;
}
public void addOverlay(OverlayItem overlay) {
    mOverlays.add(overlay);
    /*Each time you add a new OverlayItem to the ArrayList, you must 
     * call populate() for the ItemizedOverlay, which will read each 
     * of the OverlayItems and prepare them to be drawn.*/
    populate();
}
public void addOverlayList(List<OverlayItem> overlayitems) {
    Object temp[] = overlayitems.toArray();
    try{
        for(int i = 0;i<temp.length;i++)
        {
            mOverlays.add((OverlayItem)temp[i]);
        }
    }catch(Error e)
    {
        Toast.makeText(mContext, "Something happened when adding the overlays:"+e.getMessage() ,
                Toast.LENGTH_LONG).show();
    }

    populate();
}
public void removeOverlayList(List<OverlayItem> overlayitems) {
    Object temp[] = overlayitems.toArray();
    try{
        for(int i = 0;i<temp.length;i++)
        {
            mOverlays.remove((OverlayItem)temp[i]);
        }
    }catch(Error e)
    {
        Toast.makeText(mContext, "Something happened when adding the overlays:"+e.getMessage() ,
                Toast.LENGTH_LONG).show();
    }

    populate();
}
public void removeOverlay(OverlayItem overlay){
    mOverlays.remove(overlay);
    populate();
}
public void doPopulate()
{
    populate();
}

@Override
protected OverlayItem createItem(int i) {
    // TODO Auto-generated method stub
    return mOverlays.get(i);
}

@Override
public int size() {
    /*You must also override the size() method to return the current 
     * number of items in the ArrayList:*/
    return mOverlays.size();
}

}

Does anyone know if there is a method or something I can call to force a redraw/refresh when I put the new items in?

EDIT: Here is a snippet of the MapsActivity:

public class HelloGoogleMaps extends MapActivity  {

/***************************
 * map stuff
 *****/


HelloItemizedOverlay myPosition;
MapView mapView;
MapController mapController;
List<Overlay> mapOverlays;

OverlayItem myPositionOverlayItem;

public double myLatitude = 0;
public double myLongitude = 0;
public double myCoarseLatitude = 0;
public double myCoarseLongitude = 0;

public boolean isGPS;
public boolean isGPSFix;
public boolean useGPSLocation;
public boolean useNetworkLocation;

public long mLastLocationMillis;//system time of last gps contact
/*boolean so when gps gets your location it will zoom to where you are, 
 * but will only do this once (once it's set to true)*/
boolean pickedUpLocation;

public MyCount counter;//for timing events


/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.mymapview);
    pickedUpLocation = false;



    mapView = (MapView) findViewById(R.id.mapview);
    mapView.setBuiltInZoomControls(true);
    mapView.setStreetView(true);
    /*mapcontroller controls zoom etc*/
    mapController = mapView.getController();

    mapOverlays = mapView.getOverlays();
    Drawable my_icon = this.getResources().getDrawable(R.drawable.androidmarker_teacher);
    myPosition = new HelloItemizedOverlay(my_icon, this);
    itemizedoverlay = new HelloItemizedOverlay(drawable, this);
    /*All overlay elements on a map are held by the MapView, so when you 
     * want to add some, you have to get a list from the getOverlays() method. 
     * Then instantiate the Drawable used for the map marker, which was saved in 
     * the res/drawable/ directory. The constructor for HelloItemizedOverlay 
     * (your custom ItemizedOverlay) takes the Drawable in order to set the 
     * default marker for all overlay items.*/

    /*Initialise GPS*/
    try{
    LocationManager mlocManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);

    LocationListener mlocListener = new MyLocationListener();
    //get fine location
    mlocManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
    //get coarse location
    mlocManager.requestLocationUpdates( LocationManager.NETWORK_PROVIDER, 0, 0, mlocListener);
    boolean isGPS = mlocManager.isProviderEnabled (LocationManager.GPS_PROVIDER);
    MyGPSListener myGPSListener = new MyGPSListener();
    mlocManager.addGpsStatusListener(myGPSListener);
    }
    catch(Error e)
    {
        Toast.makeText( getApplicationContext(),"Error!"+e.getMessage(),Toast.LENGTH_SHORT).show();
    }


    GeoPoint point = new GeoPoint((int)(myCoarseLatitude * 1e6),(int) (myCoarseLongitude* 1e6));
    myPositionOverlayItem = new OverlayItem(point, "Evening guvna!", "This is where i am");



    /*All that's left is to add this OverlayItem to your collection in the 
     * HelloItemizedOverlay instance, then add the HelloItemizedOverlay to the MapView: */
    myPosition.addOverlay(myPositionOverlayItem);
    mapOverlays.add(myPosition);
    /*begin counting 5 seconds to update positions*/
    counter = new MyCount(5000,1000);
    counter.start();
}

@Override
protected boolean isRouteDisplayed() {
    // TODO Auto-generated method stub
    return false;
}
public void updateMyPosition()
{
    /*remove my guy*/
    mapView.getOverlays().remove(myPosition);
    myPosition.removeOverlay(myPositionOverlayItem);
    myPosition.doPopulate();

    GeoPoint point;
    if(useGPSLocation)
    {
        point = new GeoPoint((int)(myLatitude * 1e6),(int) (myLongitude* 1e6));
    }
    else
    {
        point = new GeoPoint((int)(myCoarseLatitude * 1e6),(int) (myCoarseLongitude* 1e6));
    }


    myPositionOverlayItem = new OverlayItem(point, "You are here", "Awww yeah!");
    myPosition.addOverlay(myPositionOverlayItem);
    myPosition.doPopulate();
    mapOverlays.add(myPosition);
}

public void clearTheMap()
{
    mapView.getOverlays().clear();
    myPosition.doPopulate();
}


 /*******************************************************
 * GPS!!!!!!!!
 * This method gets the location of you from gps
 * ************************************************/
public class MyLocationListener implements LocationListener
{

    public void onLocationChanged(Location loc)
    {
        String provider = loc.getProvider();
        if(provider.equals(LocationManager.GPS_PROVIDER))
        {
            myLatitude = loc.getLatitude();
            myLongitude = loc.getLongitude();
            mLastLocationMillis = SystemClock.elapsedRealtime();
            if((!pickedUpLocation)&&(myLatitude!=0))
            {
                mapController.animateTo(new GeoPoint((int)(myLatitude * 1e6),(int) (myLongitude* 1e6)));
                pickedUpLocation = true;
            }
        }
        else
        {
            myCoarseLatitude = loc.getLatitude();
            myCoarseLongitude = loc.getLongitude();
            if((!pickedUpLocation)&&(myCoarseLatitude!=0))  
            {
                //Toast.makeText(getBaseContext(), "picked up Location with network - "+myCoarseLatitude+" "+myCoarseLongitude, Toast.LENGTH_LONG).show();
                mapController.animateTo(new GeoPoint((int)(myCoarseLatitude * 1e6),(int) (myCoarseLongitude* 1e6)));
                pickedUpLocation = true;
            }
        }

        /*first time it picks up your location it will animate to where you are*/


        /*
        String Text = "My current location is: "+
        "Latitud = " + loc.getLatitude()+
        "Longitud = " + loc.getLongitude();

        Toast.makeText( getApplicationContext(),Text,Toast.LENGTH_SHORT).show();
        */
    }

    public void onProviderDisabled(String provider)
    {
        Toast.makeText( getApplicationContext(),"Gps Disabled",Toast.LENGTH_SHORT ).show();
        myLatitude = -1;
        myLongitude = -1;
    }
    public void onProviderEnabled(String provider)
    {
        Toast.makeText( getApplicationContext(),"Gps Enabled",Toast.LENGTH_SHORT).show();
        myLatitude = 0;
        myLongitude = 0;
    }

    public void onStatusChanged(String provider, int status, Bundle extras)
    {

    }
}

/***********************************************
 * -GPS Status monitor-
 * Will see if the sattelites are still fixed to your phone
 * If satellites arent available, it takes network (coarse) location
 * If a fix is aquired it will use GPS (fine) location 
 * **********************************/
private class MyGPSListener implements GpsStatus.Listener {
    public void onGpsStatusChanged(int event) {
        switch (event) {
            case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
                if (myLatitude != 0)
                    isGPSFix = (SystemClock.elapsedRealtime() - mLastLocationMillis) < 3000;

                if (isGPSFix) { // A fix has been acquired.
                    useGPSLocation = true;
                    useNetworkLocation = false;
                } else { // The fix has been lost.
                    useGPSLocation = false;
                    useNetworkLocation = true;
                }

                break;
            case GpsStatus.GPS_EVENT_FIRST_FIX:
                // Do something.
                isGPSFix = true;
                useGPSLocation = true;
                    useNetworkLocation = false;
                break;
        }
    }
}

/*************************************************************
 * Counter class for timing events
 **********/
public class MyCount extends CountDownTimer{

    public MyCount(long millisInFuture, long countDownInterval) {
    super(millisInFuture, countDownInterval);
    }

    @Override
    public void onFinish() {
        clearTheMap();
        updateMyPosition();//redraw my guy
        myPosition.doPopulate();

        //Toast.makeText( getApplicationContext(),"Sent my position - used ",Toast.LENGTH_SHORT).show();
        resetTimer();
    }

    public void resetTimer()
    {
        counter = new MyCount(5000,1000);
        counter.start();
    }

    @Override
    public void onTick(long millisUntilFinished) {
    /*tv.setText(”Left: ” + millisUntilFinished/1000);*/

    }

    }
}

Answer

Reno picture Reno · May 16, 2011

Use mapview.invalidate(). This will eventually cause a redraw.