0

I am trying to implement the MyLocationOverlay class from google maps. However, when I try and use my own locationManager -- I cannot get the overlay to acutally draw on the map. I am wondering if I am doing something wrong.

I don't want to call the super method(enbaleMyLocation) of the MyLocationOverlay class because that request updates from the locationManager way too quickly and will eat my battery alive.

Here is my code:

private class CenterOverlay extends MyLocationOverlay {

    private Context mContext;
    private LocationManager mLocManager;

    public CenterOverlay(Context context, MapView mapView) {
        super(context, mapView);
        this.mContext = context;

    }

    @Override
    public void onLocationChanged(Location location) {
        super.onLocationChanged(location);
        try {
            doExternalCenterOverlayTask(location);
        } catch (JSONException e) {
            e.printStackTrace();
            ErrorHandler.serviceException(mContext);
        } catch (IOException e) {
            e.printStackTrace();
            ErrorHandler.IOException(mContext);
        } catch (ServiceException e) {
            e.printStackTrace();
            ErrorHandler.serviceException(mContext);
        }
    }

    @Override
    public boolean enableMyLocation() {
        mLocManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
        mLocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 50, this);
        mLocManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 5000, 25, this);

        return mLocManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
                || mLocManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
    }

    @Override
    public void disableMyLocation() {
        super.disableMyLocation();
        mLocManager.removeUpdates(this);
    }

    @Override
    public void onProviderDisabled(String provider) {
        super.onProviderDisabled(provider);
        ViewAdapter.createStandardAlertDialog(mContext,
                "Your location provider has been disabled, please re-enable it.");
    }

    @Override
    public void onProviderEnabled(String provider) {
        super.onProviderEnabled(provider);
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
        super.onStatusChanged(provider, status, extras);
        if (status == 0) {
            ViewAdapter.showLongToast(mContext, "Location is not available at this time");
        } else if (status == 1) {
            //Trying to connect
        } else if (status == 2) {
            // Available
        }

    }

}
hwrdprkns
  • 7,525
  • 12
  • 48
  • 69

2 Answers2

5

I have gotten to the bottom of this and it is not possible to do until Google feels like updating their code.

Instead, I've created my own class that draws the location for me -- that can be updated whenever you like.

Code for that is here.

/**
* 
* @author (hwrdprkns)
* 2010
*
*/
public class CenterOverlay extends ItemizedOverlay<OverlayItem> implements LocationListener {

private static final String TAG = "CenterOverlay: ";

private LocationManager mLocationManager;

private long updateTime = 60000;

private static final int updateDistance = 50;

private GeoPoint lastKnownPoint;

private Location lastKnownLocation;

private Drawable centerDrawable;

private Context mContext;

private final List<OverlayItem> mOverlays = new ArrayList<OverlayItem>();

private Paint accuracyPaint;

private Point center;

private Point left;

private Drawable drawable;

private int width;

private int height;

// San Francisco
private final static double[] DEFAULT_LOCATION = {
        37.7749295, -122.4194155
};

private Runnable firstFixRunnable = null;

private boolean firstFixRun = false;

public CenterOverlay(Drawable defaultMarker, MapView mapView, Context c) {
    super(boundCenter(defaultMarker));
    this.centerDrawable = defaultMarker;
    this.mContext = c;
    mLocationManager = (LocationManager) c.getSystemService(Context.LOCATION_SERVICE);

    if (Constants.DEBUG) {
        updateTime = 0;
    } else {
        updateTime = 60000;
    }
}

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

private void checkFirstRunnable() {
    if (!firstFixRun && lastKnownLocation != null && firstFixRunnable != null) {
        firstFixRunnable.run();
    }
}

private OverlayItem createCenterOverlay(GeoPoint point) {
    OverlayItem i = new OverlayItem(point, "Location", null);
    i.setMarker(centerDrawable);
    return i;
}

private GeoPoint createGeoPoint(Location loc) {
    int lat = (int) (loc.getLatitude() * 1E6);
    int lng = (int) (loc.getLongitude() * 1E6);
    return new GeoPoint(lat, lng);
}

@Override
protected OverlayItem createItem(int i) {
    return mOverlays.get(i);
}

public void disableLocation() {
    mLocationManager.removeUpdates(this);
}

@Override
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
    drawMyLocation(canvas, mapView, lastKnownLocation, lastKnownPoint, 0);
}

