Aspectos avanzados de Android 09.1: Google Maps

1. Bienvenido

Este codelab es parte del curso de capacitación sobre desarrollo avanzado de Android, desarrollado por el equipo de capacitación de Google Developers. Aprovecharás al máximo este curso si trabajas con los codelabs en secuencia.

Para obtener información completa sobre el curso, consulta la Descripción general del desarrollo avanzado de Android.

Introducción

Crear apps con Google Maps te permite agregar funciones a tu app, como imágenes satelitales, controles de IU sólidos, seguimiento de ubicación y marcadores de ubicación. Puedes agregar valor a Google Maps estándar mostrando información de tu propio conjunto de datos, como las ubicaciones de áreas de pesca o escalada conocidas. También puedes crear juegos vinculados al mundo real, como Pokémon Go.

En esta práctica, crearás una app de Google Maps llamada Wander.

Conocimientos que ya deberías tener

Debes estar familiarizado con lo siguiente:

  • Funcionalidad básica de Google Maps
  • Permisos de tiempo de ejecución.
  • Creación, compilación y ejecución de apps en Android Studio
  • Incluir bibliotecas externas en el archivo build.gradle.

Qué aprenderás

  • Integra un mapa de Google Maps en tu app.
  • Muestra diferentes tipos de mapas.
  • Aplica diseño al mapa de Google Maps.
  • Agrega marcadores a tu mapa.
  • Permite que el usuario coloque un marcador en un lugar de interés.
  • Habilita el seguimiento de la ubicación.
  • Habilita Google Street View.

Actividades

  • Obtén una clave de API en la Consola de APIs de Google y regístrala en tu app.
  • Crea la app de Wander, que tiene un mapa de Google incorporado.
  • Agrega funciones personalizadas a tu app, como marcadores, estilos y seguimiento de ubicación.
  • Habilita el seguimiento de ubicación y Street View en tu app.

2. Descripción general de la app

En esta práctica, crearás la app de Wander, que es un mapa de Google Maps con estilo. La app de Wander te permite colocar marcadores en diferentes ubicaciones, ver tu ubicación en tiempo real y ver panorámicas de Street View.

Un mapa de Google con diseños

Google Street View en una app para Android

3. Tarea 1: Configura el proyecto y obtén una clave de API

La API de Google Maps, al igual que la API de Places, requiere una clave de API. Para obtener la clave de API, registra tu proyecto en la Consola de APIs de Google. La clave de API está vinculada a un certificado digital que vincula la app con su autor. Para obtener más información acerca del uso de certificados digitales y la firma de tu app, consulta Firma tu app.

En esta práctica, usarás la clave de API para el certificado de depuración. El certificado de depuración tiene un diseño inseguro, como se describe en Cómo firmar tu compilación de depuración. Las aplicaciones para Android publicadas que usan la API de Google Maps requieren una segunda clave de API: la clave para el certificado de lanzamiento. Para conocer más detalles sobre cómo obtener un certificado de lanzamiento, consulta Cómo obtener una clave de API.

Android Studio incluye una plantilla de actividad de Google Maps, que genera un código de plantilla útil. El código de la plantilla incluye un archivo google_maps_api.xml con un vínculo que simplifica la obtención de una clave de API.

1.1 Crea el proyecto Wander con la plantilla de Maps

  1. Crea un nuevo proyecto de Android Studio.
  2. Asigna el nombre "Wander" a la app nueva. Acepta los valores predeterminados hasta que llegues a la página Add an Activity.
  3. Selecciona la plantilla Google Maps Activity.
  4. Deja los valores predeterminados de Activity Name y Layout Name.
  5. Cambia el Título a "Wander". y haz clic en Finish.

Android Studio crea varios archivos adicionales relacionados con mapas:

google_maps_api**.xml**

Usa este archivo de configuración para conservar tu clave de API. La plantilla genera dos archivos google_maps_api.xml: uno para la depuración y otro para el lanzamiento. El archivo de la clave de API para el certificado de depuración se encuentra en src/debug/res/values. El archivo de la clave de API para el certificado de lanzamiento se encuentra en src/release/res/values. En esta práctica, solo usamos el certificado de depuración.

activity_maps.xml

Este archivo de diseño contiene un solo fragmento que ocupa toda la pantalla. La clase SupportMapFragment es una subclase de la clase Fragment. Puedes incluir SupportMapFragment en un archivo de diseño con una etiqueta <fragment> en cualquier ViewGroup, con un atributo adicional:

android:name="com.google.android.gms.maps.SupportMapFragment"

MapsActivity.java

