Compila una app de navegación simple para Android con el SDK de Navigation de Google Maps Platform

Crea una app de navegación simple para Android con el SDK de Navigation de Google Maps Platform

Acerca de este codelab

subjectÚltima actualización: oct 10, 2024
account_circleEscrito por Ed Boiling

1. Antes de comenzar

En este codelab, aprenderás a crear una app para Android simple que use el SDK de Navigation de Google Maps Platform para navegar a un destino preconfigurado.

Así se verá tu app cuando hayas terminado.

b6c535afde7abd20.png

  • Conocimientos sobre desarrollo básico de apps para Android en Kotlin
  • Estar familiarizados con los conceptos básicos del SDK de Google Maps, como mapas, ubicaciones y coordenadas

Qué aprenderás

  • Cómo crear una app para Android simple que use el SDK de Navigation para navegar a un destino
  • Cómo integrar el SDK de Navigation desde el repositorio remoto de Google Maven
  • Cómo administrar los permisos de ubicación y el acuerdo del usuario con las condiciones para el usuario final del SDK de Navigation
  • Cómo inicializar el SDK
  • Cómo establecer un destino y comenzar la guía de navegación

Requisitos

  • La versión estable más reciente de Android Studio instalada Este codelab se creó con Android Studio Jellyfish. Si usas una versión diferente, es posible que la apariencia y el diseño de la interfaz y los componentes varíen.
  • Una Cuenta de Google y un proyecto con la facturación habilitada
  • Un dispositivo Android en modo de desarrollador con la depuración por USB habilitada o un emulador de Android Cualquiera que elijas debe cumplir con los requisitos mínimos del SDK de Navigation.

2. Prepárate

Si aún no tienes una cuenta de Google Cloud Platform y un proyecto con la facturación habilitada, configura tu proyecto de Google Cloud siguiendo las instrucciones de Cómo comenzar a utilizar Google Maps Platform https://developers.google.com/maps/gmp-get-started

Selecciona tu proyecto de Google Cloud en la consola.

En Cloud Console, haz clic en el menú desplegable del proyecto y selecciona el proyecto que deseas usar para este codelab.

Menú desplegable del selector de proyectos en la consola de Google Cloud.

Habilita el SDK de Navigation en tu proyecto

Habilita las API y los SDK de Google Maps Platform necesarios para este codelab en Google Cloud Marketplace.

Navega a APIs y servicios > Biblioteca en la consola de Google Cloud y busca "SDK de Navigation".

Deberías ver un resultado de la búsqueda.

La pantalla Biblioteca de APIs de la consola de Google Cloud, que muestra la página del SDK de Navigation.

Haz clic en el resultado del SDK de Navigation para abrir la página de detalles del producto. Haz clic en el botón Habilitar para habilitar el SDK en tu proyecto.

Repite este proceso para el SDK de Google Maps para Android.

Crea una clave de API

Genera una clave de API en la página Credenciales de Cloud Console. Puedes seguir los pasos del paso 3 de la sección de la guía de inicio rápido en Cómo comenzar a usar Google Maps Platform. Todas las solicitudes a Google Maps Platform requieren una clave de API.

3. Obtén los archivos de proyecto de muestra

En esta sección, se describe cómo configurar un proyecto básico y vacío de Android Studio clonando archivos del repositorio de GitHub para este codelab. El repositorio de GitHub contiene versiones anteriores y posteriores del código del codelab. El codelab comenzará con una plantilla de proyecto vacía y se compilará hasta el estado finalizado. Si te quedas atascado, puedes usar el proyecto terminado en el repositorio como referencia.

Clona este repositorio de GitHub para obtener el código necesario para este codelab.

git clone https://github.com/googlemaps-samples/codelab-navigation-101-android-kotlin.git

Si no tienes instalado git, haz clic en este botón para obtener el código:

Para que puedas comenzar lo más rápido posible, el repo contiene código de partida en la carpeta Starter que te ayudará a seguir este codelab. El proyecto inicial proporciona una IU de app y una configuración de compilación básicas, pero no tiene el SDK de Navigation agregado. También hay un proyecto Solution terminado en caso de que quieras avanzar o consultar tu progreso en cualquier momento.

