API de Google Maps en Wear OS

Mapa en un dispositivo wearable

Con el SDK de Maps para Android, puedes crear una app para wearables basada en mapas que se ejecute directamente en dispositivos Wear OS by Google. Los usuarios de tu app pueden ver su ubicación en el mapa con solo dar un vistazo a sus pulseras. Pueden representar su posición en una ruta, por ejemplo, y luego acercar el mapa para obtener más detalles, o presionar un marcador a fin de ver una ventana de información que proporcione tu app.

En esta página, se describe la funcionalidad de API disponible en un dispositivo para Wear y se brinda información que te ayudará para comenzar a crear tu app.

Cómo comenzar a usar Wear OS

Compilar una app para wearables con el SDK de Maps para Android es básicamente lo mismo que compilar una app de GoogleMaps para cualquier otro dispositivo Android. La diferencia recae en el diseño que realices para el factor de forma más pequeño del dispositivo wearable, a fin de optimizar la usabilidad y el rendimiento de la app.

Android Studio es la herramienta recomendada para el desarrollo de Wear OS, ya que proporciona elementos prácticos de configuración de proyectos, inclusión de bibliotecas y empaquetado.

Si deseas obtener ayuda en general con el diseño de una app para wearables, consulta los lineamientos de diseño para Wear OS. Si deseas obtener ayuda con la creación de tu primera app para wearables, consulta la guía sobre cómo crear apps para wearables.

Cómo compilar tu primera app de mapas en Wear OS

En esta guía rápida, se presupone que estás familiarizado con el SDK de Maps para Android, que seguiste las guías de Wear OS a fin de crear un módulo para wearables en tu app y que deseas agregar un mapa al módulo para wearables.

Cómo agregar dependencias para tu módulo de Wear OS

Asegúrate de que se incluyan las siguientes dependencias en el archivo build.gradle del módulo de Wear OS de tu app:

dependencies {
    // ...
    compileOnly 'com.google.android.wearable:wearable:2.9.0'
    implementation 'com.google.android.support:wearable:2.9.0'
    implementation 'com.google.android.gms:play-services-maps:18.1.0'

    // This dependency is necessary for ambient mode
    implementation 'androidx.wear:wear:1.2.0'
}

Para obtener más información sobre las dependencias, consulta la guía Cómo agregar un módulo de Wear OS en un proyecto existente.

Cómo implementar un gesto de deslizar para descartar y establecer el color de fondo inicial

Se recomienda usar una clase SwipeDismissFrameLayout para mostrar el mapa en el dispositivo wearable. Con la clase SwipeDismissFrameLayout, puedes implementar el gesto de deslizar para descartar, así los usuarios podrán salir de la app deslizando el dedo desde el borde izquierdo de la pantalla.

Para establecer un color de fondo inicial personalizado, usa el atributo XML map:backgroundColor para definir el color que se mostrará hasta que se carguen los mosaicos de mapas reales.

Agrega los elementos SwipeDismissFrameLayout y backgroundColor a tu definición de diseño como contenedor de SupportMapFragment:

  <androidx.wear.widget.SwipeDismissFrameLayout
      android:id="@+id/map_container"
      android:layout_width="match_parent"
      android:layout_height="match_parent">
    <fragment
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        map:backgroundColor="#fff0b2dd" />
  </androidx.wear.widget.SwipeDismissFrameLayout>

Cuando incluyas el objeto SwipeDismissFrameLayout en tu actividad, agrega una devolución de llamada y configura su comportamiento para que realice la acción de descarte necesaria, tal como se muestra a continuación:

Java


