This is a migrated thread and some comments may be shown as answers.

Support for Google maps

3 Answers 713 Views
Map
This is a migrated thread and some comments may be shown as answers.
Peter
Top achievements
Rank 1
Veteran
Peter asked on 14 Jun 2017, 01:13 PM

One of our customers wants to be able to show Google maps in our application. I understand that they have purchased a licence to allow them to use the Goggle API. Has anyone tried to usethis with the RadMap control? Is it legal? Are Telerik planning any support for this?

Thanks

Pete

3 Answers, 1 is accepted

Sort by
0
Dinko | Tech Support Engineer
Telerik team
answered on 19 Jun 2017, 09:50 AM
Hello Peter,

Thank you for contacting us.

RadMap does not have a Google Maps provider and currently such cannot be implemented because of the additional protection which Google implemented in their service. Using the Google Maps tile server in a WPF application is not allowed. Currently, we do not plan to implement support for Google map API.

In your case, you mentioned that the customer has a license for using Google API. In this case, you can try creating a custom Google provider. You can take a look at the Implement custom map provider help article in our documentation.Technically a custom Google Maps provider for RadMap can be designed like the sample code below.
using System;
using System.Collections.Generic;
using System.Windows;
using Telerik.Windows.Controls.Map;
  
namespace GoogleMaps
{
    public class GoogleCustomProvider : TiledProvider, ICloneable
    {
        /// <summary>
        /// Identifies the <see cref="Mode"/> Mode dependency property.
        /// </summary>
        public static readonly DependencyProperty ModeProperty = DependencyProperty.Register(
            "Mode",
            typeof(GoogleCustomMapMode),
            typeof(GoogleCustomProvider),
            new PropertyMetadata(ModeChanged));
  
        private ISpatialReference projection = new MercatorProjection();
        private Dictionary<GoogleCustomMapMode, string> mapModeSource = new Dictionary<GoogleCustomMapMode, string>();
  
        /// <summary>
        /// Initializes a new instance of the GoogleCustomProvider class.
        /// </summary>
        public GoogleCustomProvider()
            : base()
        {
            TiledMapSource source = new GoogleStreetCustomSource();
            this.MapSources.Add(source.UniqueId, source);
            this.mapModeSource[GoogleCustomMapMode.Street] = source.UniqueId;
  
            source = new GoogleSatelliteCustomSource();
            this.MapSources.Add(source.UniqueId, source);
            this.mapModeSource[GoogleCustomMapMode.Satellite] = source.UniqueId;
  
            source = new GoogleSatelliteHybridCustomSource();
            this.MapSources.Add(source.UniqueId, source);
            this.mapModeSource[GoogleCustomMapMode.SatelliteHybrid] = source.UniqueId;
  
            source = new GooglePhysicalCustomSource();
            this.MapSources.Add(source.UniqueId, source);
            this.mapModeSource[GoogleCustomMapMode.Physical] = source.UniqueId;
  
            source = new GooglePhysicalHybridCustomSource();
            this.MapSources.Add(source.UniqueId, source);
            this.mapModeSource[GoogleCustomMapMode.PhysicalHybrid] = source.UniqueId;
  
            this.SetupCommands();
        }
  
        /// <summary>
        /// Gets or sets map mode.
        /// </summary>
        public GoogleCustomMapMode Mode
        {
            get
            {
                return (GoogleCustomMapMode)this.GetValue(ModeProperty);
            }
            set
            {
                this.SetValue(ModeProperty, value);
            }
        }
  
        /// <summary>
        /// Returns the SpatialReference for the map provider.
        /// </summary>
        public override ISpatialReference SpatialReference
        {
            get
            {
                return this.projection;
            }
        }
  
        public new object Clone()
        {
            GoogleCustomProvider clone = new GoogleCustomProvider();
            this.InheritCurrentSource(clone);
            this.InheritParameters(clone);
  
            return clone;
        }
  
        private static void ModeChanged(DependencyObject source, DependencyPropertyChangedEventArgs eventArgs)
        {
            GoogleCustomProvider provider = source as GoogleCustomProvider;
            if (provider != null)
            {
                provider.OnMapModeChanged((GoogleCustomMapMode)eventArgs.OldValue, (GoogleCustomMapMode)eventArgs.NewValue);
            }
        }
  