Abre el repositorio clonado en Android Studio

Una vez que hayas clonado el repositorio de forma local, usa Android Studio para abrir la carpeta Starter como un proyecto existente.

  1. En el diálogo Welcome to Android Studio, haz clic en el botón Open.
  2. Navega a la carpeta en la que guardaste el repositorio clonado y selecciona la carpeta Starter dentro de la carpeta de nivel superior "codelab-navigation-101-android-kotlin".
  3. Verifica que el proyecto se compile y ejecute.

Agrega un dispositivo virtual o conecta un dispositivo de hardware

Para conectar un dispositivo Android a tu computadora, sigue las instrucciones de Android Studio para ejecutar apps en un dispositivo de hardware. También puedes configurar un dispositivo virtual con el Administrador de dispositivos virtuales de Android (AVD). Cuando elijas un emulador, asegúrate de seleccionar una imagen que incluya las APIs de Google.

En Android Studio, haz clic en la opción Ejecutar del menú o en el ícono del botón de reproducción. Selecciona un dispositivo según se solicite.

4. Agrega el SDK de Navigation a tu app

Agrega la biblioteca del SDK de Navigation y tu clave de API a tu proyecto

Para agregar la biblioteca del SDK de Navigation a tu app, debes modificar el build.gradle.kts de nivel de la app para recuperar el SDK de Navigation del repositorio de Maven de Google y configurar un número de versión.

Crea una variable en la configuración de compilación para almacenar el número de versión del SDK de Navigation.

Configura una variable en tu build.gradle.kts a nivel de la app para que contenga el valor de la versión del SDK de Navigation que se usa en tu app, de modo que sea fácil cambiar a la versión más reciente en el futuro.

Consulta las notas de la versión del SDK de Navigation para conocer el número de versión más reciente.

val navSdkVersion by extra("6.0.0")

También puedes modificar los valores de esta y otras variables usando el diálogo que se encuentra en Archivo > Estructura del proyecto > Variables:

668332736b67dc82.png

Agrega una dependencia a la configuración de compilación

Ahora, agrega la siguiente dependencia de API al bloque de dependencias en el archivo build.gradle.kts. del nivel de la app. La versión que se usará será el valor de ${navSdkVersion} que acabas de establecer en el archivo build.gradle.kts del nivel de la app:

dependencies {

   // Include the Google Navigation SDK.
   api("com.google.android.libraries.navigation:navigation:${navSdkVersion}")

...

Agrega tu clave de API

Usa el complemento Secrets Gradle para administrar la clave de API

Te recomendamos que uses el complemento Secrets Gradle para administrar la clave de API de forma segura en tu app. Se agregó el complemento a la plantilla inicial del proyecto como una dependencia en tu archivo build.gradle.kts de nivel superior.

// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
    id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin") version "2.0.1" apply false
    //... other plugin definitions here
}

Abre el archivo secrets.properties en tu directorio de nivel superior y, luego, reemplaza YOUR_API_KEY por tu clave de API. Almacena tu clave en este archivo, ya que secrets.properties no se registra en un sistema de control de versión.

MAPS_API_KEY=YOUR_API_KEY

Para obtener más información sobre este tema, consulta Cómo agregar la clave de API a tu app en la documentación del SDK de Navigation.

Verifica el contenido de local.defaults.properties

El proyecto vacío también contiene un archivo local.defaults.properties en tu directorio de nivel superior, en la misma carpeta que el archivo secrets.properties. Ábrelo y observa el siguiente código.

MAPS_API_KEY=DEFAULT_API_KEY

Esto existe para proporcionar un valor de copia de seguridad para la propiedad MAPS_API_KEY en caso de que no se agregue secrets.properties al proyecto, de modo que no fallen las compilaciones. No es necesario editar este archivo. Si no se encuentra la definición secrets.properties de MAPS_API_KEY, el valor predeterminado detendrá la ejecución de la app en el tiempo de ejecución y se mostrará un error de clave de API.

Verifica que el manifiesto de Android use la clave de API que especificaste