public class MainActivity extends AppCompatActivity implements OnMapReadyCallback,
    AmbientModeSupport.AmbientCallbackProvider {

    public void onCreate(Bundle savedState) {
        super.onCreate(savedState);

        // Set the layout. It only contains a SupportMapFragment and a DismissOverlay.
        setContentView(R.layout.activity_main);

        // Enable ambient support, so the map remains visible in simplified, low-color display
        // when the user is no longer actively using the app but the app is still visible on the
        // watch face.
        AmbientModeSupport.AmbientController controller = AmbientModeSupport.attach(this);
        Log.d(MainActivity.class.getSimpleName(), "Is ambient enabled: " + controller.isAmbient());

        // Retrieve the containers for the root of the layout and the map. Margins will need to be
        // set on them to account for the system window insets.
        final SwipeDismissFrameLayout mapFrameLayout = (SwipeDismissFrameLayout) findViewById(
            R.id.map_container);
        mapFrameLayout.addCallback(new SwipeDismissFrameLayout.Callback() {
            @Override
            public void onDismissed(SwipeDismissFrameLayout layout) {
                onBackPressed();
            }
        });

        // Obtain the MapFragment and set the async listener to be notified when the map is ready.
        mapFragment = (SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    // ...
}

      

Kotlin


class MainActivity : AppCompatActivity(), OnMapReadyCallback,
                     AmbientModeSupport.AmbientCallbackProvider {

    public override fun onCreate(savedState: Bundle?) {
        super.onCreate(savedState)

        // Set the layout. It only contains a SupportMapFragment and a DismissOverlay.
        setContentView(R.layout.activity_main)

        // Enable ambient support, so the map remains visible in simplified, low-color display
        // when the user is no longer actively using the app but the app is still visible on the
        // watch face.
        val controller = AmbientModeSupport.attach(this)
        Log.d(MainActivity::class.java.simpleName, "Is ambient enabled: " + controller.isAmbient)

        // Retrieve the containers for the root of the layout and the map. Margins will need to be
        // set on them to account for the system window insets.
        val mapFrameLayout = findViewById<SwipeDismissFrameLayout>(R.id.map_container)
        mapFrameLayout.addCallback(object : SwipeDismissFrameLayout.Callback() {
            override fun onDismissed(layout: SwipeDismissFrameLayout) {
                onBackPressed()
            }
        })

        // Obtain the MapFragment and set the async listener to be notified when the map is ready.
        mapFragment = supportFragmentManager
            .findFragmentById(R.id.map) as SupportMapFragment
        mapFragment.getMapAsync(this)
    }

    // ...
}

      

Cómo agregar un mapa

Usa el método de devolución de llamada onMapReady(GoogleMap) como de costumbre a fin de generar un controlador para el objeto GoogleMap. La devolución de llamada se activa cuando el mapa está listo para utilizarse. En el método de devolución de llamada, puedes agregar marcadores o polilíneas al mapa, agregar objetos de escucha o mover la cámara. En el siguiente ejemplo se agrega un marcador cerca de la Ópera de Sydney:

Java


private static final LatLng SYDNEY = new LatLng(-33.85704, 151.21522);

@Override
public void onMapReady(@NonNull GoogleMap googleMap) {
    // Add a marker with a title that is shown in its info window.
    googleMap.addMarker(new MarkerOptions().position(SYDNEY)
        .title("Sydney Opera House"));

    // Move the camera to show the marker.
    googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(SYDNEY, 10));
}

      

Kotlin


private val sydney = LatLng(-33.85704, 151.21522)

override fun onMapReady(googleMap: GoogleMap) {
    // Add a marker with a title that is shown in its info window.
    googleMap.addMarker(
        MarkerOptions().position(sydney)
            .title("Sydney Opera House")
    )

    // Move the camera to show the marker.
    googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(sydney, 10f))
}

      

Cómo habilitar el modo ambiente

El SDK de Maps para Android admite el modo ambiente en las apps para wearables. A veces, a las apps que admiten el modo ambiente se las denomina siempre activas. El modo ambiente se activa cuando el usuario deja de usar activamente la app y permite que esta permanezca visible en el dispositivo wearable.

El SDK de Maps para Android proporciona una renderización del mapa simplificada y con bajo contenido de colores para usar en el modo ambiente, y el estilo del mapa se ajusta automáticamente cuando el dispositivo pasa del modo interactivo al modo ambiente. Todos los marcadores, objetos y controles de la IU desaparecen en el modo ambiente. Esto reduce el consumo de energía de tu app y garantiza un aspecto coherente con otras apps de ambiente, como las caras de reloj.

