Forum Cross Platform with Xamarin

Announcement:

The Xamarin Forums have officially moved to the new Microsoft Q&A experience. Microsoft Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

To create new threads and ask questions head over to Microsoft Q&A for .NET and get involved today.

OSMSharp Offline Maps and Crossplatform use

Does anyone has experience with osmsharp for crossplatform use. I want to build an application which works on all three platzforms (iOS, Android and Windows Phone) with a map for offline use. Does anyone have a piece of sample code from where I might understand how to use this lib (also for windows phone)?
Many thanks for your help in advance.
Jérôme

Answers

  • jerome.tonnjerome.tonn USMember ✭✭

    Does anyone has an idea about that?

    Jérôme

  • stephenshaw.3366stephenshaw.3366 USMember ✭✭
    edited November 2015

    Hi Jerome

    I've used OSM sharp to offer offline maps for ios and android using xamarin.forms

    basically you'll need to create a custom control in your xamarin.forms project and fire a bindable object when you want to update the maps on the native device.

    this is my code for the custom control in xam forms

    public class MapContentView: View
    {
    public static readonly BindableProperty IndeterminateProperty =
    BindableProperty.Create<MapContentView,bool> (
    p => p.Changed, default(bool));

        public bool Changed {
            get { return (bool)GetValue (IndeterminateProperty); }
            set { 
                SetValue (IndeterminateProperty, value); 
                OnPropertyChanged ();
            }
        }
    
    }
    

    on the map page i create a new instance of MapContentView and set the Changed value when i want to update the map

    e.g. to add the map to the page

    public MapContentView map = new MapContentView(){HeightRequest=500};
    StackLayout MainStack = new StackLayout();
    MainStack.Children.Add (map);

    then to fire the bindable property

    map.Changed = !map.Changed;

    I then have a custom rendere on my respective platforms that check for this event and redraws the maps
    Here is the android example

    public class MapContentViewRenderer : ViewRenderer
    {
    public static MapView mv ;

        protected override void OnElementChanged(ElementChangedEventArgs<View> e)
        {
            mv = InitializeMap();
            base.OnElementChanged(e);
            if (e.OldElement != null || Element == null)
                return;
    
            RedrawMap(); 
    
            if (mv != null)
            {
                ViewGroup vg = mv;
                var par = ((ViewGroup)vg.Parent);
                if (par != null)
                    par.RemoveView(mv);
            }
    
            SetNativeControl(mv);
        }
    
        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
    
            base.OnElementPropertyChanged(sender, e);
            if (e.PropertyName == MapContentView.IndeterminateProperty.PropertyName)
            {
                if (LastUpdated < DateTime.Now.AddSeconds(-10))
                {
                   RedrawMap();
                    LastUpdated = DateTime.Now;
                }
            }
    
        }
    
        public void RedrawMap()
        { 
                List<MapMarker> mms = GenerateMarkers ();
                Device.BeginInvokeOnMainThread (() => { 
                mv.MapMaxZoomLevel = 11; // limit min/max zoom
                mv.MapMinZoomLevel = 6;
                mv.MapTilt = 0;
                mv.MapAllowTilt = false;
    
                if (mv.Markers.Count > 0)
                    mv.ClearMarkers ();
    
                if (App.SearchFocus != null) {
                    mv.MapCenter = App.SearchFocus;
                } else {
                    mv.MapCenter = new GeoCoordinate (51.5072, 0.1275);
                }
    
                foreach (MapMarker marker in mms) { 
                        mv.AddMarker (marker);
                }
                mv.MapZoom = 8;
                });
    
        }
    
        public List<MapMarker> GenerateMarkers()
        {
            List<MapMarker> mms = new List<MapMarker>();
    
            // add markers here
    
            return mms;
    }
    
        public MapView InitializeMap()
        {
    
            var map = new Map();
    
            // add MBTiles Layer.
            // any stream will do or any path on the device to a MBTiles SQLite databas
            // in this case the data is taken from the resource stream, written to disk and then opened.
            map.AddLayer(new LayerMBTile(SQLiteConnection.CreateFrom(
                        Assembly.GetExecutingAssembly().GetManifestResourceStream(@"YOUR MB TILES FILE HERE"), "map")));
    
    
    
            GeoCoordinate Center = new GeoCoordinate(51.5072, 0.1275);
    
    
    
            mv = new MapView(this.Context, new MapViewSurface(this.Context));
            //mv.MapBoundingBox = geo;
            mv.SetMeasureAllChildren(false);
            mv.Map = map;
            mv.MapMaxZoomLevel = 6; // limit min/max zoom because MBTiles sample only contains a small portion of a map.
            mv.MapMinZoomLevel = 10;
    
            mv.MapTilt = 0;
            mv.MapCenter = Center;
            mv.MapZoom = 6;
            mv.MapAllowTilt = false;
            SetNativeControl(mv);
            return mv;
        }
    }
    

    This is how i got it to work. I used the mbtiles sample from the OSMSharp github.
    OSMSharp has terrible documentation and they never do actual releases so you may want to use the latest beta prerelease because the last stable release has loads of bugs

  • jerome.tonnjerome.tonn USMember ✭✭

    Many thanks for your response... I am going to give it a try.

  • DirkWeltzDirkWeltz DEMember ✭✭✭

    Hey, thank you for sharing your code.

    One question: what's the difference between the iOS and the Android version? Only the SQL connection or more?

  • DirkWeltzDirkWeltz DEMember ✭✭✭

    @stephenshaw.3366
    Thank you very much for sharing your code. Helped me a lot to use OsmSharp with Xamarin.Forms. Is very easy :)

    Now I'm stuck with getting offline maps to work. Perhaps you have a good idea?

    I try to use a OSM/PBF file instead of a tile layer to create the map. I use this code

            // Get assembly
            var assembly = typeof(OsmMap).GetTypeInfo().Assembly;
            // Create the MapCSS image source.
            var imageSource = new MapCSSDictionaryImageSource();
            // Load mapcss style interpreter.
            var mapCSSInterpreter = new MapCSSInterpreter(assembly.GetManifestResourceStream("OsmSharp.Forms.MapCSS.Default.mapcss"), imageSource);
            // Initialize the data source.
            var stream = assembly.GetManifestResourceStream("OsmSharp.Forms.Maps.test.osm");
            // Create data source
            MemoryDataSource source = MemoryDataSource.CreateFromOsmStream(stream);
    
            if (layerMap != null)
                layerMap.Close();
    
            layerMap = map?.AddLayerOsm(source, mapCSSInterpreter);
    

    It starts without an error, but didn't display any map.

    Thank you for any help.

  • BryantAlfordBryantAlford USMember

    Can someone point me in the right direction for implementing the OSMSHarp lib using Xamarin Forms.

    Need some examples of implementing the ViewRenderer for android and iOS.

    Thanks.

  • DirkWeltzDirkWeltz DEMember ✭✭✭

    Perhaps this repository (https://github.com/charlenni/OsmSharp.Forms) could help you. I tried to create a replacement for Xamarin.Forms.Maps. Even offline mapping works, but the map files should be very small. I up to now didn't find the problem with bigger maps. Because it should replace Xamarin.Forms.Maps, you need this nuget package in the PCL (for objects like MapSpan and so on), but not in the platform code.

    I hope, it helps you.

  • JonAlzaJonAlza ESMember ✭✭✭

    @DirkWeltz said:
    Perhaps this repository (https://github.com/charlenni/OsmSharp.Forms) could help you. I tried to create a replacement for Xamarin.Forms.Maps. Even offline mapping works, but the map files should be very small. I up to now didn't find the problem with bigger maps. Because it should replace Xamarin.Forms.Maps, you need this nuget package in the PCL (for objects like MapSpan and so on), but not in the platform code.

    I hope, it helps you.

    Hello @DirkWeltz , I'm trying to run the sample, but I have problem to compile it. I don't not why in OsmSharp.Forms.Demo project are 5 errors saying Build action 'EmbeddedResource' is not supported by one or more of the project's targets. for Default.mapcss, Mapnik.mapcss, OsmOsnimki.mapcss, test.osm and test.osm.pbf files. Do you know the reason?

  • DirkWeltzDirkWeltz DEMember ✭✭✭

    @JonAlza: I assume, that there is something wrong with the declaration of this files.

    I didn't get the problem with offline maps, so I stopped the project.

  • Prajakta.ShindePrajakta.Shinde INUniversity ✭✭✭
    edited April 2017

    Can anyone give me brief description of how can I use OsmSharp for offline maps in Xamarin.Forms(ios,android,windows).
    https://github.com/charlenni/OsmSharp.Forms This is giving me so many namespace and .dll files missing errors. I tried to update the packages too. But no use. Please help.

  • DirkWeltzDirkWeltz DEMember ✭✭✭

    OsmSharp dropped the development of the UI. It uses now project for UI: [https://github.com/pauldendulk/Mapsui]. Mapsui could handle up to now online and offline raster map data. It works for Android, iOS and UWP with Skia as renderer.

    I'm trying again to create a wrapper for Xamarin.Forms ([https://github.com/charlenni/Mapsui.Forms]), so that it is easy to use. It isn't ready. At the end (I hope in the next weeks), it should be possible to get it from NuGet. But you could easily build your own.

  • Prajakta.ShindePrajakta.Shinde INUniversity ✭✭✭

    @DirkWeltz thank you for the reply. https://github.com/charlenni/Mapsui.Forms this project solution is confusing me. I am not getting it. Will you please explain in detail?

  • DirkWeltzDirkWeltz DEMember ✭✭✭

    What did you not get? You understand not the purpose of this project? You don't understand the code? You couldn't download the project? You couldn't compile the project?

  • crisstyriscrisstyris USMember

    Agree with Dirk, here its working perfect.

    Thanks.
    Cris
    Hire Ionic Developers

Sign In or Register to comment.