        /// <summary>
        /// MapModeChanged handler.
        /// </summary>
        /// <param name="newMode">New map mode.</param>
        /// <param name="oldMode">Old map mode.</param>
        private void OnMapModeChanged(GoogleCustomMapMode oldMode, GoogleCustomMapMode newMode)
        {
            this.SetMapSource(this.mapModeSource[newMode]);
        }
  
        private void SetupCommands()
        {
            this.CommandBindingCollection.Clear();
  
            this.RegisterSetSourceCommand(
                typeof(GoogleStreetCustomSource),
                "Street",
                null,
                new Uri("/Telerik.Windows.Controls.DataVisualization;component/themes/road.png", UriKind.Relative),
                null,
                null);
  
            this.RegisterSetSourceCommand(
                typeof(GoogleSatelliteCustomSource),
                "Satellite",
                null,
                new Uri("/Telerik.Windows.Controls.DataVisualization;component/themes/aerial.png", UriKind.Relative),
                null,
                null);
  
  
            this.RegisterSetSourceCommand(
                typeof(GoogleSatelliteHybridCustomSource),
                "Satellite Hybrid",
                null,
                new Uri("/Telerik.Windows.Controls.DataVisualization;component/themes/aerial.png", UriKind.Relative),
                null,
                null);
  
            this.RegisterSetSourceCommand(
                typeof(GooglePhysicalCustomSource),
                "Physical",
                null,
                new Uri("/Telerik.Windows.Controls.DataVisualization;component/themes/aerial.png", UriKind.Relative),
                null,
                null);
  
            this.RegisterSetSourceCommand(
                typeof(GooglePhysicalHybridCustomSource),
                "Physical Hybrid",
                null,
                new Uri("/Telerik.Windows.Controls.DataVisualization;component/themes/aerial.png", UriKind.Relative),
                null,
                null);
        }
    }
  
    public class GoogleStreetCustomSource : GoogleCustomSourceBase
    {
        /// <summary>
        /// Initializes a new instance of the GoogleWorldImagerySource class.
        /// </summary>
        public GoogleStreetCustomSource()
            : base("m")
        {
        }
    }
  
    public class GoogleSatelliteCustomSource : GoogleCustomSourceBase
    {
        /// <summary>
        /// Initializes a new instance of the GoogleWorldImagerySource class.
        /// </summary>
        public GoogleSatelliteCustomSource()
            : base("s")
        {
        }
    }
  
    public class GoogleSatelliteHybridCustomSource : GoogleCustomSourceBase
    {
        /// <summary>
        /// Initializes a new instance of the GoogleWorldImagerySource class.
        /// </summary>
        public GoogleSatelliteHybridCustomSource()
            : base("y")
        {
        }
    }
  
    public class GooglePhysicalCustomSource : GoogleCustomSourceBase
    {
        /// <summary>
        /// Initializes a new instance of the GoogleWorldImagerySource class.
        /// </summary>
        public GooglePhysicalCustomSource()
            : base("t")
        {
        }
    }
  
    public class GooglePhysicalHybridCustomSource : GoogleCustomSourceBase
    {
        /// <summary>
        /// Initializes a new instance of the GoogleWorldImagerySource class.
        /// </summary>
        public GooglePhysicalHybridCustomSource()
            : base("p")
        {
        }
    }
  
    public class GoogleCustomSourceBase : TiledMapSource
    {
        private const string UrlFormat = @"http://mt{0}.google.com/vt/lyrs={1}&z={2}&x={3}&y={4}";
  
        private int server = 0;
        private string mapLayers;
  
        /// <summary>
        /// Initializes a new instance of the GoogleWorldMapSourceBase class.
        /// </summary>
        public GoogleCustomSourceBase(string mapLayers)
            : base(0, 19, 256, 256)
        {
            this.mapLayers = mapLayers;
        }
  
        /// <summary>
        /// Initialize provider.
        /// </summary>
        public override void Initialize()
        {
            // Raise provider initialized event.
            this.RaiseInitializeCompleted();
        }
  
        /// <summary>
        /// Gets the image URI.
        /// </summary>
        /// <param name="tileLevel">Tile level.</param>
        /// <param name="tilePositionX">Tile X.</param>
        /// <param name="tilePositionY">Tile Y.</param>
        /// <returns>URI of image.</returns>
        protected override Uri GetTile(int tileLevel, int tilePositionX, int tilePositionY)
        {
            int zoomLevel = ConvertTileToZoomLevel(tileLevel);
  
            string url = string.Empty;
            string prefix = string.Empty;
  
            this.server = (this.server + 1) % 4;
  
            url = string.Format(UrlFormat, server, this.mapLayers, zoomLevel, tilePositionX, tilePositionY);
            url = ProtocolHelper.SetScheme(url);
  
            return new Uri(url);
        }
    }
  