Sigue estos pasos para asegurarte de que tu app use el modo ambiente del mapa:

  1. Actualiza tu SDK de Android para incluir Android 6.0 (API 23) o una plataforma posterior; con esto, se proporcionan las APIs necesarias para que las actividades puedan usar el modo ambiente. Consulta la documentación de Android sobre cómo agregar paquetes del SDK a fin de obtener instrucciones para actualizar el SDK.
  2. Configura targetSdkVersion en 23 o un valor superior en el manifiesto de la app con el fin de asegurarte de que tu proyecto se haya diseñado para Android 6.0 o una versión posterior.
  3. Agrega las dependencias para wearables al archivo build.gradle de tu app. Consulta la muestra de código que se incluye en esta página.
  4. Agrega la entrada de la biblioteca compartida de wearables al manifiesto de la app para wearables, tal como se describe en la clase de capacitación de Android sobre cómo mantener visible tu app.
  5. Agrega el permiso WAKE_LOCK a los manifiestos de la app para dispositivos wearable y de mano, tal como se describe en la clase de capacitación de Android sobre cómo mantener visible tu app.
  6. En el método onCreate() de tu actividad, llama al método AmbientModeSupport.attach(). Con esto se le indica al sistema operativo que la aplicación está siempre activa, de modo que cuando el dispositivo se apaga, debería habilitarse el modo ambiente en lugar de la cara de reloj.
  7. Implementa la interfaz AmbientModeSupport.AmbientCallbackProvider en tu actividad para que pueda recibir los cambios de estado del modo ambiente.
  8. Configura tu mapa para que admita el modo ambiente. Para ello, configura el atributo map:ambientEnabled="true" en el archivo de diseño XML de la actividad o configura GoogleMapOptions.ambientEnabled(true) de forma programática. Esta configuración le indica a la API que debe cargar previamente los mosaicos de mapas necesarios para usarlos en el modo ambiente.
  9. Cuando la actividad pasa al modo ambiente, el sistema llama al método onEnterAmbient() de la devolución de llamada AmbientCallback proporcionada por ti. Anula onEnterAmbient() y llama a SupportMapFragment.onEnterAmbient(ambientDetails) o MapView.onEnterAmbient(ambientDetails). La API pasa a una renderización del mapa no interactiva y con bajo contenido de colores.
  10. Del mismo modo, en onExitAmbient() llama a SupportMapFragment.onExitAmbient() o MapView.onExitAmbient(). La API pasa a la renderización normal del mapa.

La siguiente muestra de código habilita el modo ambiente en la actividad:

Java


public class AmbientActivity extends AppCompatActivity implements
    AmbientModeSupport.AmbientCallbackProvider {

    private SupportMapFragment mapFragment;

    public void onCreate(Bundle savedState) {
        super.onCreate(savedState);

        // Set the layout. It only contains a SupportMapFragment and a DismissOverlay.
        setContentView(R.layout.activity_main);

        // Enable ambient support, so the map remains visible in simplified, low-color display
        // when the user is no longer actively using the app but the app is still visible on the
        // watch face.
        AmbientModeSupport.AmbientController controller = AmbientModeSupport.attach(this);
        Log.d(AmbientActivity.class.getSimpleName(), "Is ambient enabled: " + controller.isAmbient());

        // Obtain the MapFragment and set the async listener to be notified when the map is ready.
        mapFragment = (SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.map);
    }

    @Override
    public AmbientCallback getAmbientCallback() {
        return new AmbientCallback() {
            /**
             * Starts ambient mode on the map.
             * The API swaps to a non-interactive and low-color rendering of the map when the user is no
             * longer actively using the app.
             */
            @Override
            public void onEnterAmbient(Bundle ambientDetails) {
                super.onEnterAmbient(ambientDetails);
                mapFragment.onEnterAmbient(ambientDetails);
            }

            /**
             * Exits ambient mode on the map.
             * The API swaps to the normal rendering of the map when the user starts actively using the app.
             */
            @Override
            public void onExitAmbient() {
                super.onExitAmbient();
                mapFragment.onExitAmbient();
            }
        };
    }
}

      

Kotlin


class AmbientActivity : AppCompatActivity(), AmbientModeSupport.AmbientCallbackProvider {

    private lateinit var mapFragment: SupportMapFragment

    public override fun onCreate(savedState: Bundle?) {
        super.onCreate(savedState)

        // Set the layout. It only contains a SupportMapFragment and a DismissOverlay.
        setContentView(R.layout.activity_main)

        // Enable ambient support, so the map remains visible in simplified, low-color display
        // when the user is no longer actively using the app but the app is still visible on the
        // watch face.
        val controller = AmbientModeSupport.attach(this)
        Log.d(AmbientActivity::class.java.simpleName, "Is ambient enabled: " + controller.isAmbient)

        // Obtain the MapFragment and set the async listener to be notified when the map is ready.
        mapFragment = supportFragmentManager
            .findFragmentById(R.id.map) as SupportMapFragment
    }

