11

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.

zyamys
  • 1,609
  • 1
  • 21
  • 23
rayman
  • 20,786
  • 45
  • 148
  • 246

3 Answers3

17

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> 

.

NickT
  • 23,844
  • 11
  • 78
  • 121
  • Yes, I have changed it to DefaultResousrseProxyImpl but I still get this error: 06-30 15:48:55.153: ERROR/AndroidRuntime(11997): FATAL EXCEPTION: main 06-30 15:48:55.153: ERROR/AndroidRuntime(11997): java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.test.overlay/com.test.overlay.OverlayDemo}: java.lang.ClassNotFoundException: com.test.overlay.OverlayDemo in loader dalvik.system.PathClassLoader[/data/app/com.test.overlay-2.apk] ... – rayman Jun 30 '11 at 12:49
  • Maybe I need to add more Jars to the build path? Currently I use these ones: APACHEMIME ver:47.0.4, HTTPMIME ver:4.0 beta1, osmdroid3.0.4.jar slf4j ver:1.5.8 – rayman Jun 30 '11 at 13:02
  • No, I've just got the sl4j and the osmdroid versions that you have. I'll see if I can cut down my code to the bare minimum to show an overlay and post it into my answer. – NickT Jun 30 '11 at 13:17
  • Thank you for that, I am struggling days with this! – rayman Jun 30 '11 at 13:18
  • Still same error with the ClassNotFoundException. What am I missing here? – rayman Jun 30 '11 at 13:53
  • Maybe it's your manifest.xml? The package names need to match. – NickT Jun 30 '11 at 14:04
  • You were right. thanks:) sometimes u dont pay attention to the old details – rayman Jun 30 '11 at 14:15
  • I'm not sure what bits you've renamed but I've got the one class - DemoMap and it's in the package 'osmdemo.demo'. I'll add my manifest to the answer in a minute. I haven't got the . before the activity name though. the dot means something though, I just can't remember what! – NickT Jun 30 '11 at 14:22
  • it works.. but question.. when I tried to change to another longtitude,latitude I didnt see the item. those are the lines I changed in your code: GeoPoint point2 = new GeoPoint(32.056516, 34.782367); GeoPoint point3 = new GeoPoint(32.056516 + 1000, 34.782367 + 1000); – rayman Jun 30 '11 at 14:24
  • Pass the params as ints (in microdegrees) not doubles for this offset to work, e.g. 32056516, 34782367 – NickT Jun 30 '11 at 14:40
  • Please one more thing. When there is a change in the location the map does change but the Icon is gone. how do i validate the Icon into the new change? – rayman Jul 01 '11 at 07:12
  • since these libraries have been suplanted, from osmdroid 4.2 onwards, you must alter `mTitle` for `getTitle()`and `MapController` becomes `IMapController` (from 4.3 onwards, `GeoPoint` becomes `IGeoPoint` also) – tony gil Apr 20 '16 at 14:40
0

@rayman

Please one more thing. When there is a change in the location the map does change but the Icon is gone. how do i validate the Icon into the new change? – rayman Jul 1 '11 at 7:12

this is where your location changes

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();
}

But as you can see it does not add new icon to the overlay.

You should clear the previous items

items.clear()

(if you want the "old" icon to be removed when the new one is created) and then add the new point (gpt) to the items.

items.add(new OverlayItem("Title", "Description", gpt));

and so on...

bubbly
  • 495
  • 1
  • 10
  • 22
0

If you are trying to add an icon, then you want to look at the ItemizedOverlay classes. You can use osmdroid's ItemizedIconOverlay which is a concrete implementation of ItemizedOverlay, or you can subclass ItemizedOverlay on your own. Take a look at the samples, such as:

http://code.google.com/p/osmdroid/source/browse/trunk/OpenStreetMapViewer/src/org/osmdroid/samples/SampleWithMinimapItemizedoverlay.java

kurtzmarc
  • 3,110
  • 1
  • 24
  • 40
  • I found that example: http://code.google.com/p/osmdroid/source/browse/trunk/osmdroid-android/src/org/osmdroid/views/overlay/ItemizedIconOverlay.java?r=887. but I couldn't understand how do I integrate it in my code? how my map will use it inside of it? – rayman Jun 29 '11 at 06:33
  • I added a sample to my answer that should help. – kurtzmarc Jun 29 '11 at 23:51
  • It requires the class ResourceProxyImpl. So I took it from: http://www.google.com/codesearch#OOgMjZrCM0A/trunk/OpenStreetMapViewer/src/org/osmdroid/ResourceProxyImpl.java&q=ResourceProxyImpl%20package:http://osmdroid%5C.googlecode%5C.com. but I get this error on runtime: unable to instantiate activity ComponentInfo{com.test.overlay/com.test.overlay.OverlayDemo}: java.lang.ClassNotFoundException: com.test.overlay.OverlayDemo in loader dalvik.system.PathClassLoader[/data/app/com.test.overlay-1.apk] any idea? thanks. – rayman Jun 30 '11 at 07:34