El archivo MapsActivity.java crea una instancia de la clase SupportMapFragment y usa el método getMapAsync() de la clase para preparar el mapa de Google Maps. La actividad que contiene el SupportMapFragment debe implementar la interfaz de OnMapReadyCallback y el método onMapReady() de esa interfaz. El método getMapAsync() muestra un objeto GoogleMap, lo que indica que se cargó el mapa.

1.2 Cómo obtener la clave de API

  1. Abre la versión de depuración del archivo google_maps_api.xml.

El archivo incluye un comentario con una URL extensa. Los parámetros de la URL incluyen información específica sobre tu app.

  1. Copia y pega la URL en un navegador.
  2. Sigue las indicaciones para crear un proyecto en la Consola de APIs de Google. Debido a los parámetros de la URL proporcionada, la Consola de API sabe que debe habilitar automáticamente la API de Google Maps para Android.
  3. Crea una clave de API y haz clic en Restringir clave para restringir el uso de la clave a las apps para Android. La clave de API generada debe comenzar con AIza.
  4. En el archivo google_maps_api.xml, pega la clave en la cadena google_maps_key, donde dice YOUR_KEY_HERE.
  5. Ejecuta tu app. Tienes un mapa incorporado en tu actividad con un marcador establecido en Sídney, Australia. (El marcador Sídney es parte de la plantilla y podrás cambiarlo más adelante).

4. Tarea 2: Agrega tipos de mapas y marcadores

Google Maps incluye varios tipos de mapas: normales, híbridos, satelitales, de terreno y "ninguno". En esta tarea, agregarás una barra de la app con un menú de opciones que le permite al usuario cambiar el tipo de mapa. Mueve la ubicación de partida del mapa a la de tu casa. A continuación, agregarás compatibilidad con marcadores, que indican ubicaciones únicas en un mapa y pueden incluir una etiqueta.

2.1 Agrega tipos de mapas

El tipo de mapa que desea el usuario depende del tipo de información que necesite. Cuando utilizas mapas para navegar en tu automóvil, resulta útil ver los nombres de las calles con claridad. Cuando haces senderismo, probablemente te preocupe más cuánto tienes que escalar para llegar a la cima de la montaña. En este paso, agregarás una barra de la app con un menú de opciones que le permite al usuario cambiar el tipo de mapa.

  1. Para crear un archivo XML de menú nuevo, haz clic con el botón derecho en el directorio res y selecciona New > Archivo de recursos de Android.
  2. En el diálogo, asigna el nombre map_options al archivo. Elige Menú para el tipo de recurso. Haz clic en OK.
  3. Reemplaza el código del archivo nuevo por el siguiente para crear las opciones del mapa. El argumento "ninguno" el tipo de mapa se omite porque "ninguno" resulta en la falta de ningún mapa.
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto">
   <item android:id="@+id/normal_map"
       android:title="@string/normal_map"
       app:showAsAction="never"/>
   <item android:id="@+id/hybrid_map"
       android:title="@string/hybrid_map"
       app:showAsAction="never"/>
   <item android:id="@+id/satellite_map"
       android:title="@string/satellite_map"
       app:showAsAction="never"/>
   <item android:id="@+id/terrain_map"
       android:title="@string/terrain_map"
       app:showAsAction="never"/>
</menu>
  1. Crea recursos de cadenas para los atributos title.
  2. En el archivo MapsActivity, cambia la clase para extender la clase AppCompatActivity en lugar de extender la clase FragmentActivity. Si usas AppCompatActivity, se mostrará la barra de la app y, por lo tanto, el menú.
  3. En MapsActivity, anula el método onCreateOptionsMenu() y, luego, aumenta el archivo map_options:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
   MenuInflater inflater = getMenuInflater();
   inflater.inflate(R.menu.map_options, menu);
   return true;
}
  1. Para cambiar el tipo de mapa, utiliza el método setMapType() en el objeto GoogleMap y pasa una de las constantes de tipo de mapa.

Anula el método onOptionsItemSelected(). Pega el siguiente código para cambiar el tipo de mapa cuando el usuario selecciona una de las opciones del menú:

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
       // Change the map type based on the user's selection.
       switch (item.getItemId()) {
           case R.id.normal_map:
               mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
               return true;
           case R.id.hybrid_map:
               mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
               return true;
           case R.id.satellite_map:
               mMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
               return true;
           case R.id.terrain_map:
               mMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
               return true;
           default:
               return super.onOptionsItemSelected(item);
       }
    }
  1. Ejecuta la app. Usa el menú de la barra de la aplicación para cambiar el tipo de mapa. Observa cómo cambia la apariencia del mapa.