Abre app/src/main/AndroidManifest.xml. Notarás que la propiedad MAPS_API_KEY se usa para establecer la clave de API para la aplicación:

<meta-data
    android:name="com.google.android.geo.API_KEY"
    android:value="${MAPS_API_KEY}" />

Abre el archivo build.gradle.kts de nivel de la app y busca la propiedad secrets.

El parámetro propertiesFileName del complemento debe establecerse como secrets.properties, y defaultPropertiesFileName debe mostrar local.defaults.properties.

secrets {
    // Optionally specify a different file name containing your secrets.
    // The plugin defaults to "local.properties"
    propertiesFileName = "secrets.properties"

    // A properties file containing default secret values. This file can be
    // checked in version control.
    defaultPropertiesFileName = "local.defaults.properties"
}

Guarda todos los archivos y sincroniza tu proyecto con Gradle.

5. Cómo configurar los permisos de la app y agregar una IU básica

Cómo solicitar el permiso de ubicación precisa

El SDK de Navigation depende de las señales de GPS para funcionar, por lo que tu app deberá pedirle al usuario que otorgue acceso a datos de ubicación precisa. Agrega el permiso para acceder a la ubicación precisa como elemento secundario del elemento <manifest> en AndroidManifest.xml.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" >
   <uses-permission
      android:name="android.permission.ACCESS_FINE_LOCATION"
   />
</manifest>

Puedes obtener más información sobre los permisos de ubicación de Android en la sección Cómo solicitar permisos de ubicación de la documentación para desarrolladores de Android.

Para ejecutar tu app en un dispositivo con Android 14, solicita el permiso de ubicación de servicio en primer plano agregando la siguiente etiqueta uses-permission en la misma ubicación que el permiso de acceso a la ubicación precisa:

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

Cómo agregar una actividad de inicio con una IU básica

Cuando se ejecute tu app, necesitará código que se ejecute durante el inicio para verificar si el usuario otorgó permiso para acceder a su ubicación y controlar cada situación posible solicitando permiso si aún no se otorgó. Para ello, agrega una interfaz de usuario básica a tu app. En este codelab, se usa la IU que se genera cuando creas una nueva actividad de Views vacía en Android Studio. Adaptarás esto para realizar la verificación del permiso de ubicación antes de agregar código a la actividad para la IU de navegación.

Abre el archivo MainActivity.kt en el editor de código y, luego, inspecciona el código, que muestra una IU básica.

Cómo solicitar permisos de acceso a la ubicación en el tiempo de ejecución

Tu app deberá activar la solicitud para acceder a la ubicación precisa antes de que se inicialice el SDK de Navigation.

Para asegurarte de que esta verificación se realice cuando se inicie tu app, agrega código a la clase MainActivity, en el método onCreate() anulado de tu actividad.

El siguiente código verifica si el usuario otorgó el permiso de ubicación precisa. De lo contrario, solicita el permiso. Agrega este código a tu método onCreate().

    val permissions =
      if (VERSION.SDK_INT >= VERSION_CODES.TIRAMISU) {
        arrayOf(permission.ACCESS_FINE_LOCATION, permission.POST_NOTIFICATIONS)
      } else {
        arrayOf(permission.ACCESS_FINE_LOCATION)
      }

    if (permissions.any { !checkPermissionGranted(it) }) {

      if (permissions.any { shouldShowRequestPermissionRationale(it) }) {
        // Display a dialogue explaining the required permissions.
      }

      val permissionsLauncher =
        registerForActivityResult(
          RequestMultiplePermissions(),
          { permissionResults ->
            if (permissionResults.getOrDefault(permission.ACCESS_FINE_LOCATION, false)) {
              onLocationPermissionGranted()
            } else {
              finish()
            }
          },
        )

      permissionsLauncher.launch(permissions)
    } else {
      android.os.Handler(Looper.getMainLooper()).postDelayed({ onLocationPermissionGranted() }, SPLASH_SCREEN_DELAY_MILLIS)
    }
  }

  private fun checkPermissionGranted(permissionToCheck: String): Boolean =
    ContextCompat.checkSelfPermission(this, permissionToCheck) == PackageManager.PERMISSION_GRANTED