protected void drawMyLocation(Canvas canvas, MapView mapView, Location lastFix, GeoPoint myLoc,
        long when) {

    accuracyPaint = new Paint();
    accuracyPaint.setAntiAlias(true);
    accuracyPaint.setStrokeWidth(2.0f);

    drawable = centerDrawable;
    width = drawable.getIntrinsicWidth();
    height = drawable.getIntrinsicHeight();
    center = new Point();
    left = new Point();

    Projection projection = mapView.getProjection();

    double latitude = lastFix.getLatitude();
    double longitude = lastFix.getLongitude();
    float accuracy = lastFix.getAccuracy();

    float[] result = new float[1];

    Location.distanceBetween(latitude, longitude, latitude, longitude + 1, result);
    float longitudeLineDistance = result[0];

    GeoPoint leftGeo = new GeoPoint((int) (latitude * 1e6), (int) ((longitude - accuracy
            / longitudeLineDistance) * 1e6));
    projection.toPixels(leftGeo, left);
    projection.toPixels(myLoc, center);
    int radius = center.x - left.x;

    accuracyPaint.setColor(0xff6666ff);
    accuracyPaint.setStyle(Style.STROKE);
    canvas.drawCircle(center.x, center.y, radius, accuracyPaint);

    accuracyPaint.setColor(0x186666ff);
    accuracyPaint.setStyle(Style.FILL);
    canvas.drawCircle(center.x, center.y, radius, accuracyPaint);

    drawable.setBounds(center.x - width / 2, center.y - height / 2, center.x + width / 2,
            center.y + height / 2);
    drawable.draw(canvas);
}

public void enableMyLocation() {
    for (String s : mLocationManager.getProviders(true)) {
        mLocationManager.requestLocationUpdates(s, updateTime, updateDistance, this);
    }

    Location loc = null;

    for (String s : mLocationManager.getProviders(true)) {
        loc = mLocationManager.getLastKnownLocation(s);
        if (loc != null) {
            loc.setLatitude(DEFAULT_LOCATION[0]);
            loc.setLongitude(DEFAULT_LOCATION[1]);
            lastKnownLocation = loc;
            lastKnownPoint = createGeoPoint(loc);
            return;
        }
    }

    loc = new Location(LocationManager.GPS_PROVIDER);
    loc.setLatitude(DEFAULT_LOCATION[0]);
    loc.setLongitude(DEFAULT_LOCATION[1]);

    lastKnownLocation = loc;
    lastKnownPoint = createGeoPoint(loc);
}

public Location getLastKnownLocation() {
    return lastKnownLocation;
}

public GeoPoint getLastKnownPoint() {
    return lastKnownPoint;
}

public void onLocationChanged(Location location) {
    checkFirstRunnable();
    this.lastKnownLocation = location;
    this.lastKnownPoint = createGeoPoint(location);
    replaceOverlay(createCenterOverlay(lastKnownPoint));

}

public void onProviderDisabled(String provider) {
    ViewAdapter.showLongToast(mContext,
            "Your location provider has been disabled -- please reenable it");

}

public void onProviderEnabled(String provider) {

}

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

    if (status == LocationProvider.AVAILABLE) {

    }
    if (status == LocationProvider.OUT_OF_SERVICE) {
        ViewAdapter.showShortToast(mContext, "Location is temporarily out of service.");
    }
    if (status == LocationProvider.TEMPORARILY_UNAVAILABLE) {

    }
}

private void replaceOverlay(OverlayItem overlay) {
    mOverlays.clear();
    mOverlays.add(overlay);
    populate();
}

public boolean runOnFirstFix(Runnable runnable) {

    if (lastKnownLocation != null) {
        runnable.run();
        return true;
    }

    firstFixRunnable = runnable;
    return false;

}

@Override
public int size() {
    return mOverlays.size();
}

public void updateLocation() {

}

}

hwrdprkns
  • 7,525
  • 12
  • 48
  • 69
  • Thank you for the post, I cannot seem to get it to work though, it crashes around "GeoPoint leftGeo = new GeoPoint(". I've just created a new CenterOverlay object, called enableMyLocation() on the newly created object, then added the object to the overlays mapView.getOverlays().add(obj). Am I doing something wrong ? Thank you in advance ! – Dr1Ku Nov 24 '10 at 00:33
1

You're not adding the overlays to your mapView anywhere in your code. I.e. like mapView.getOverlays().add(centerOverlay);

That would usually happen outside the class you posted. Can you post the rest of the code of your activity that's relevant.

btw: The class (CenterOverlay) has a different name than your constructor (TaggstrCenterOverlay)... is that correct?

Mathias Conradt
  • 28,420
  • 21
  • 138
  • 192
  • It shouldn't matter -- I literally add the overlay just like you put in your code `mapView.getOverlays().add(centerOverlay)` I don't know why it doesn't show up when I don't call the super method. Is there some way I can examine the google maps for android code (although I think not). – hwrdprkns Aug 11 '10 at 21:13
  • which super method you mean, super(context, mapView);? The class above extends from MyLocationOverlay, which is a custom class as well,not the SDK one. And you don't have the draw-method anywhere in your above posted class. Can you please post the class the includes the draw method (MyLocationOverlay). – Mathias Conradt Aug 12 '10 at 01:04
  • `MyLocationOverlay`(http://bit.ly/dBIVdj) is not a custom class(at least in the way I think your speaking). Its from the GoogleMaps SDK. – hwrdprkns Aug 13 '10 at 01:31
  • oh yes, you're right. Never used that one, I use a class extended only from Overlay for the current location display. nevermind then. – Mathias Conradt Aug 13 '10 at 02:18
  • Regardless -- I need someway to display a dot at a centerPoint -- (preferably with MyLocationOverlay) and then request that that dot be updated as often as I want it to. I think I might have to use a different parent class. – hwrdprkns Aug 17 '10 at 16:26