2.2 Mueve la ubicación predeterminada del mapa

De forma predeterminada, la devolución de llamada onMapReady() incluye el código que coloca un marcador en Sídney, Australia, donde se creó Google Maps. La devolución de llamada predeterminada también anima el mapa para que se desplaza lateralmente a Sídney. En este paso, harás que el mapa se desplace hasta la ubicación de tu casa sin colocar un marcador y, luego, aplicarás zoom al nivel que especifiques.

  1. En el método onMapReady(), quita el código que coloca el marcador en Sídney y mueve la cámara.
  2. Ve a www.google.com/maps en tu navegador y encuentra tu dirección particular.
  3. Haz clic con el botón derecho en la ubicación y selecciona ¿Qué hay aquí?

Cerca de la parte inferior de la pantalla, aparece una ventana emergente con información sobre la ubicación, como la latitud y la longitud.

  1. Crea un objeto LatLng nuevo llamado home. En el objeto LatLng, usa las coordenadas que encontraste de Google Maps en el navegador.
  2. Crea una variable float llamada zoom y configúrala en el nivel de zoom inicial que desees. La siguiente lista te brinda una idea del nivel de detalle que muestra cada nivel de zoom:
  • 1: Mundo
  • 5: Tierra firme y continente
  • 10: Ciudad
  • 15: Calles
  • 20: Edificios
  1. Crea un objeto CameraUpdate con CameraUpdateFactory.newLatLngZoom() y pasa el objeto LatLng y la variable zoom. Para hacer zoom en la cámara y hacer zoom, llama a moveCamera() en el objeto GoogleMap y pasa el nuevo objeto CameraUpdate:
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(home, zoom));
  1. Ejecuta la app. El mapa debería desplazarse lateralmente hasta tu casa y acercar el mapa al nivel que desees.

2.3 Cómo agregar marcadores de mapa

Google Maps puede seleccionar una ubicación mediante un marcador, que creas con la clase Marker. El marcador predeterminado utiliza el ícono estándar de Google Maps: Marcador de Google Maps.

Puedes extender los marcadores para mostrar información contextual en ventanas de información.

En este paso, se agrega un marcador cuando el usuario toca y mantiene una ubicación en el mapa. Luego, agrega una InfoWindow que muestre las coordenadas del marcador cuando se lo presiona.

Ventana de información para un marcador colocado

  1. Crea un stub de método en MapsActivity llamado setMapLongClick() que tome un final GoogleMap como argumento y muestre void:
private void setMapLongClick(final GoogleMap map) {}
  1. Usa el método setOnMapLongClickListener() del objeto GoogleMap para colocar un marcador en el lugar donde el usuario lo toca y mantiene presionado. Pasa una instancia nueva de OnMapLongClickListener que anule el método onMapLongClick(). El argumento entrante es un objeto LatLng que contiene las coordenadas de la ubicación que presionó el usuario:
private void setMapLongClick(final GoogleMap map) {
   map.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() {
       @Override
       public void onMapLongClick(LatLng latLng) {
       }
   });
}
  1. Dentro de onMapLongClick(), llama al método addMarker(). Pasa un objeto MarkerOptions nuevo con la posición establecida en el LatLng pasado:
map.addMarker(new MarkerOptions().position(latLng));
  1. Llama a setMapLongClick() al final del método onMapReady(). Pasa mMap.
  2. Ejecuta la app. Mantén presionado el mapa para colocar un marcador en una ubicación.
  3. Presiona el marcador, que lo centra en la pantalla.

Los botones de navegación aparecen en la parte inferior izquierda de la pantalla, lo que permite al usuario utilizar la app de Google Maps para navegar a la posición marcada.

Para agregar una ventana de información para el marcador, sigue estos pasos:

  1. En el objeto MarkerOptions, configura los campos title y snippet.
  2. En onMapLongClick(), establece el campo title como "Pin colocado". Establece el campo snippet en las coordenadas de la ubicación dentro del método addMarker().
map.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() {
   @Override
   public void onMapLongClick(LatLng latLng) {
       String snippet = String.format(Locale.getDefault(),
               "Lat: %1$.5f, Long: %2$.5f",
               latLng.latitude,
               latLng.longitude);

       map.addMarker(new MarkerOptions()
               .position(latLng)
               .title(getString(R.string.dropped_pin))
               .snippet(snippet));
   }
});
  1. Ejecuta la app. Para colocar un marcador de ubicación, mantenlo presionado en el mapa. Presiona el marcador para que aparezca la ventana de información.

2.4 Cómo agregar objetos de escucha de lugares de interés

