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

1. Antes de comenzar

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

Así se verá tu app cuando hayas terminado.

7e7c194a98d6dfa4.png

Requisitos previos

Qué aprenderás

  • Cómo crear una app sencilla de iOS Swift que use el SDK de Navigation para navegar a un destino
  • Cómo integrar el SDK de Navigation desde el repositorio remoto de Cocoapods
  • Cómo administrar los permisos de ubicación y el acuerdo del usuario con las condiciones del usuario final del SDK de Navigation
  • Cómo inicializar el SDK
  • Cómo establecer un destino e iniciar la guía de navegación

Requisitos

  • La versión estable más reciente de XCode.
  • Una Cuenta de Google y un proyecto con facturación habilitada
  • Un dispositivo iOS o un dispositivo emulado que se ejecute en el simulador de XCode 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 para comenzar a usar Google Maps Platform.

Selecciona un 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 & Servicios > Biblioteca en la consola de Google Cloud y busca “SDK de Navigation”.

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

Pantalla de la biblioteca de APIs en la consola de Google Cloud, que muestra la página del SDK de Navigation.

Haz clic en SDK de Navigation para abrir la página Detalles del producto. Haz clic en Habilitar para habilitar el SDK en tu proyecto.

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

Crea una clave de API

Genera una clave de API en la página Credenciales de Cloud Console. Todas las solicitudes a Google Maps Platform requieren una clave de API. En la página Credenciales en la consola. Haz clic en “+Crear credenciales”. en la parte superior de la página y selecciona "Clave de API" de las opciones.

Para el uso en producción, se recomienda establecer una restricción de aplicaciones para tu clave de API, pero es opcional para este codelab.

3. Obtén los archivos de proyecto de muestra

En esta sección, se describe cómo configurar un proyecto básico de app de Xcode vacío mediante la clonación de archivos del repositorio de GitHub de 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 el repositorio o descarga el código

Navega al directorio en el que deseas almacenar el codelab.

Luego, clona el repositorio o descarga el código:

git clone https://github.com/googlemaps-samples/codelab-navigation-101-ios-swift

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

Para que puedas comenzar lo más rápido posible, el repositorio contiene código de partida en la carpeta Starter que te ayudará a seguir este codelab. También hay un proyecto Solution terminado en caso de que quieras avanzar o consultar tu progreso en cualquier momento. Para usar el proyecto de solución, deberás seguir las instrucciones de la sección "Instalación con CocoaPods" que se indican a continuación y, luego, ejecuta el comando “pod update” de la carpeta solution/Navigation SDK Codelab.

Una vez que hayas clonado el repositorio de forma local, usa Xcode para abrir la carpeta Starter como un proyecto existente. Verifica que el proyecto se compile y se ejecute.

Conecta un dispositivo o configura el simulador de Xcode

4. Agrega el SDK de Navigation a tu app

Existen tres maneras de integrar el SDK de Navigation en un proyecto de Xcode:En este codelab, se usa CocoaPods. Para obtener detalles sobre cómo realizar la integración con Swift Package Manager o para instalarla manualmente descargando el SDK, consulta Cómo crear el proyecto de Xcode e instalar el SDK de Navigation en la documentación del SDK de Navigation.

Cómo instalar con CocoaPods

Si todavía no dispones de la herramienta CocoaPods, instálala en macOS ejecutando el siguiente comando desde el terminal. Para obtener más información, consulta la guía de introducción de CocoaPods.

sudo gem install cocoapods

Crea un archivo nuevo llamado Podfile en la carpeta de tu proyecto, dentro de la carpeta del codelab del SDK de Navigation/starter (en XCode, File > New > File > Other > Empty, save as "Podfile").

Agrega el siguiente contenido a tu Podfile:

source 'https://github.com/CocoaPods/Specs.git'

platform :ios, '15.0'

target 'Navigation SDK Codelab' do
  pod 'GoogleNavigation', '9.1.1'
end

