Question

I have an extremely weird issue.

First of all, when I zoom in and out of a MapView, the marker (overlay) moves to incorrect places (doesn't work well with scaling).

Secondly, the market is being drawn at the wrong position!

I'll post code below but first listen to this:

I'm in Islamabad. The GeoCoder also tells me I'm in Islamabad. But when I draw a circle around my location using overlays, it draws it in a city that's 100s of kilometers away.

Kindly help me with both the problems.

Here's the activity:

public class LocatePickup extends MapActivity implements LocationListener {
    Geocoder gc;

    MapView mapView;
    MapController mc;
    GeoPoint p;

    double lat = 0;
    double lng = 0;

    LocationManager lm;

    WebMethods wm;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.locate_pickup);

        mapView = (MapView) findViewById(R.id.mapView);
        mapView.setBuiltInZoomControls(true);
        mapView.setStreetView(true);

        lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000L, 500.0f, this);

        Location l = new Location(LocationManager.NETWORK_PROVIDER);
        l = lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

        mc = mapView.getController();
        p = new GeoPoint((int) (l.getLatitude()), (int) (l.getLongitude()));
        mc.setCenter(p);
        mc.setZoom(14);

        MapOverlay myLocationOverlay = new MapOverlay();
        List<Overlay> list = mapView.getOverlays();
        list.add(myLocationOverlay);

        gc = new Geocoder(this);
        try {
            List<Address> address = gc.getFromLocation(l.getLatitude(), l.getLongitude(), 1);
            Toast.makeText(this, ""+address.get(0).getAddressLine(1), 1).show();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected boolean isRouteDisplayed() {
        return false;
    }

    class MapOverlay extends com.google.android.maps.Overlay {
        Paint paint = new Paint();
        @Override
        public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when) {
            super.draw(canvas, mapView, shadow);

            Point myScreenCoords = new Point();
            mapView.getProjection().toPixels(p, myScreenCoords);

            paint.setStrokeWidth(1);
            paint.setARGB(255, 218, 28, 28);
            paint.setStyle(Paint.Style.STROKE);

            //Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.pin);

            canvas.drawCircle(myScreenCoords.x, myScreenCoords.y, 15, paint);
            //(bmp, myScreenCoords.x, myScreenCoords.y - 256, paint);
            canvas.drawText("Hey!", myScreenCoords.x, myScreenCoords.y, paint);
            return true;
        }
    }

    @Override
    public void onLocationChanged(Location arg0) {
        if(arg0 != null) {
            Log.d("New Location: ", arg0.getLatitude() + " - " + arg0.getLongitude());
            lat = arg0.getLatitude();
            lng = arg0.getLongitude();

            p = new GeoPoint((int) lat * 1000000, (int) lng * 1000000);
            mc.animateTo(p);
        }
    }

    @Override
    public void onProviderDisabled(String provider) {
        // empty
    }

    @Override
    public void onProviderEnabled(String provider) {
        // empty
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
        //empty
    }
}

Once the code is complete, I'd like the user to be able to tap a spot on the map and get its address (the marker should move to that spot as well). But it should be accurate.

Was it helpful?

Solution 2

Since no one answered this question correctly..

For some reason, the normal Overlay class wasn't working for me the way it should have. I switched to ItemizedOverlay and now everything is perfect.

I'm no Android expert so I'd like someone with better experience to comment on this but, I feel that ItemizedOverlay is much better than the simple Overlay. With itemizedoverlay, zooming in and out of the mapview with an object drawn at a fixed point works the way it should, the pin (object) stays exactly where it should stay (that wasn't the case previously).

Here's some code for those who are looking for it. This is of course incomplete, and for a specific purpose, but you get the general idea.

`class CustomOverlay extends com.google.android.maps.ItemizedOverlay { private ArrayList mOverlays = new ArrayList(); Context mContext;

    public CustomOverlay(Drawable defaultMarker)
    {
        super(defaultMarker);

    }

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

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

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

    public CustomOverlay(Drawable defaultMarker, Context context)
    {
        super(boundCenterBottom(defaultMarker));
        mContext = context;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event, MapView mapView)
    {
        if (event.getAction() == 1)
        {
            p = mapView.getProjection().fromPixels((int) event.getX(),
                    (int) event.getY());

            gc = new Geocoder(getBaseContext(), Locale.getDefault());
            try
            {
                address = gc.getFromLocation(
                        (double) p.getLatitudeE6() / 1E6,
                        (double) p.getLongitudeE6() / 1E6, 1);

                addressfound = true;
            }
            catch (IOException e)
            {
                addressfound = false;
                e.printStackTrace();
            }

            if (address.size() != 0)
            {
                l1 = address.get(0).getAddressLine(0);
                l2 = address.get(0).getAddressLine(1);
                l3 = address.get(0).getAddressLine(2);
            }

            OverlayItem point = new OverlayItem(p, "Location", l1 + ", "
                    + l2 + ", " + l3);
            List<Overlay> mapOverlays = mapView.getOverlays();
            Drawable drawable = getBaseContext().getResources()
                    .getDrawable(R.drawable.androidmarker);
            CustomOverlay itemizedoverlay = new CustomOverlay(drawable,
                    getBaseContext());

            itemizedoverlay.addOverlay(point);
            mapOverlays.clear();
            mapOverlays.add(itemizedoverlay);

            mapView.invalidate();
        }`

OTHER TIPS

To animate the map towards the given geopoint, use animateTo() method,

So implement a zoomListener in your method, and add the line,

mapController.animateTo(geoPoint);

also, try mapview.invalidate()

And btw, if you don't know to implement zoom listener, refer How to implemennt OnZoomListener on MapView.

for the second question, you have used only NETWORK_PROVIDER which is less accurate than using GPS to get location values. So try using GPS_PROVIDER.An efficient and correct implemention could get you more accurate values.

And to get latitude and longitude of the spot touched on the map, in the mapOverlay class implement a onTouchEvent

 @Override
    public boolean onTouchEvent(MotionEvent event, MapView mapView) 
    {   
        //---when user lifts his finger---
        if (event.getAction() == 1) {                
            GeoPoint p = mapView.getProjection().fromPixels(
                (int) event.getX(),
                (int) event.getY());
                Toast.makeText(getBaseContext(), 
                    p.getLatitudeE6() / 1E6 + "," + 
                    p.getLongitudeE6() /1E6 , 
                    Toast.LENGTH_SHORT).show();
        }                            
        return false;
    } 

you can get the address from latitude and longitude by using GeoCoder

Geocoder geoCoder = new Geocoder(
                getBaseContext(), Locale.getDefault());
try {
    List<Address> addresses = geoCoder.getFromLocation(latitude/1E6, 
                    longitude / 1E6, 1);
                String add = "";
                if (addresses.size() > 0) 
                {
                    for (int i=0; i<addresses.get(0).getMaxAddressLineIndex(); 
                         i++)
                       add += addresses.get(0).getAddressLine(i) + "\n";
                }

                Toast.makeText(getBaseContext(), add, Toast.LENGTH_SHORT).show();
  }catch (IOException e) {                
                e.printStackTrace();
   }

If you want to add marker to that point, add overlayItem for that point and add it to the overlay.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top