    /// <summary>
    /// Represents map modes.
    /// </summary>
    public enum GoogleCustomMapMode
    {
        Street,
        Satellite,
        SatelliteHybrid,
        Physical,
        PhysicalHybrid
    }
}
<telerik:RadMap x:Name="radMap">
    <telerik:RadMap.Provider>
        <local:GoogleCustomProvider Mode="SatelliteHybrid" />
    </telerik:RadMap.Provider>
</telerik:RadMap>

Regards,
Dinko
Progress Telerik
Want to extend the target reach of your WPF applications, leveraging iOS, Android, and UWP? Try UI for Xamarin, a suite of polished and feature-rich components for the Xamarin framework, which allow you to write beautiful native mobile apps using a single shared C# codebase.
0
Joe Bohen
Top achievements
Rank 1
answered on 22 Dec 2017, 10:57 AM

Hi Dinko,

I have attempted to copy your code in a project there are no errors and the project builds but I get an error:

System.Windows.Markup.XamlParseException occurred
  HResult=-2146233087
  LineNumber=11
  LinePosition=10
  Message='The invocation of the constructor on type 'Telerik.Windows.Controls.RadMap' that matches the specified binding constraints threw an exception.' Line number '11' and line position '10'.
  Source=PresentationFramework
  StackTrace:
       at System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri)
       at System.Windows.Markup.WpfXamlLoader.LoadBaml(XamlReader xamlReader, Boolean skipJournaledProperties, Object rootObject, XamlAccessLevel accessLevel, Uri baseUri)
       at System.Windows.Markup.XamlReader.LoadBaml(Stream stream, ParserContext parserContext, Object parent, Boolean closeStream)
       at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
       at GoogleMaps.Page1.InitializeComponent()
  InnerException: 
       HResult=-2146233036
       Message=The type initializer for 'Telerik.Windows.Controls.TelerikLicense' threw an exception.
       Source=Telerik.Windows.Controls
       TypeName=Telerik.Windows.Controls.TelerikLicense
       StackTrace:
            at Telerik.Windows.Controls.TelerikLicense.Verify(FrameworkElement targetControl)
            at Telerik.Windows.Controls.RadMap..ctor()
       InnerException: 
            HResult=-2146233078
            Message=Request failed.
            Source=Telerik.Windows.Controls
            StackTrace:
                 at Telerik.Windows.Controls.TelerikLicense.IsSdkSamplesBrowser()
                 at Telerik.Windows.Controls.TelerikLicense..cctor()
            InnerException: 

Jose
Top achievements
Rank 1
commented on 19 Nov 2021, 03:59 PM

Hi Joe,

Were you able to make this work?

0
Martin Ivanov
Telerik team
answered on 26 Dec 2017, 12:53 PM
Hello Joe,

I used Dinko's code to create a sample project but I couldn't reproduce the error. Can you please take a look at it and let me know if I am missing something?

Regards,
Martin Ivanov
Progress Telerik
Want to extend the target reach of your WPF applications, leveraging iOS, Android, and UWP? Try UI for Xamarin, a suite of polished and feature-rich components for the Xamarin framework, which allow you to write beautiful native mobile apps using a single shared C# codebase.
Jan
Top achievements
Rank 1
commented on 17 Nov 2022, 01:52 PM

Hi. Does that still work nowadays? Where do I put my API key?
Martin Ivanov
Telerik team
commented on 21 Nov 2022, 10:34 AM

This should still work, but there are some Google API license concerns that you should keep in mind. You can find more information here: https://stackoverflow.com/questions/58846393/how-to-apply-api-key-to-google-maps-tile-server-url

 

Jan
Top achievements
Rank 1
commented on 21 Nov 2022, 10:41 AM

Aha! OK. It's not really about the key. It is generally no longer allowed to use Google Maps for desktop applications. Good for Microsoft and OpenStreetMap. :)
Tags
Map
Asked by
Peter
Top achievements
Rank 1
Veteran
Answers by
Dinko | Tech Support Engineer
Telerik team
Joe Bohen
Top achievements
Rank 1
Martin Ivanov
Telerik team
Share this question
or