Search code examples
androidandroid-mapsopenstreetmaposmdroid

Adding Overlay to OSMDROID


I have been struggling with this long time. I am trying to add Overlay on my map. I am using the open source OSMdroid. but all I get by the example is a straight red line from one corner to another. My target is to add some icon where my geoPoint is set.

here is my code:

 package osmdemo.demo;

import java.util.List;

import microsoft.mappoint.TileSystem;

import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.MapController;
import org.osmdroid.views.MapView;
import org.osmdroid.views.MapView.Projection;
import org.osmdroid.views.overlay.Overlay;
import org.osmdroid.views.overlay.ScaleBarOverlay;
import org.osmdroid.views.util.constants.MapViewConstants;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.location.LocationManager;
import android.os.Bundle;

public class map extends Activity implements MapViewConstants
{

    /** Called when the activity is first created. */

    protected static final String PROVIDER_NAME = LocationManager.GPS_PROVIDER;
    MapController mapController;
    MapView mapView;
    ScaleBarOverlay mScaleBarOverlay;
    private MapOverlay mmapOverlay = null;
    private LocationManager mLocMgr;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mapView = (MapView) findViewById(R.id.mapview);

        mapView.setTileSource(TileSourceFactory.MAPNIK);
        mapView.setBuiltInZoomControls(true);
        mapView.setMultiTouchControls(true);

        mapController = mapView.getController();
        mapController.setZoom(20);
        GeoPoint point2 = new GeoPoint(31.987968, 34.783069);
        mapController.setCenter(point2);

        this.mmapOverlay = new MapOverlay(this);

        List<Overlay> listOfOverlays = mapView.getOverlays();
        listOfOverlays.add(mmapOverlay);
        mapView.invalidate();
    }

    public class MapOverlay extends org.osmdroid.views.overlay.Overlay
    {

        public MapOverlay(Context ctx)
        {
            super(ctx);
            // TODO Auto-generated constructor stub
        }

        @Override
        protected void draw(Canvas pC, MapView pOsmv, boolean shadow)
        {
            if (shadow)
                return;

            Paint lp3;
            lp3 = new Paint();
            lp3.setColor(Color.RED);
            lp3.setAntiAlias(true);
            lp3.setStyle(Style.STROKE);
            lp3.setStrokeWidth(1);
            lp3.setTextAlign(Paint.Align.LEFT);
            lp3.setTextSize(12);
            // Calculate the half-world size
            final Rect viewportRect = new Rect();
            final Projection projection = pOsmv.getProjection();
            final int zoomLevel = projection.getZoomLevel();
            int mWorldSize_2 = TileSystem.MapSize(zoomLevel) / 2;

            // Save the Mercator coordinates of what is on the screen
            viewportRect.set(projection.getScreenRect());
            // DON'T set offset with either of below
            // viewportRect.offset(-mWorldSize_2, -mWorldSize_2);
            // viewportRect.offset(mWorldSize_2, mWorldSize_2);

            // Draw a line from one corner to the other
            pC.drawLine(viewportRect.left, viewportRect.top,
                    viewportRect.right, viewportRect.bottom, lp3);
        }

        public void onProviderDisabled(String arg0)
        {
        }

        public void onProviderEnabled(String provider)
        {
        }

    }

}

thats my Manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.test.overlay" android:versionCode="1" android:versionName="1.0">
    <uses-sdk android:minSdkVersion="3" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />


    <application >
        <activity android:name=".OverlayDemo" android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>
</manifest>

Thanks in advance,

ray.