Ahorra Podfile.

Abre una terminal y cambia el directorio a la ubicación en la que guardaste tu Podfile (debería ser la carpeta "starter/Navigation SDK Codelab" en el repositorio del codelab).

cd "<path-to-starter-project-folder>/Navigation SDK Codelab"

Ejecuta el comando pod install. Esto instala las APIs especificadas en el archivo Podfile, junto con cualquier dependencia.

pod install

Cierra Xcode y, luego, abre el archivo .xcworkspace de tu proyecto para ejecutar Xcode. A partir de este punto, debes usar el archivo .xcworkspace para abrir el proyecto.

Verifica que se haya agregado un directorio de Pods a la estructura del proyecto y que contenga los Pods "GoogleMaps" y "GoogleNavigation".

6e81772ee067d452.png

Agrega tu clave de API

Agrega tu clave de API a AppDelegate.swift de la siguiente manera:

  1. Agrega las siguientes instrucciones de importación:
import GoogleMaps
import GoogleNavigation
  1. Agrega lo siguiente a tu método application(_:didFinishLaunchingWithOptions:):
GMSServices.provideAPIKey("YOUR_API_KEY")

Reemplaza "YOUR_API_KEY" por la clave de API que creaste en el paso anterior.

Compila tu proyecto y corrige los errores.

5. Cómo configurar los permisos de la app

El SDK de Navigation depende de las señales de GPS para proporcionar una ubicación ajustada a la ruta y una guía paso a paso, por lo que tu app deberá solicitarle al usuario que otorgue acceso a datos de ubicación precisa.

Para ello, agregarás algunas propiedades al archivo Info.plist de tu app en Xcode, agregarás código a la app para solicitarle permiso al usuario durante el tiempo de ejecución y controlarás cualquier error, como que no se otorgue el permiso o que la ubicación no esté disponible.

Abre Info.plist en Xcode. Debe verse más o menos así.

6532a85bd9ac8fb4.png

Cómo solicitar el permiso de ubicación precisa

Para agregar valores nuevos, coloca el puntero del mouse sobre la fila "Lista de propiedades de información" hasta que aparezca el ícono "+". Haz clic en el signo "+" para ver un diálogo con nombres de propiedades sugeridos, pero ten en cuenta que también puedes agregar propiedades de forma manual.

Agrega las siguientes propiedades y valores al archivo Info.plist:

Propiedad

Valor

Privacidad: Descripción de uso de la ubicación siempre y cuando está en uso

"Esta app requiere la ubicación de tu dispositivo para proporcionar navegación paso a paso"

Privacidad: Descripción del uso de la ubicación durante el uso

"Esta app requiere la ubicación de tu dispositivo para proporcionar navegación paso a paso"

allowsBackgroundLocationUpdates

Cómo solicitar el permiso de ubicación en segundo plano

Agrega las siguientes propiedades y valores al archivo Info.plist:

UIBackgroundModes Agregar fila > Item 0: App registers for location updates (selecciona este valor de la lista desplegable de sugerencias)

El archivo Info.plist debería tener un aspecto similar al siguiente cuando termines.

3b0c49018451d0ff.png

Solicita acceso a la ubicación en el tiempo de ejecución

Agrega las siguientes instrucciones de importación a ViewController.swift:

import GoogleNavigation

Agrega la siguiente declaración a tu clase ViewController:

var locationManager: CLLocationManager!

Agrega una anulación de método para loadView() y llama a locationManager.requestAlwaysAuthorization():

