Can't load Baspemaps and Operational Layer on a MapView control Xamarin.Forms when UWP project is in Release Mode.

923
3
Jump to solution
05-30-2017 08:10 PM
Highlighted
New Contributor II

I'm developing an Xamarin.Forms mapping app to Android and UWP Platforms using ESRI ArcGISRuntime SDK .NET 100.0 . As part of the workflow the app loads a basemap and a lot of different operational layers based on ArcGIS Tiled and Dynamic Map Services. At almost all development time I wrote and tested code in Debug mode of Visual Studio 2017 and everything went right. But as part of testing time I made a Release apk and appx files to tester teams. The testers of Android version reported that installations went OK, but Windows 10 and Windows 10 Mobile testers reported that basemaps and operational layers did not load. Then I tested inside Visual Studio launching the UWP project in Release mode and I realized that it was true. On the other hand, to upload the application packages to the stores (Play Store and Windows Store) the app must me compiled in Release mode.

Checking the two configurations at project property window I noted there was a pair of differences among Debug and Release mode the "General / Compile with .NET Native tool chain" checkbox was not checked in the first case and checked in the second case:

Debug Configuration

Release Configuration

I wrote a lite version of the app to proof the point, and the behavior is the same: this is the code of the ViewModel class of the MapPage.xaml that does this part of the workflow:

using Esri.ArcGISRuntime.Mapping;
using Prism.Mvvm;
using Prism.Services;
using System;
using Xamarin.Forms;

/// <summary>
///
/// </summary>
namespace MapTest.ViewModels
{
  /// <summary>
  ///
  /// </summary>
  public class MapPageViewModel : BindableBase
  {
    private Map _map;

    /// <summary>
    ///
    /// </summary>
    public Map Map
    {
      get { return _map; }
      set { SetProperty(ref _map, value); }
    }

    private IPageDialogService dialogService;

    /// <summary>
    ///
    /// </summary>
    /// <returns></returns>
    public IPageDialogService GetDialogService()
    {
      return dialogService;
    }

    /// <summary>
    ///
    /// </summary>
    /// <param name="value"></param>
    public void SetDialogService(IPageDialogService value)
    {
      dialogService = value;
    }

    /// <summary>
    ///
    /// </summary>
    public MapPageViewModel(IPageDialogService dialogService)
    {
      Map = new Map();
      SetDialogService(dialogService);
      AddLayers();
    }

    /// <summary>
    ///
    /// </summary>
    private void AddLayers()
    {
      try
      {
        Map.Basemap = Basemap.CreateTopographic();
        AddLayer("http://sampleserver5.arcgisonline.com/arcgis/rest/services/Elevation/WorldElevations/MapServer", "dynamic");
        ShowAlert("MapTest", "Finish");
      }
      catch (Exception ex)
      {
        ShowAlert("Exception", ex.Message);
      }
    }

    /// <summary>
    ///
    /// </summary>
    /// <param name="url"></param>
    /// <param name="tipo"></param>
    private void AddLayer(string url, string tipo)
    {
      Layer layer = null;
      if (tipo == "tiled")
      {
        layer = new ArcGISTiledLayer(new Uri(url));
      }
      else if (tipo == "dynamic")
      {
        layer = new ArcGISMapImageLayer(new Uri(url));
      }

      try
      {
        this.Map.OperationalLayers.Add(layer);
        ShowAlert("MapTest", "layer Added.");
      }
      catch (Exception ex)
      {
        throw ex;
      }
    }

    /// <summary>
    /// /
    /// </summary>
    /// <param name="title"></param>
    /// <param name="message"></param>
    private void ShowAlert(string title, string message)
    {
      System.Diagnostics.Debug.WriteLine(message);
      Device.BeginInvokeOnMainThread(async () =>
      {
          await this.GetDialogService().DisplayAlertAsync(
          title,
          message,
          "Close");
      });
    }
  }
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

The complete solution is published at github in this address: https://github.com/marceloctorres/MapTest.

Someone can help me to find the solution or at least a workaround? I would appreciate it.

Marcelo.

Reply
0 Kudos
1 Solution

Accepted Solutions
Highlighted
Esri Frequent Contributor

The .NET Native toolchain is a little tricky, as it strips out quite a lot of type information if it doesn't know any better.

The issue is also described here: https://forums.xamarin.com/discussion/comment/229956/#Comment_229956

To fix, go into your UWP project's App.xaml.cs file and find the Xamarin.Forms.Forms.Init call. Change it to explicitly initialize with our assembly:

Xamarin.Forms.Forms.Init(e, new[] { typeof(Esri.ArcGISRuntime.Xamarin.Forms.MapView).GetTypeInfo().Assembly });

Make sure you use the Xamarin.Forms MapView, and not the native Controls.UI.MapView control (it can actually be any type inside the specific assembly, since it's really just the assembly we need a reference to).

(Our included Forms project template also includes this call, but when starting from scratch you have to include it yourself).

View solution in original post

3 Replies
Highlighted
Esri Frequent Contributor

The .NET Native toolchain is a little tricky, as it strips out quite a lot of type information if it doesn't know any better.

The issue is also described here: https://forums.xamarin.com/discussion/comment/229956/#Comment_229956

To fix, go into your UWP project's App.xaml.cs file and find the Xamarin.Forms.Forms.Init call. Change it to explicitly initialize with our assembly:

Xamarin.Forms.Forms.Init(e, new[] { typeof(Esri.ArcGISRuntime.Xamarin.Forms.MapView).GetTypeInfo().Assembly });

Make sure you use the Xamarin.Forms MapView, and not the native Controls.UI.MapView control (it can actually be any type inside the specific assembly, since it's really just the assembly we need a reference to).

(Our included Forms project template also includes this call, but when starting from scratch you have to include it yourself).

View solution in original post

Highlighted
New Contributor II

Thanks, this solves my problem. I had tried that solution but adding the MapView of the wrong namespace.

Reply
0 Kudos
Highlighted
Esri Frequent Contributor

Funny. I made the same mistake the first time too 🙂 I wish there was a way we could hide the native MapView control when using Forms to avoid this confusion, but AFAIK that can't be done (the Xamarin.Forms MapView control actually uses the native MapView control internally, so it's really just a cross-platform wrapper for all the different platform controls).