Solution

  • The jars versions 3.0.3 and 3.0.4 seem to have changed a bit since the sample code was written.

    If you are basing your app on the code as quoted in the previous answer, then change the line

    mResourceProxy = new ResourceProxyImpl(getApplicationContext());
    

    to

    mResourceProxy = new DefaultResourceProxyImpl(getApplicationContext());
    

    This should at least get you going with a default icon.

    EDIT

    This should centre the map just NE of Liverpool and put an icon just off centre.

    package osmdemo.demo;
    
    import java.util.ArrayList;
    import org.osmdroid.DefaultResourceProxyImpl;
    import org.osmdroid.ResourceProxy;
    import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
    import org.osmdroid.util.GeoPoint;
    import org.osmdroid.views.MapController;
    import org.osmdroid.views.MapView;
    import org.osmdroid.views.overlay.ItemizedIconOverlay;
    import org.osmdroid.views.overlay.ItemizedOverlay;
    import org.osmdroid.views.overlay.OverlayItem;
    import org.osmdroid.views.util.constants.MapViewConstants;
    
    import android.app.Activity;
    import android.location.Location;
    import android.location.LocationListener;
    import android.location.LocationManager;
    import android.os.Bundle;
    import android.widget.Toast;
    
    public class DemoMap extends Activity implements LocationListener,
            MapViewConstants {
    
        private MapView mMapView;
        private MapController mapController;
        private LocationManager mLocMgr;
        private ItemizedOverlay<OverlayItem> mMyLocationOverlay;
        private ResourceProxy mResourceProxy;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            mResourceProxy = new DefaultResourceProxyImpl(getApplicationContext());
            setContentView(R.layout.copymain);
    
            mMapView = (MapView) this.findViewById(R.id.mapview);
            mMapView.setTileSource(TileSourceFactory.MAPNIK);
            mMapView.setBuiltInZoomControls(true);
            mMapView.setMultiTouchControls(true);
            mapController = this.mMapView.getController();
            mapController.setZoom(15);
            GeoPoint point2 = new GeoPoint(53554070, -2959520); // centre map here
            GeoPoint point3 = new GeoPoint(53554070 + 1000, -2959520 + 1000); // icon goes here
            mapController.setCenter(point2);
            mLocMgr = (LocationManager) getSystemService(LOCATION_SERVICE);
            mLocMgr.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 100,
                    this);
    
            ArrayList<OverlayItem> items = new ArrayList<OverlayItem>();
            // Put overlay icon a little way from map centre
            items.add(new OverlayItem("Here", "SampleDescription", point3));
    
            /* OnTapListener for the Markers, shows a simple Toast. */
            this.mMyLocationOverlay = new ItemizedIconOverlay<OverlayItem>(items,
                    new ItemizedIconOverlay.OnItemGestureListener<OverlayItem>() {
                        @Override
                        public boolean onItemSingleTapUp(final int index,
                                final OverlayItem item) {
                            Toast.makeText(
                                    DemoMap.this,
                                    "Item '" + item.mTitle, Toast.LENGTH_LONG).show();
                            return true; // We 'handled' this event.
                        }
                        @Override
                        public boolean onItemLongPress(final int index,
                                final OverlayItem item) {
                            Toast.makeText(
                                    DemoMap.this, 
                                    "Item '" + item.mTitle ,Toast.LENGTH_LONG).show();
                            return false;
                        }
                    }, mResourceProxy);
            this.mMapView.getOverlays().add(this.mMyLocationOverlay);
            mMapView.invalidate();
        }
    
        public void onLocationChanged(Location location) {
            int lat = (int) (location.getLatitude() * 1E6);
            int lng = (int) (location.getLongitude() * 1E6);
            GeoPoint gpt = new GeoPoint(lat, lng);
            mapController.setCenter(gpt);
            mMapView.invalidate();
        }
    
        @Override
        public void onProviderDisabled(String arg0) {}
        @Override
        public void onProviderEnabled(String provider) {}
        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {}
    
    }
    

    It's a bit rough and ready, but at least it runs OK with just the 3.0.4 jar and the slf4j one. Hope it helps.

    EDIT 2

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="osmdemo.demo"
          android:versionCode="1"
          android:versionName="1.0">
        <application android:icon="@drawable/icon" android:label="@string/app_name">
            <activity android:name="DemoMap"
                      android:label="@string/app_name">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
    
        </application>
        <uses-sdk android:minSdkVersion="3" />
    
        <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
        <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> 
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    
    </manifest> 
    

    .