Agrega una función nueva a tu clase MainActivity, llamada onLocationPermissionGranted, que controlará el resultado cuando el usuario otorgue permiso para compartir su ubicación. En los próximos pasos, agregaremos código aquí para iniciar una nueva actividad de navegación.

private fun onLocationPermissionGranted() {
   //code to initialize Navigation SDK will go here
}

Compila tu proyecto. Si encuentras errores de compilación, búscalos y corrígelos.

Ejecuta tu proyecto en un dispositivo virtual nuevo. Deberías ver el diálogo de solicitud de permiso cuando la app se instale y se inicie.

6. Cómo agregar una interfaz de usuario de navegación

Existen dos maneras de agregar una IU de Navigation: SupportNavigationFragment o NavigationView.

Para simplificar, el codelab usa un NavigationView.

Edita el diseño

Edita res/layout/activity_main.xml para agregar un diseño para un elemento NavigationView.

  1. Abre el archivo y cambia a Vista de código.
  2. Reemplaza todo el contenido del archivo por un nuevo diseño de NavigationView dentro de un RelativeLayout, como en el siguiente ejemplo. Como solo agregarás una vista de navegación a la app, bastará con un diseño simple.
  3. Asigna a tu NavigationView un ID de "@+id/navigation_view".
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="match_parent">
 <com.google.android.libraries.navigation.NavigationView
     android:id="@+id/navigation_view"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
      />
</RelativeLayout>

Configura la actividad de Navigation

En Android Studio, abre el archivo MainActivity.kt en el editor.

Agrega código de configuración básico para garantizar que la experiencia de navegación funcione correctamente en tu app. En el archivo MainActivity.kt, realiza los siguientes cambios:

  1. Declara una variable en la clase MainActivity para hacer referencia a tu NavigationView:
private lateinit var navView: NavigationView
  1. Agrega código al método onCreate() para obtener una referencia a tu NavigationView:
navView = findViewById(R.id.navigation_view)
navView.onCreate(savedInstanceState)
  1. Agrega código al método onCreate() para asegurarte de que la pantalla permanezca encendida durante la guía de navegación:
// Ensure the screen stays on during nav.
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
  1. Edita el código que llama a ViewCompat.setOnApplyWindowInsetsListener para hacer referencia al ID de tu NavigationView.
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.navigation_view)) { v, insets ->
  val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
  v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
  insets
}
  1. Agrega un método showToast() a la clase para mostrar comentarios al usuario:
private fun showToast(errorMessage: String) {
   Toast.makeText(this@MainActivity, errorMessage, Toast.LENGTH_LONG).show()
}

7. Inicializa el SDK de Navigation

Ahora que completaste la configuración básica de la actividad de Navigation, puedes inicializar el SDK de Navigation. Para ello, agrega el siguiente código a tu archivo MainActivity.kt:

/** Starts the Navigation API, capturing a reference when ready. */
@SuppressLint("MissingPermission")
private fun initializeNavigationApi() {
   NavigationApi.getNavigator(
       this,
       object : NavigatorListener {
           override fun onNavigatorReady(navigator: Navigator) {
               // store a reference to the Navigator object
               mNavigator = navigator
               // code to start guidance will go here
           }

           override fun onError(@NavigationApi.ErrorCode errorCode: Int) {
               when (errorCode) {
                   NavigationApi.ErrorCode.NOT_AUTHORIZED -> {
                       // Note: If this message is displayed, you may need to check that
                       // your API_KEY is specified correctly in AndroidManifest.xml
                       // and is been enabled to access the Navigation API
                       showToast(
                           "Error loading Navigation API: Your API key is " +
                                   "invalid or not authorized to use Navigation."
                       )
                   }
                   NavigationApi.ErrorCode.TERMS_NOT_ACCEPTED -> {
                       showToast(
                           "Error loading Navigation API: User did not " +
                                   "accept the Navigation Terms of Use."
                       )
                   }
                   else -> showToast("Error loading Navigation API: $errorCode")
               }
           }
       },
   )

}

Este código crea un método nuevo llamado initializeNavigationApi(). Este método obtiene una referencia a un objeto Navigator llamando a NavigationApi.getNavigator() y, luego, implementa un NavigatorListener para controlar la devolución de llamada.

