Inicialización y configuración de Xamarin.Forms Map

El control Map usa el control de mapa nativo en cada plataforma. Esto proporciona una experiencia de mapas rápida y familiar para los usuarios, pero significa que se necesitan algunos pasos de configuración para cumplir los requisitos de API de cada plataforma.

Inicialización de mapa

El control Map lo proporciona el paquete NuGet Xamarin.Forms.Maps, que se debe agregar a todos los proyectos de la solución.

Después de instalar el paquete NuGet Xamarin.Forms.Maps, se debe inicializar en cada proyecto de plataforma.

En iOS, esto debe producirse en AppDelegate.cs invocando el método Xamarin.FormsMaps.Init después del método Xamarin.Forms.Forms.Init:

Xamarin.FormsMaps.Init();

En Android, esto debe producirse en MainActivity.cs invocando el método Xamarin.FormsMaps.Init después del método Xamarin.Forms.Forms.Init:

Xamarin.FormsMaps.Init(this, savedInstanceState);

En la Plataforma universal de Windows (UWP), esto debe producirse en MainPage.xaml.cs invocando el método Xamarin.FormsMaps.Init desde el constructor MainPage:

Xamarin.FormsMaps.Init("INSERT_AUTHENTICATION_TOKEN_HERE");

Para obtener información sobre el token de autenticación necesario en UWP, consulte Plataforma universal de Windows.

Una vez agregado el paquete NuGet y el método de inicialización denominado dentro de cada aplicación, las API Xamarin.Forms.Maps se pueden usar en el proyecto de código compartido.

Configuración de la plataforma

Se requiere configuración adicional en Android y la Plataforma universal de Windows (UWP) antes de que se muestre el mapa. Además, en iOS, Android y UWP, el acceso a la ubicación del usuario requiere que se hayan concedido permisos de ubicación a la aplicación.

iOS

Mostrar e interactuar con un mapa en iOS no requiere ninguna configuración adicional. Sin embargo, para acceder a los servicios de ubicación, debe establecer las siguientes claves en Info.plist:

Para admitir iOS 11 y versiones anteriores, puede incluir las tres claves: NSLocationWhenInUseUsageDescription, NSLocationAlwaysAndWhenInUseUsageDescription y NSLocationAlwaysUsageDescription.

La representación de XML de estas claves en Info.plist se muestra a continuación: Debe actualizar los valores string para reflejar cómo usa la aplicación la información de ubicación:

<key>NSLocationAlwaysUsageDescription</key>
<string>Can we use your location at all times?</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Can we use your location when your application is being used?</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Can we use your location at all times?</string>

Las entradas de Info.plist también se pueden agregar en la vista Origen al editar el archivo Info.plist:

Info.plist para iOS 8

A continuación, se muestra un mensaje cuando la aplicación intenta acceder a la ubicación del usuario, solicitando acceso:

Captura de pantalla de la solicitud de permisos de ubicación en iOS

Android

El proceso de configuración para mostrar e interactuar con un mapa en Android es:

  1. Obtener una clave de API de Google Maps y agregarla al manifiesto.
  2. Especifica el número de versión de Google Play Services en el manifiesto.
  3. Especificar el requisito de la biblioteca heredada HTTP de Apache en el manifiesto.
  4. [opcional] Especifica el permiso WRITE_EXTERNAL_STORAGE en el manifiesto.
  5. [opcional] Especifica los permisos de ubicación en el manifiesto.
  6. [opcional] Solicitar permisos de ubicación en tiempo de ejecución en la clase MainActivity.

Para obtener un ejemplo de un archivo de manifiesto configurado correctamente, consulte AndroidManifest.xml de la aplicación de ejemplo.

Obtener una clave de API de Google Maps

Para usar la API de Google Maps en Android, debe generar una clave de API. Para ello, siga las instrucciones de Obtención de una clave de API de Google Maps.

Una vez que haya obtenido una clave de API, debe agregarse dentro del elemento <application> del archivo Properties/AndroidManifest.xml:

<application ...>
    <meta-data android:name="com.google.android.geo.API_KEY" android:value="PASTE-YOUR-API-KEY-HERE" />
</application>

Esto inserta la clave de API en el manifiesto. Sin una clave de API válida, el control Map mostrará una cuadrícula en blanco.

Nota:

com.google.android.geo.API_KEY es el nombre de metadatos recomendado para la clave de API. Para la compatibilidad con versiones anteriores, se puede usar el nombre de los metadatos com.google.android.maps.v2.API_KEY, pero solo permite la autenticación en Android Maps API v2.

Para que el APK tenga acceso a Google Maps, debe incluir los nombres de paquete y las huellas digitales SHA-1 para cada almacén de claves (depuración y lanzamiento) que se use para firmar el APK. Por ejemplo, si usa un equipo para la depuración y otro para generar el APK de versión, debe incluir la huella digital del certificado SHA-1 desde el almacén de claves de depuración del primer equipo y la huella digital del certificado SHA-1 del almacén de claves de versión del segundo equipo. Recuerde también editar las credenciales de clave si cambia el nombre del paquete de la aplicación. Consulte Obtención de una clave de API de Google Maps.

Especificar el número de versión de Google Play Services

Agrega la siguiente declaración en el elemento <application> de AndroidManifest.xml:

<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />

Esto inserta la versión de los servicios de Google Play con la que se compiló la aplicación, en el manifiesto.

Especificación del requisito de la biblioteca heredada HTTP de Apache

Si la aplicación Xamarin.Forms tiene como destino API 28 o posterior, debe agregar la siguiente declaración dentro del elemento <application> de AndroidManifest.xml:

<uses-library android:name="org.apache.http.legacy" android:required="false" />    