override func loadView() {
        locationManager = CLLocationManager()
        locationManager.requestAlwaysAuthorization()

Ahora, tu app solicitará la ubicación del usuario y la pondrá a disposición de tu app si otorga permiso.

Solicita permiso para mostrar notificaciones

Agrega el siguiente código a loadView() para solicitar permiso al usuario para mostrar notificaciones, lo cual será necesario para mostrar las instrucciones de maniobra de navegación.

UNUserNotificationCenter.current().requestAuthorization(options: [.alert]) {
        granted, error in
        // Handle denied authorization to display notifications.
          if !granted || error != nil {
              print("User rejected request to display notifications.")
          }
        }

Compila y ejecuta la app, y verifica que se te solicite compartir la ubicación y habilitar las notificaciones.

ad5f665a21170c49.png

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

En este paso, agregarás un mapa y lo configurarás para que muestre una ubicación. Luego, le mostrarás al usuario un diálogo con las condiciones de uso del SDK de Navigation.

Cómo agregar una vista de mapa a tu app

Agrega esta línea para declarar una variable GMSMapView en tu ViewController.

var mapView: GMSMapView!

Agrega el siguiente código a loadView() en tu Viewcontroller.swift para inicializar el mapa.

let camera = GMSCameraPosition.camera(withLatitude: 51.483174, longitude: -0.177369, zoom: 14)
let options = GMSMapViewOptions()
options.camera = camera
options.frame = .zero
        
mapView = GMSMapView(options: options)
view = mapView

Compila y ejecuta tu app. Deberías ver un mapa centrado en el suroeste de Londres.

1d46ce5c0851cae3.png

Cómo mostrar el diálogo de Condiciones de uso del producto del SDK de Navigation

Agrega el siguiente código a ViewController.swift en el mismo método loadView() que el código anterior. Se mostrarán las condiciones de uso para usuarios finales del SDK de Navigation. Si no se acepta, no se habilitará la navegación.

// Show the terms and conditions.
let companyName = "Navigation SDK Codelab"
GMSNavigationServices.showTermsAndConditionsDialogIfNeeded(withCompanyName: companyName) { termsAccepted in
  if termsAccepted {
    // Enable navigation if the user accepts the terms.
    self.mapView.isNavigationEnabled = true
    // Request authorization for alert notifications which deliver guidance instructions
    // in the background.
  } else {
    // Handle the case when the user rejects the terms and conditions.
  }
}

Compila y ejecuta la app para ver el diálogo.

29f17ae5b4c07c9f.png

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

En este paso, aprenderás a configurar objetos de escucha para eventos clave, como la llegada a un destino o la redirección del conductor.

Para escuchar estos eventos, tu controlador de vistas debe adoptar el protocolo GMSNavigatorListener.

Agrega este protocolo a la definición de clase en ViewController.swift.

class ViewController: UIViewController,
                      GMSNavigatorListener {

Ahora, agrega una línea de código para configurar el objeto de escucha en loadView():.

// Add a listener for GMSNavigator.
mapView.navigator?.add(self)

Por último, agrega dos métodos a tu clase para controlar los eventos que se generan.

// Listener to handle arrival events.
func navigator(_ navigator: GMSNavigator, didArriveAt waypoint: GMSNavigationWaypoint) {
  print("You have arrived at: \(waypoint.title)")
}

// Listener for route change events.
func navigatorDidChangeRoute(_ navigator: GMSNavigator) {
  print("The route has changed.")
}

8. Establece un destino y comienza la guía

En esta sección, aprenderás a establecer un destino e iniciar la guía de navegación.

Crea una función nueva para la lógica de navegación.

Primero, agrega una nueva función llamada startNav() a tu ViewController. Contendrá la lógica para establecer un destino y comenzar a navegar.

// Create a route and start guidance.
@objc func startNav() {
}

Crea un Waypoint para el destino.

A continuación, crea un array de destinos con un solo punto de referencia.

// Create a route and start guidance.
@objc func startNav() {
  var destinations = [GMSNavigationWaypoint]()
  destinations.append(
    GMSNavigationWaypoint.init(
      placeID: "ChIJH-tBOc4EdkgRJ8aJ8P1CUxo",
      title: "Trafalgar Square")!)
}

Llama a setDestinations()y controla la respuesta.

A continuación, llama a setDestinations y controla el GMSRouteStatus que se muestra.

Si GMSRouteStatus es "OK", establece isGuidanceActive=true en el objeto navigator de mapView para iniciar la guía. De lo contrario, imprime una instrucción para mostrar que se produjo un error.

Si el valor de GMSRouteStatus que se muestra es "OK", comienza a simular la conducción a lo largo de la ruta llamando a mapView.locationSimulator.simulateLocationsAlongExistingRoute().

// Create a route and start guidance.
@objc func startNav() {
  var destinations = [GMSNavigationWaypoint]()
    destinations.append(
      GMSNavigationWaypoint.init(
        placeID: "ChIJH-tBOc4EdkgRJ8aJ8P1CUxo",
          title: "Trafalgar Square")!)
      
  mapView.navigator?.setDestinations(
    destinations
  ) { routeStatus in
    guard routeStatus == .OK else {
      print("Handle route statuses that are not OK.")
      return
    }
    //If routeStatus is OK, start guidance.
    self.mapView.navigator?.isGuidanceActive = true
    //start simulating driving along the route. self.mapView.locationSimulator?.simulateLocationsAlongExistingRoute()
    self.mapView.cameraMode = .following
  }
}

Cómo controlar los estados de error comunes

Resulta útil controlar los errores GMSRouteStatus de forma más explícita, en especial cuando depuras problemas iniciales con la app nueva. Por ejemplo, tal vez descubras que obtienes permiso de ubicación, clave de API o que no se encontró ninguna ruta errores con mayor frecuencia al principio debido a tu configuración de depuración, por lo que puede ser útil manejar estos estados de error.

Agrega un código que controle estos casos específicos y que imprima una sentencia en la consola.

mapView.navigator?.setDestinations(
  destinations
) { routeStatus in
    guard routeStatus == .OK else {
      print("Handle route statuses that are not OK.")
      switch routeStatus {
       case .locationUnavailable:
        print("Location unavailable.") //check permissions
      case .noRouteFound:
        print("No route found.") //check start location and destination
      case .waypointError:
        print("Waypoint error") //check Place ID
      default:
        print("Not sure what happened")
      }
    return
  }

Agrega un botón para iniciar la guía de navegación

Por último, agrega un botón a la IU y conéctalo al método startNav. Crea un método llamado makeButton() con el siguiente código. Llama a la función makeButton() desde loadView().

// Add a button to the view.
func makeButton() {
  // A button to start navigation.
  let navButton = UIButton(frame: CGRect(x: 5, y: 150, width: 200, height: 35))
  navButton.backgroundColor = .blue
  navButton.alpha = 0.5
  navButton.setTitle("Start navigation", for: .normal)
  navButton.addTarget(self, action: #selector(startNav), for: .touchUpInside)
  self.mapView.addSubview(navButton)
}

Compila y ejecuta tu app.

Nota: Ejecutar el código en

startNav()

llamará al

setDestinations()

que genera un cargo después de los primeros 1,000 destinos utilizados. Consulta Uso y facturación para obtener más información.

9. ¡Felicitaciones!

¡Bien hecho! Llegaste a tu destino.

7a69dcb75c904d7.png

Creaste una app simple que ofrece una guía de navegación paso a paso hacia un destino con el SDK de Navigation de Google Maps Platform.

Ya configuraste los permisos de la app y el diálogo de condiciones para el usuario final del SDK de Navigation, y especificaste un destino con un ID de Place. Controlaste varios estados de éxito y error en tu app.

10. Más información

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

  • Cómo detectar más eventos de navegación Agrega un código para mostrar un mensaje si el tiempo o la distancia restantes supera un umbral.
  • Personaliza la interfaz de navegación.
  • Si quieres un desafío mayor, intenta agregar un selector de lugares de la API de Places para permitir que el usuario establezca el destino. Sugerencia: Las apps de demostración del SDK de Navigation tienen una implementación de ejemplo. Ejecuta pod try GoogleNavigation en la carpeta de tu proyecto para ver el código.