Ten en cuenta que, cuando se inicialice la API de Navigation, se invocará el método NavigationListener.onNavigatorReady, con un objeto Navigator que se pasa como parámetro. El código anterior actualizará la variable mNavigator que declaraste antes con el objeto Navigator inicializado que se pasa a este método.

Por último, agrega una llamada a tu método initializeNavigationApi desde el método onLocationPermissionGranted.

private fun onLocationPermissionGranted() {
   initializeNavigationApi()
}

8. Agrega objetos de escucha para eventos de navegación clave

Cuando los usuarios sigan las indicaciones, el SDK de Navigation activará eventos que pueden notificar a la app sobre cambios de estado clave en el proceso, como cuando el usuario se desvía o llega a su destino. En el archivo MainActivity.kt, agrega objetos de escucha para controlar estos eventos:

  1. Dentro de la clase MainActivity, declara dos variables para hacer referencia a objetos de objetos de escucha de eventos:
private var arrivalListener: Navigator.ArrivalListener? = null
private var routeChangedListener: Navigator.RouteChangedListener? = null
  1. Agrega un método registerNavigationListeners() para configurar los objetos de escucha cuando se inicialice Navigator. Este método llama a Navigator.clearDestinations() para restablecer NavigationView cuando se activa el evento de llegada:
/**
* Registers a number of example event listeners that show an on screen message when certain
* navigation events occur (e.g. the driver's route changes or the destination is reached).
*/
private fun registerNavigationListeners() {
   withNavigatorAsync {
       arrivalListener =
           Navigator.ArrivalListener { // Show an onscreen message
               showToast("User has arrived at the destination!")
               mNavigator?.clearDestinations()
           }
       mNavigator?.addArrivalListener(arrivalListener)

       routeChangedListener =
           Navigator.RouteChangedListener { // Show an onscreen message when the route changes
               showToast("onRouteChanged: the driver's route changed")
           }
       mNavigator?.addRouteChangedListener(routeChangedListener)
   }
}
  1. Agrega una llamada a registerNavigationListeners() desde el código de devolución de llamada onNavigatorReady en el método initializeNavigationApi:
override fun onNavigatorReady(navigator: Navigator) {
   // store a reference to the Navigator object
   mNavigator = navigator

   //listen for events en route
   registerNavigationListeners()


}
  1. Configura la interfaz de usuario. Puedes controlar varios aspectos de la interfaz de usuario de navegación cuando se ejecuta la guía. Una personalización importante es la posición de la cámara. Agrega una llamada al método setTaskRemovedBehaviour del objeto navigator que se muestra en onNavigatorReady de la siguiente manera. Esto finalizará la guía y la notificación si se desliza la app:
// Disables the guidance notifications and shuts down the app and background service
// when the user dismisses/swipes away the app from Android's recent tasks.
navigator.setTaskRemovedBehavior(Navigator.TaskRemovedBehavior.QUIT_SERVICE)
  1. Agrega una llamada a GoogleMap.followMyLocation para especificar un CameraPerspective. Se puede acceder a GoogleMap a través del método NavigatorView.getMapAsync() de la siguiente manera:
navView.getMapAsync {
   googleMap  ->
   googleMap.followMyLocation(GoogleMap.CameraPerspective.TILTED)
}
  1. Para garantizar que la navegación funcione sin problemas durante el ciclo de vida de la app, implementa los siguientes métodos en tu clase MainActivity:
override fun onSaveInstanceState(savedInstanceState: Bundle) {
   super.onSaveInstanceState(savedInstanceState)

   navView.onSaveInstanceState(savedInstanceState)
}

override fun onTrimMemory(level: Int) {
   super.onTrimMemory(level)
   navView.onTrimMemory(level)
}

override fun onStart() {
   super.onStart()
   navView.onStart()
}

override fun onResume() {
   super.onResume()
   navView.onResume()
}

override fun onPause() {
   navView.onPause()
   super.onPause()
}

override fun onConfigurationChanged(configuration: Configuration) {
   super.onConfigurationChanged(configuration)
   navView.onConfigurationChanged(configuration)
}