De forma predeterminada, los lugares de interés aparecen en el mapa junto con sus íconos correspondientes. Los lugares de interés incluyen parques, escuelas, edificios gubernamentales y mucho más. Cuando el tipo de mapa se establece en normal, también aparecen en el mapa los lugares de interés comerciales. Estos representan a empresas como tiendas, restaurantes y hoteles.

En este paso, agregarás un objeto GoogleMap.OnPoiClickListener al mapa. Este objeto de escucha de clics coloca un marcador en el mapa de forma inmediata, en lugar de esperar que lo toquen. en espera. El objeto de escucha de clics también muestra la ventana de información que contiene el nombre del lugar de interés.

Marcador de lugar de interés

  1. Crea un stub de método en MapsActivity llamado setPoiClick() que tome un final GoogleMap como argumento y muestre void:
private void setPoiClick(final GoogleMap map) {}
  1. En el método setPoiClick(), configura un OnPoiClickListener en el GoogleMap pasado:
map.setOnPoiClickListener(new GoogleMap.OnPoiClickListener() {
   @Override
   public void onPoiClick(PointOfInterest poi) {
   }
});
  1. En el método onPoiClick(), coloca un marcador en la ubicación del lugar de interés. Establece el título con el nombre del lugar de interés. Guarda el resultado en una variable llamada poiMarker.