    override fun getAmbientCallback(): AmbientModeSupport.AmbientCallback {
        return object : AmbientModeSupport.AmbientCallback() {
            /**
             * Starts ambient mode on the map.
             * The API swaps to a non-interactive and low-color rendering of the map when the user is no
             * longer actively using the app.
             */
            override fun onEnterAmbient(ambientDetails: Bundle) {
                super.onEnterAmbient(ambientDetails)
                mapFragment.onEnterAmbient(ambientDetails)
            }

            /**
             * Exits ambient mode on the map.
             * The API swaps to the normal rendering of the map when the user starts actively using the app.
             */
            override fun onExitAmbient() {
                super.onExitAmbient()
                mapFragment.onExitAmbient()
            }
        }
    }
}

      

Puedes actualizar la pantalla mientras la app se encuentre en el modo ambiente. Para obtener más información sobre la actualización de contenido y el modo ambiente en general, consulta la clase de capacitación de Android sobre cómo mantener visible tu app.

Cómo usar Street View en Wear OS

Street View es totalmente compatible con los dispositivos wearable.

A fin de que los usuarios puedan salir de la app cuando están viendo una panorámica de Street View, usa la interfaz StreetViewPanorama.OnStreetViewPanoramaLongClickListener para escuchar un gesto de clic largo. Cuando un usuario haga clics largos en alguna parte de la imagen de Street View, recibirás un evento onStreetViewPanoramaLongClick(StreetViewPanoramaOrientation). Llama a DismissOverlayView.show() para mostrar un botón de salida.

Código de muestra

Hay una app de muestra disponible en GitHub, que puedes usar como punto de partida para tu app. En este ejemplo, se muestra cómo configurar un mapa base de Google Maps en Wear OS.

Funcionalidad admitida de la API de Google Maps en Wear OS

En esta sección se describen las diferentes funcionalidades para mapas que se admiten en los dispositivos wearable en comparación con los de mano (teléfonos y tablets). Las funciones de API que no se mencionan a continuación deberían funcionar según lo establecido para la API completa.

Funcionalidad
Modo lite y totalmente interactivo

Puedes usar el SDK de Maps para Android en modo completamente interactivo o en modo lite. Considera usar el modo lite si deseas optimizar el rendimiento en el dispositivo wearable. No es necesario que tu app admita aspectos interactivos, como gestos o acciones de desplazamiento lateral y zoom en el mapa.

En el modo lite, el intent para iniciar la app para dispositivos móviles de Google Maps cuando el usuario presiona el mapa está inhabilitado y no puede habilitarse en un dispositivo wearable.

Para obtener una lista completa de las diferencias entre el modo lite y el modo totalmente interactivo, consulta la documentación sobre el modo lite.

Barra de herramientas del mapa La barra de herramientas del mapa está inhabilitada y no se puede habilitar en un dispositivo wearable.
Controles de la IU Los controles de la IU están inhabilitados de forma predeterminada en los dispositivos wearable. Esto incluye los controles de zoom, brújula y Mi ubicación. Puedes habilitarlos mediante la clase UiSettings como lo haces normalmente.
Gestos Los gestos de un solo toque funcionan según lo esperado. Entre los ejemplos se incluyen tocar y arrastrar para desplazar el mapa lateralmente, presionar dos veces para acercarlo y presionar con dos dedos para alejarlo. La compatibilidad varía en el caso de los gestos de varios toques, según el dispositivo del usuario. Entre los ejemplos de gestos de varios toques se incluyen presionar con dos dedos para inclinar el mapa, pellizcarlo para hacer zoom y rotarlo con dos dedos.
Mapas de interiores y edificios Los mapas de interiores están inhabilitados de forma predeterminada en los dispositivos wearable. Para habilitarlos, llama a GoogleMap.setIndoorEnabled(true). Si los mapas de interiores están habilitados, el mapa mostrará el nivel de piso predeterminado. El elemento de la IU del selector de nivel no se admite en los dispositivos wearable.
Superposiciones de mosaicos Las superposiciones de mosaicos no se admiten en los dispositivos wearable.

Prácticas recomendadas de desarrollo con la API de Google Maps en Wear OS

Cómo brindar la mejor experiencia de usuario en tu app:

  • El mapa debe ocupar una proporción amplia de la pantalla. Esto es necesario para optimizar la usabilidad del mapa en el factor de forma pequeño de un dispositivo wearable.
  • Al diseñar la experiencia del usuario de tu app, ten en cuenta que la batería de un dispositivo wearable tiene poca capacidad. Mantener la pantalla activa y el mapa visible afectará el rendimiento de la batería.