override fun onStop() {
   navView.onStop()
   super.onStop()
}

override fun onDestroy() {
   navView.onDestroy()
   withNavigatorAsync {
       // Unregister event listeners to avoid memory leaks.
       if (arrivalListener != null) {
           navigator.removeArrivalListener(arrivalListener)
       }
       if (routeChangedListener != null) {
           navigator.removeRouteChangedListener(routeChangedListener)
       }

       navigator.simulator?.unsetUserLocation()
       navigator.cleanup()
   }
   super.onDestroy()
}

9. Establece un destino

Ya está todo listo para establecer un destino y comenzar la guía de navegación. En el archivo MainActivity.kt, realiza los siguientes cambios:

  1. Agrega un nuevo método navigateToPlace() que establezca el destino de navegación y acepte un parámetro placeId.
/**
* Requests directions from the user's current location to a specific place (provided by the
* Place ID).
*/
private fun navigateToPlace(placeId: String) {

}
  1. En tu método navigateToPlace(), usa Waypoint.builder() para crear un Waypoint a partir del ID de lugar que se pasó al método. Controla el UnsupportedPlaceIdException que puede generar esta situación en el caso de que el ID de lugar no se resuelva en una dirección precisa:
val waypoint: Waypoint? =
// Set a destination by using a Place ID (the recommended method)
try {
   Waypoint.builder().setPlaceIdString(placeId).build()
} catch (e: Waypoint.UnsupportedPlaceIdException) {
   showToast("Place ID was unsupported.")
   return
}
  1. Agrega el siguiente código a tu método navigateToPlace() para establecer un destino con el punto de referencia:
val pendingRoute = mNavigator?.setDestination(waypoint)

// Set an action to perform when a route is determined to the destination
pendingRoute?.setOnResultListener { code ->
   when (code) {
       RouteStatus.OK -> {
           // Code to start guidance will go here
       }

       RouteStatus.ROUTE_CANCELED -> showToast("Route guidance canceled.")
       RouteStatus.NO_ROUTE_FOUND,
       RouteStatus.NETWORK_ERROR ->
           // TODO: Add logic to handle when a route could not be determined
           showToast("Error starting guidance: $code")

       else -> showToast("Error starting guidance: $code")
   }
}

El objeto Navigator tiene un método setDestinations() que puede tomar una variedad de parámetros. La opción más básica es proporcionar un Waypoint. De forma predeterminada, el medio de transporte será DRIVING, adecuado para vehículos de 4 ruedas a motor. El método setDestinations() muestra un objeto ListenableResultFuture que contiene un objeto RouteStatus. RouteStatus indicará si se encontró una ruta hacia el destino y te permitirá controlar varios estados de error si no es así.

  1. Realiza cambios de configuración adicionales para mejorar la experiencia del usuario de navegación:
// Hide the toolbar to maximize the navigation UI
supportActionBar?.hide()

// Enable voice audio guidance (through the device speaker)
mNavigator?.setAudioGuidance(Navigator.AudioGuidance.VOICE_ALERTS_AND_GUIDANCE)


// Simulate vehicle progress along the route (for demo/debug builds)
if (BuildConfig.DEBUG) {
   mNavigator?.simulator?.simulateLocationsAlongExistingRoute(
       SimulationOptions().speedMultiplier(5f)
   )
}

Estos cambios incluyen las siguientes mejoras:

  • Se oculta la barra de acción para maximizar el espacio de la IU de Navigation.
  • Habilita las indicaciones por audio para las alertas habladas y las instrucciones de navegación.
  • Configurar el simulador para la depuración mediante la especificación de un multiplicador de velocidad.
  1. Busca un ID de lugar que actuará como destino. Lo ideal sería que no estuviera demasiado lejos de la ubicación del usuario. Usa la utilidad Buscador de IDs de lugares de Google Maps Platform o obtén un ID de lugar a partir de una llamada a la API de Places.

Si simulas la navegación, puedes establecer la ubicación del usuario en el código o tomarla de tu dispositivo conectado. En el codelab, se dará por sentado que estás simulando una ubicación en Londres, Reino Unido.

  1. Agrega un objeto complementario a tu clase MainActivity para almacenar una ubicación de inicio y un ID de lugar. El codelab usará una ubicación de partida en Londres y el ID de lugar de Trafalgar Square:
companion object{
   const val TRAFALGAR_SQUARE ="ChIJH-tBOc4EdkgRJ8aJ8P1CUxo" //London, UK
   val startLocation = LatLng(51.345678, -0.1234456)
}
  1. Agrega una llamada a tu método navigateToPlace() desde la devolución de llamada onNavigatorReady dentro del método initializeNavigationApi y agrega una rama de la lógica que se ejecutará en el modo de depuración y que establezca la ubicación del usuario:
// Disables the guidance notifications and shuts down the app and background service
// when the user dismisses/swipes away the app from Android's recent tasks.
navigator.setTaskRemovedBehavior(Navigator.TaskRemovedBehavior.QUIT_SERVICE)

mNavigator = navigator

if (BuildConfig.DEBUG) {
   mNavigator?.simulator?.setUserLocation(MainActivity.startLocation)
}
//listen for events en route
registerNavigationListeners()

navView.getMapAsync {
   googleMap  ->
   googleMap.followMyLocation(GoogleMap.CameraPerspective.TILTED)
}

//navigate to a destination
navigateToPlace(MainActivity.TRAFALGAR_SQUARE)

10. Compila y ejecuta tu código

La primera vez que ejecutes la app, deberás otorgarle permisos de ubicación y aceptar las condiciones de uso del SDK de Navigation.

Nota: Cuando ejecutes la app, se llamará al método setDestinations(), que genera un cargo después de que se usen los primeros 1,000 destinos. Consulta Uso y facturación para obtener más información.

93aa433000a14dfc.png

Diálogo de las condiciones del usuario final del SDK de Navigation.

Cómo configurar la ubicación

De forma predeterminada, el dispositivo emulado puede tener su ubicación establecida en el campus de Google en Mountain View, California, a menos que hayas establecido una ubicación en el código o usando el diálogo de propiedades del emulador.

Si es así, es posible que la app no encuentre una ruta hacia el ID de lugar que configuraste (de forma predeterminada, la Ópera de Sídney, Sídney, Australia). Tu método showToast() lo indicará con el mensaje "No route found".

Vista del mapa de la app de Navegación que muestra la oficina de Google en Mountain View, California.

Cómo codificar de forma fija la ubicación de partida

Para establecer una ubicación diferente en el código, agrega la siguiente línea a tu método navigateToPlace() en MainActivity.kt, antes de la llamada a mNavigator.startGuidance():

mNavigator?.simulator?.setUserLocation(startLocation)

Cómo iniciar el emulador en la ubicación predeterminada que elijas

Para establecer una ubicación diferente en el emulador del dispositivo, inícialo si aún no se está ejecutando y haz clic en el menú de 3 puntos con la información sobre la herramienta "Extended Controls". El cuadro de diálogo que se abre tiene una opción de menú para "Ubicación".

Por ejemplo, si utilizas el ID de lugar de la Ópera de Sídney como destino, elige una ubicación en Sídney, Australia. Por ejemplo, busca "playa Bondi", selecciona una sugerencia y haz clic en "Guardar ubicación" en la parte inferior derecha del diálogo. También puedes hacer clic en "Guardar punto" para agregar la ubicación a una lista guardada para usarla en el futuro.

Diálogo Extended Controls en el Administrador de dispositivo Android, muestra un selector de lugar y un mapa centrados en Bondi Beach, Australia

Si estableces un ID de Place diferente como destino, elige una ubicación cercana para que la ruta simulada sea realista y no demasiado larga para facilitar la depuración.

Reinicia la app, que ahora debería navegar al destino.

Una captura de pantalla de la app de navegación que brinda instrucciones para llegar al destino

11. ¡Felicitaciones!

Completaste este codelab. ¡Felicitaciones! Llegaste a tu destino. ¡Diviértete programando! :-)

55812f33256c0596.png

12. Más información

Si quieres llevar el desarrollo de tu app más allá, echa un vistazo a los siguientes temas para inspirarte.