public void onPoiClick(PointOfInterest poi) {
   Marker poiMarker = mMap.addMarker(new MarkerOptions()
       .position(poi.latLng)
       .title(poi.name);
}
  1. Llama a showInfoWindow() en poiMarker para que se muestre de inmediato la ventana de información.
poiMarker.showInfoWindow();
  1. Llama a setPoiClick() al final de onMapReady(). Pasa mMap.
  2. Ejecuta tu app y busca un lugar de interés, como un parque. Presiona el lugar de interés para colocarle un marcador y mostrar su nombre en una ventana de información.

5. Tarea 3: Elige un estilo para tu mapa

Puedes personalizar Google Maps de muchas formas para darle a tu mapa un aspecto único.

Puedes personalizar un objeto MapFragment con los atributos XML disponibles, como lo harías con cualquier otro fragmento. Sin embargo, en este paso, personalizarás la apariencia del contenido de MapFragment mediante métodos en el objeto GoogleMap. Puedes utilizar el Asistente de diseño en línea para agregar un diseño a tu mapa y personalizar tus marcadores. También agregarás un objeto GroundOverlay a la ubicación de tu casa que se ajuste y rote con el mapa.

3.1 Cómo agregar un diseño al mapa

Para crear un diseño personalizado para tu mapa, debes generar un archivo JSON que especifique cómo se muestran los componentes del mapa.No es necesario que crees este archivo manualmente, ya que Google proporciona el Asistente de diseño, que genera el archivo JSON después de que aplicas diseño visual en el mapa. En esta práctica, diseñarás el mapa para el "modo nocturno", lo que significa que el mapa usa colores tenues y un contraste bajo para su uso por la noche.

  1. Navega a https://mapstyle.withgoogle.com/ en tu navegador.
  2. Selecciona Crear un diseño.
  3. Selecciona el tema Noche.
  4. Haz clic en Más opciones en la parte inferior del menú.
  5. En la parte inferior de la lista Tipo de componente, selecciona Agua > Relleno. Cambia el color del agua a azul oscuro (por ejemplo, #160064).
  6. Haz clic en Finalizar. Copia el código JSON de la ventana emergente que aparecerá.
  7. En Android Studio, crea un directorio de recursos llamado raw en el directorio res. Crea un archivo en res/raw llamado map_style.json.
  8. Pega el código JSON en el archivo de recursos nuevo.
  9. Para establecer el diseño JSON en el mapa, llama a setMapStyle() en el objeto GoogleMap. Pasa un objeto MapStyleOptions, que carga el archivo JSON. El método setMapStyle() muestra un valor booleano que indica el éxito del diseño. Si no se puede cargar, el método arroja una Resources.NotFoundException.

Copia el siguiente código en el método onMapReady() para definir el diseño del mapa. Es posible que debas crear una cadena TAG para tus instrucciones de registro:

     try {
        // Customize the styling of the base map using a JSON object defined
        // in a raw resource file.
        boolean success = googleMap.setMapStyle(
           MapStyleOptions.loadRawResourceStyle(
                   this, R.raw.map_style));

        if (!success) {
            Log.e(TAG, "Style parsing failed.");
        }
     } catch (Resources.NotFoundException e) {
        Log.e(TAG, "Can't find style. Error: ", e);
     }
  1. Ejecuta tu app. El nuevo diseño debería mostrarse cuando el mapa esté en el modo normal.

Google Maps en modo nocturno

3.2 Cómo cambiar el estilo del marcador

Puedes aplicar diseño a los marcadores del mapa para personalizar aún más tu mapa. En este paso, cambiarás los marcadores rojos predeterminados para que coincidan con el esquema de colores del modo nocturno.

  1. En el método onMapLongClick(), agrega la siguiente línea de código al constructor MarkerOptions() para usar el marcador predeterminado, pero cambiar el color a azul:
.icon(BitmapDescriptorFactory.defaultMarker
       (BitmapDescriptorFactory.HUE_BLUE))
  1. Ejecuta la app. Los marcadores que coloques ahora tendrán una sombra de color azul, lo que es más coherente con el tema del modo nocturno de la app.

Ten en cuenta que los marcadores de lugares de interés siguen siendo rojos porque no agregaste un diseño al método onPoiClick().

3.3 Cómo agregar una superposición

Una forma de personalizar el mapa de Google Maps es dibujar sobre él. Esta técnica es útil si quieres destacar un tipo de ubicación en particular, como puntos de pesca populares. Se admiten tres tipos de superposiciones:

  • Formas: Puedes agregar polilíneas, polígonos y círculos al mapa.
  • Objetos TileOverlay: Una superposición de mosaicos define un conjunto de imágenes que se agregan sobre los mosaicos del mapa base. Las superposiciones de mosaicos son útiles cuando deseas agregar muchas imágenes al mapa. Una superposición de mosaicos típica abarca un área geográfica extensa.
  • Objetos GroundOverlay: Una superposición de suelo es una imagen que se fija a un mapa. A diferencia de los marcadores, las superposiciones de suelo se orientan a la superficie de la Tierra y no a la pantalla. La rotación, la inclinación o el zoom del mapa cambian la orientación de la imagen. Las superposiciones de suelo resultan útiles cuando deseas fijar una sola imagen en un área del mapa.

En este paso, agregarás una superposición de suelo con forma de Android a la ubicación de tu casa.

  1. Descarga esta imagen de Android y guárdala en la carpeta res/drawable.
  2. En onMapReady(), después de la llamada para mover la cámara a la posición inicial, crea un objeto GroundOverlayOptions. Asigna el objeto a una variable llamada homeOverlay:
GroundOverlayOptions homeOverlay = new GroundOverlayOptions();
  1. Usa el método BitmapDescriptorFactory.fromResource() para crear un objeto BitmapDescriptor a partir de la imagen anterior. Pasa el objeto al método image() del objeto GroundOverlayOptions:
GroundOverlayOptions homeOverlay = new GroundOverlayOptions()
    .image(BitmapDescriptorFactory.fromResource(R.drawable.android));
  1. Configura la propiedad position para el objeto GroundOverlayOptions llamando al método position(). Pasa el objeto LatLng de home y una float para el ancho en metros de la superposición deseada. Para este ejemplo, un ancho de 100 m funciona bien:
GroundOverlayOptions homeOverlay = new GroundOverlayOptions()
     .image(BitmapDescriptorFactory.fromResource(R.drawable.android))
       .position(home, 100);
  1. Llama a addGroundOverlay() en el objeto GoogleMap. Pasa tu objeto GroundOverlayOptions:
mMap.addGroundOverlay(homeOverlay);
  1. Ejecuta la app. Acerca la ubicación de tu casa y verás la imagen de Android como una superposición.

6. Tarea 4: Habilitar el seguimiento de la ubicación y Street View

A menudo, los usuarios utilizan Google Maps para ver su ubicación actual. Puedes obtener la ubicación del dispositivo con la API de Location Services. Para mostrar la ubicación del dispositivo en el mapa sin usar más datos de Location, puedes usar la capa de datos de ubicación.

La capa de datos de ubicación agrega el botón Mi ubicación en la parte superior derecha del mapa. Cuando el usuario presiona el botón, el mapa se centra en la ubicación del dispositivo. La ubicación se muestra como un punto azul si el dispositivo está quieto y como un corchete angular azul si el dispositivo está en movimiento.

Un mapa de Google Maps con diseño y funciones de seguimiento de la ubicación

Puedes proporcionar información adicional sobre una ubicación usando Google Street View, que es una foto panorámica navegable de una ubicación determinada.

En esta tarea, habilitarás la capa de datos de ubicación y Street View para que, cuando el usuario presione la ventana de información del marcador de lugares de interés, el mapa entre en el modo Street View.

4.1 Habilita el seguimiento de la ubicación

Para habilitar el seguimiento de ubicación en Google Maps, se necesita una sola línea de código. Sin embargo, debes asegurarte de que el usuario haya otorgado permisos de ubicación (con el modelo de permisos de tiempo de ejecución).

En este paso, debes solicitar permisos de ubicación y habilitar el seguimiento de ubicación.

  1. En el archivo AndroidManifest.xml, verifica que el permiso FINE_LOCATION ya esté presente. Android Studio insertó este permiso cuando seleccionaste la plantilla de Google Maps.
  2. Para habilitar el seguimiento de ubicación en tu app, crea un método en MapsActivity llamado enableMyLocation() que no tome argumentos ni devuelva nada.
  3. Define el método enableMyLocation(). Verifica el permiso ACCESS_FINE_LOCATION. Si se otorga el permiso, habilita la capa de ubicación. De lo contrario, solicita el permiso:
private void enableMyLocation() {
   if (ContextCompat.checkSelfPermission(this,
           Manifest.permission.ACCESS_FINE_LOCATION)
           == PackageManager.PERMISSION_GRANTED) {
       mMap.setMyLocationEnabled(true);
   } else {
       ActivityCompat.requestPermissions(this, new String[]
                       {Manifest.permission.ACCESS_FINE_LOCATION},
               REQUEST_LOCATION_PERMISSION);
   }
}
  1. Llama a enableMyLocation() desde la devolución de llamada onMapReady() para habilitar la capa de ubicación.
  2. Anula el método onRequestPermissionsResult(). Si se otorga el permiso, llama a enableMyLocation():
@Override
public void onRequestPermissionsResult(int requestCode,
       @NonNull String[] permissions,
       @NonNull int[] grantResults) {
   // Check if location permissions are granted and if so enable the
   // location data layer.
   switch (requestCode) {
       case REQUEST_LOCATION_PERMISSION:
           if (grantResults.length > 0
                   && grantResults[0]
                   == PackageManager.PERMISSION_GRANTED) {
               enableMyLocation();
               break;
           }
   }
}
  1. Ejecuta la app. La esquina superior derecha ahora contiene el botón My Location, que muestra la ubicación actual del dispositivo.

4.2 Habilitar Street View

Google Maps ofrece Street View, que es una vista panorámica de una ubicación con controles para navegar por una ruta designada. Street View no tiene cobertura global.

En este paso, habilitas una panorámica de Street View que se activa cuando el usuario presiona la ventana de información de un lugar de interés. Debes seguir dos pasos:

  1. Distingue los marcadores de lugares de interés de otros marcadores, ya que quieres que la funcionalidad de tu app funcione solo en los marcadores de lugares de interés. De esta manera, puedes iniciar Street View cuando el usuario presiona una ventana de información de lugares de interés, pero no cuando presiona cualquier otro tipo de marcador.

La clase Marker incluye un método setTag() que te permite adjuntar datos. (los datos pueden ser cualquier cosa que se extienda desde Object). Establecerás una etiqueta en los marcadores que se crean cuando los usuarios hacen clic en un lugar de interés.

  1. Cuando el usuario presione una ventana de información etiquetada en una OnInfoWindowClickListener, reemplaza MapFragment por StreetViewPanoramaFragment. (El siguiente código usa SupportMapFragment y SupportStreetViewPanoramaFragment para admitir versiones de Android anteriores a la API 12).

Si alguno de los fragmentos cambia durante el tiempo de ejecución, debes agregarlos en la clase Activity que los contiene y no de forma estática en XML.

Cómo etiquetar el marcador de lugares de interés

  1. En la devolución de llamada onPoiClick(), llama a setTag() en poiMarker. Pasa cualquier cadena arbitraria:
poiMarker.setTag("poi");

Reemplaza el SupportMapFragment estático con una instancia de tiempo de ejecución

  1. Abre activity_maps.xml y cambia el elemento a un diseño de marco que sirva como contenedor para tus fragmentos:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:id="@+id/fragment_container"
   android:layout_width="match_parent"
   android:layout_height="match_parent" />
  1. En onCreate(), en MapsActivity, quita el código que encuentra el SupportMapFragment por ID, porque ya no hay un SupportMapFragment estático en el XML. En su lugar, crea una nueva instancia de entorno de ejecución de SupportMapFragment llamando a SupportMapFragment.newInstance():
SupportMapFragment mapFragment = SupportMapFragment.newInstance();
  1. Agrega el fragmento a FrameLayout usando una transacción de fragmento con el FragmentManager:
getSupportFragmentManager().beginTransaction()
       .add(R.id.fragment_container, mapFragment).commit();
  1. Mantén la línea de código que activa la carga asíncrona del mapa:
mapFragment.getMapAsync(this);

Configura un OnInfoWindowClickListener y verifica la etiqueta del marcador

  1. Crea un stub de método en MapsActivity llamado setInfoWindowClickToPanorama() que tome un GoogleMap como argumento y muestre void:
private void setInfoWindowClickToPanorama(GoogleMap map) {}
  1. Establece un OnInfoWindowClickListener en GoogleMap:
map.setOnInfoWindowClickListener(
       new GoogleMap.OnInfoWindowClickListener() {
           @Override
           public void onInfoWindowClick(Marker marker) {
           }
       });
  1. En el método onInfoWindowClick(), verifica si el marcador contiene la etiqueta de cadena que estableciste en el método onPoiClick():
if (marker.getTag() == "poi") {}

Cómo reemplazar SupportMapFragment con SupportStreetViewPanoramaFragment

  1. Cuando el marcador contenga la etiqueta, especifica la ubicación de la panorámica de Street View con un objeto StreetViewPanoramaOptions. Establece la propiedad position del objeto en la posición del marcador que se pasó:
StreetViewPanoramaOptions options =
       new StreetViewPanoramaOptions().position(
               marker.getPosition());
  1. Crea una instancia nueva de SupportStreetViewPanoramaFragment y pasa el objeto options que creaste:
SupportStreetViewPanoramaFragment streetViewFragment
       = SupportStreetViewPanoramaFragment
       .newInstance(options);
  1. Inicia una transacción de fragmento. Reemplaza el contenido del contenedor del fragmento con el fragmento nuevo, streetViewFragment. Agrega la transacción a la pila de actividades, de modo que cuando presiones Atrás, regreses a SupportMapFragment y no salgas de la app:
getSupportFragmentManager().beginTransaction()
       .replace(R.id.fragment_container,
               streetViewFragment)
       .addToBackStack(null).commit();
  1. Llama a setInfoWindowClickToPanorama(mMap) en onMapReady() después de la llamada a setPoiClick()..
  2. Ejecuta la app. Acerca la imagen a una ciudad que tenga cobertura de Street View, como Mountain View (sede de la sede central de Google), y busca un lugar de interés, como un parque. Presiona el lugar de interés para colocar un marcador y ver la ventana de información. Presiona la ventana de información para ingresar al modo Street View correspondiente a la ubicación del marcador. Presiona el botón Atrás para volver al fragmento de mapa.

Google Street View en una app para Android

7. Código de solución

Código de solución de Wander.

8. Desafío de programación

Desafío: Si presionas la ventana de información de un lugar de interés en una ubicación sin cobertura de Street View, verás una pantalla negra.

9. Resumen

  • Para usar la API de Google Maps, necesitas una clave de API de la Consola de APIs de Google.
  • En Android Studio, el uso de la plantilla de actividad de Google Maps genera un Activity con un solo SupportMapFragment en el diseño de la app. La plantilla también agrega el ACCESS_FINE_PERMISSION al manifiesto de la app, implementa el OnMapReadyCallback en tu actividad y anula el método onMapReady() requerido.

Para cambiar el tipo de mapa de una GoogleMap durante el tiempo de ejecución, usa el método GoogleMap.setMapType(). Un mapa de Google Maps puede ser uno de los siguientes tipos de mapas:

  • Normal: Mapa de ruta típico Muestra rutas, algunas características creadas por el hombre y características naturales importantes, como ríos. También muestra etiquetas de rutas y características.
  • Híbrido: Muestra datos de fotos satelitales con mapas de rutas agregados. También muestra etiquetas de rutas y características.
  • Satélite: Muestra los datos de las fotografías. No se ven etiquetas de carreteras y elementos.
  • Terreno: Datos topográficos. El mapa incluye colores, líneas de contorno y etiquetas, y sombras de perspectiva. También muestra algunas rutas y etiquetas.
  • Ninguna**:** No hay un mapa.

Acerca de Google Maps:

  • Un marcador es un indicador de una ubicación geográfica específica.
  • Cuando el marcador se presiona, el comportamiento predeterminado consiste en mostrar una ventana de información con datos sobre la ubicación.
  • De forma predeterminada, los puntos de interés (POI) aparecen en el mapa básico con sus íconos correspondientes. Los lugares de interés incluyen parques, escuelas, edificios gubernamentales y mucho más.
  • Además, los lugares de interés comerciales (tiendas, restaurantes, hoteles, etc.) aparecen de forma predeterminada en el mapa cuando el tipo de mapa es normal.
  • Puedes capturar clics en los lugares de interés con el ícono OnPoiClickListener.
  • Puedes cambiar la apariencia visual de casi todos los elementos de un mapa de Google Maps con el Asistente de diseño. El asistente de diseño genera un archivo JSON que se pasa al mapa de Google Maps con el método setMapStyle().
  • Si deseas personalizar los marcadores, puedes cambiar el color predeterminado o reemplazar el ícono predeterminado por una imagen personalizada.

Otra información importante:

  • Usa una superposición de suelo para fijar una imagen a una ubicación geográfica.
  • Usa un objeto GroundOverlayOptions para especificar la imagen, su tamaño en metros y su posición. Pasa este objeto al método GoogleMap.addGroundOverlay() para establecer la superposición en el mapa.
  • Siempre que la app tenga el permiso ACCESS_FINE_LOCATION, puedes habilitar el seguimiento de la ubicación con el método mMap.setMyLocationEnabled(true).
  • Google Street View proporciona vistas panorámicas de 360 grados de rutas designadas en su área de cobertura.
  • Utiliza el método StreetViewPanoramaFragment.newInstance() para crear un nuevo fragmento de Street View.
  • Para especificar las opciones de la vista, usa un objeto StreetViewPanoramaOptions. Pasa el objeto al método newInstance().

10. Más información

La documentación de conceptos relacionados se encuentra en 9.1: API de Google Maps.

Documentación para desarrolladores de Android:

Documentación de referencia:

11. Tarea

En esta sección, se enumeran las posibles actividades para el hogar para los alumnos que trabajan en este codelab como parte de un curso dirigido por un instructor. Depende del instructor hacer lo siguiente:

  • Si es necesario, asigna una tarea.
  • Comunicarles a los alumnos cómo enviar las actividades para el hogar.
  • Califica las actividades para el hogar.

Los instructores pueden usar estas sugerencias en la medida que quieran y deben asignar cualquier otra actividad para el hogar que consideren apropiada.

Si estás trabajando en este codelab por tu cuenta, usa estas actividades para el hogar para probar tus conocimientos.

Compila y ejecuta una app

  1. Crea una app nueva que use la plantilla de actividad de Google Maps, que carga Google Maps cuando se inicia la app.
  2. Una vez cargado el mapa de Google Maps, mueve la cámara a la ubicación de tu escuela, de tu casa o de alguna otra ubicación que tenga un significado para ti.
  3. Agrega dos marcadores al mapa: uno en la ubicación de tu escuela y otro en tu casa u otra ubicación significativa.
  4. Para personalizar los íconos de los marcadores, cambia el color predeterminado o reemplaza el ícono predeterminado por una imagen personalizada.

Pista: Consulta la documentación de onMapReady (GoogleMap googleMap).

Responde estas preguntas:

Pregunta 1

¿A qué método se llama cuando el mapa se carga y está listo para usarse en la app?

Pregunta 2

¿Qué componentes de Android puedes usar para incluir Google Maps en tu app?

  • MapView y MapFragment
  • MapFragment y MapActivity
  • MapView y MapActivity
  • Solo MapFragment

Pregunta 3

¿Qué tipos de mapas ofrece la Google Maps Android API?

  • Normal, híbrido, terreno, satélite y hoja de ruta
  • Normal, híbrido, terreno, satélite y "ninguno"
  • Híbrido, terreno, satélite, hoja de ruta y “ninguno”
  • Normal, terreno, satélite, mapa de imagen y "ninguno"

Pregunta 4

¿Qué interfaz implementas para agregar la funcionalidad de clic en un lugar de interés?

  • GoogleMap.OnPoiListener
  • GoogleMap.OnPoiClickListener
  • GoogleMap.OnPoiClick
  • GoogleMap.OnPoiClicked

Envía tu app para que se la califique

Orientación para calificadores

Verifica que la app tenga las siguientes funciones:

  • Cuando se inicia la app, se muestra correctamente el mapa de Google Maps, lo que indica que se generó correctamente una clave de API.
  • Una vez cargado el mapa de Google Maps, la cámara se mueve a la ubicación de la casa o de la escuela del estudiante. En el código, este paso debe ocurrir en el método de devolución de llamada onMapReady (GoogleMap googleMap).
  • Los marcadores se muestran en la ubicación de la escuela del estudiante y en otra ubicación, como la casa del estudiante.
  • Los dos marcadores están personalizados. Por ejemplo, los marcadores usan un color distinto del rojo predeterminado o usan un ícono personalizado.

12. Próximo codelab

Para ver todos los codelabs del curso de capacitación Desarrollo avanzado de Android, visita la página de destino de Codelabs de Desarrollo avanzado de Android.