Esto indica a la aplicación que use la biblioteca cliente HTTP de Apache, que se ha quitado de bootclasspath en Android 9.

Especificar el permiso WRITE_EXTERNAL_STORAGE

Si la aplicación tiene como destino API 22 o inferior, puede que sea necesario agregar el permiso WRITE_EXTERNAL_STORAGE al manifiesto, como elemento secundario del elemento <manifest>:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Esto no es necesario si la aplicación tiene como destino la API 23 o posterior.

Especificar permisos de ubicación

Si la aplicación necesita acceder a la ubicación del usuario, debe solicitar permiso agregando los permisos ACCESS_COARSE_LOCATION o ACCESS_FINE_LOCATION al manifiesto (o ambos), como elemento secundario del elemento <manifest>:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.myapp">
  ...
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
</manifest>

El permiso ACCESS_COARSE_LOCATION permite a la API usar WiFi o datos móviles, o ambos, para determinar la ubicación del dispositivo. Los permisos ACCESS_FINE_LOCATION permiten a la API usar el sistema de posicionamiento global (GPS), WiFi o datos móviles para determinar una ubicación lo más precisa posible.

Como alternativa, estos permisos se pueden habilitar mediante el editor de manifiestos para agregar los siguientes permisos:

  • AccessCoarseLocation
  • AccessFineLocation

Estos se muestran en la captura de pantalla siguiente:

Permisos necesarios para Android

Solicitar permisos de ubicación en tiempo de ejecución

Si la aplicación tiene como destino la API 23 o posterior y necesita acceder a la ubicación del usuario, debe comprobar si tiene el permiso necesario en tiempo de ejecución y solicitarlo si no lo tiene. Esto se puede lograr de la siguiente manera:

  1. En la clase MainActivity, agregue los siguientes campos:

    const int RequestLocationId = 0;
    
    readonly string[] LocationPermissions =
    {
        Manifest.Permission.AccessCoarseLocation,
        Manifest.Permission.AccessFineLocation
    };
    
  2. En la clase MainActivity, agregue la siguiente invalidación OnStart:

    protected override void OnStart()
    {
        base.OnStart();
    
        if ((int)Build.VERSION.SdkInt >= 23)
        {
            if (CheckSelfPermission(Manifest.Permission.AccessFineLocation) != Permission.Granted)
            {
                RequestPermissions(LocationPermissions, RequestLocationId);
            }
            else
            {
                // Permissions already granted - display a message.
            }
        }
    }
    

    Siempre que la aplicación tenga como destino la API 23 o posterior, este código realiza una comprobación de permisos en tiempo de ejecución para el permiso AccessFineLocation. Si no se ha concedido el permiso, se realiza una solicitud de permiso llamando al método RequestPermissions.

  3. En la clase MainActivity, agregue la siguiente invalidación OnRequestPermissionsResult:

    public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults)
    {
        if (requestCode == RequestLocationId)
        {
            if ((grantResults.Length == 1) && (grantResults[0] == (int)Permission.Granted))
                // Permissions granted - display a message.
            else
                // Permissions denied - display a message.
        }
        else
        {
            base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }
    

    Esta invalidación controla el resultado de la solicitud de permiso.

El efecto general de este código es que cuando la aplicación solicita la ubicación del usuario, se muestra el siguiente cuadro de diálogo que solicita permiso:

Captura de pantalla de la solicitud de permisos de ubicación en Android

Plataforma universal de Windows

En UWP, la aplicación debe autenticarse para poder mostrar un mapa y consumir servicios de mapa. Para autenticar la aplicación, debe especificar una clave de autenticación de mapas. Para obtener más información, consulte Solicitud de una clave de autenticación de mapas. A continuación, el token de autenticación debe especificarse en la llamada al método FormsMaps.Init("AUTHORIZATION_TOKEN") para autenticar la aplicación con Mapas de Bing.

Nota:

En UWP, para usar servicios de mapa como la geocodificación, también debe establecer la propiedad MapService.ServiceToken en el valor de clave de autenticación. Esto se puede lograr con la siguiente línea de código: Windows.Services.Maps.MapService.ServiceToken = "INSERT_AUTH_TOKEN_HERE";.

Además, si la aplicación necesita acceder a la ubicación del usuario, debe habilitar la funcionalidad de ubicación en el manifiesto del paquete. Esto se puede lograr de la siguiente manera:

  1. En Explorador de soluciones, haga doble clic en package.appxmanifest y seleccione la pestaña Funcionalidades.

  2. En la lista Funcionalidades, active la casilla Ubicación. Esto agrega la funcionalidad del dispositivo location al archivo de manifiesto del paquete.

    <Capabilities>
      <!-- DeviceCapability elements must follow Capability elements (if present) -->
      <DeviceCapability Name="location"/>
    </Capabilities>
    

Versiones de lanzamiento

Las compilaciones de versión de UWP usan la compilación nativa de .NET para compilar la aplicación directamente en código nativo. Sin embargo, una consecuencia de esto es que el representador del control Map en UWP puede estar vinculado fuera del ejecutable. Esto se puede corregir mediante una sobrecarga específica de UWP del método Forms.Init en App.xaml.cs:

var assembliesToInclude = new [] { typeof(Xamarin.Forms.Maps.UWP.MapRenderer).GetTypeInfo().Assembly };
Xamarin.Forms.Forms.Init(e, assembliesToInclude);

Este código pasa el ensamblado en el que reside la clase Xamarin.Forms.Maps.UWP.MapRenderer al método Forms.Init. Esto garantiza que el ensamblado no esté vinculado al archivo ejecutable por el proceso de compilación nativa de .NET.

Importante

Si no se hace esto, el control Map no aparece al ejecutar una compilación de versión.