Adding Overlay to OSMDROID
Asked Answered
H

3

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.

Hypnotist answered 27/6, 2011 at 17:7 Comment(2)
Can you be more specific about what you are trying to do? Are you trying to add an icon at a geopoint? Are you trying to do custom drawing?Thenna
I am trying to add an icon at the geopoint exactly! !Hypnotist
M
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> 

.

Mciver answered 30/6, 2011 at 12:39 Comment(12)
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] ...Hypnotist
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.8Hypnotist
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.Mciver
Thank you for that, I am struggling days with this!Hypnotist
Still same error with the ClassNotFoundException. What am I missing here?Hypnotist
Maybe it's your manifest.xml? The package names need to match.Mciver
You were right. thanks:) sometimes u dont pay attention to the old detailsHypnotist
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!Mciver
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);Hypnotist
Pass the params as ints (in microdegrees) not doubles for this offset to work, e.g. 32056516, 34782367Mciver
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?Hypnotist
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)Undercarriage
T
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

Thenna answered 28/6, 2011 at 19:40 Comment(3)
I found that example: code.google.com/p/osmdroid/source/browse/trunk/osmdroid-android/…. but I couldn't understand how do I integrate it in my code? how my map will use it inside of it?Hypnotist
I added a sample to my answer that should help.Thenna
It requires the class ResourceProxyImpl. So I took it from: google.com/codesearch#OOgMjZrCM0A/trunk/OpenStreetMapViewer/src/…. 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.Hypnotist
O
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...

Outspread answered 10/5, 2012 at 11:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.