Maps API unter Wear OS

Eine Karte auf einem Wearable-Gerät

Mit dem Maps SDK for Android kannst du eine kartenbasierte Wearable-App erstellen, die direkt auf Wear OS by Google-Geräten läuft. So können Nutzer deiner App ihren Standort auf der Karte schon mit einem einfachen Blick auf ihr Handgelenk sehen. Sie können beispielsweise ihre Position auf einer Route nachverfolgen und dann durch Vergrößern der Ansicht Details anzeigen oder durch Tippen auf eine Markierung ein Infofenster deiner App aufrufen.

Auf dieser Seite werden die auf einem Wear-Gerät verfügbaren API-Funktionen und die ersten Schritte zum Erstellen deiner App beschrieben.

Erste Schritte mit Wear OS

Das Erstellen einer Wearable-App mit dem Maps SDK for Android funktioniert im Wesentlichen genauso wie das Erstellen einer Google Maps-App für andere Android-Geräte. Allerdings muss der kleinere Formfaktor des Wearable-Geräts berücksichtigt werden, damit die App dort optimal läuft und bestmöglich genutzt werden kann.

Wir empfehlen Android Studio als Entwicklungsumgebung für Wear OS, weil es die Projektkonfiguration, die Einbindung von Bibliotheken und das Verpacken vereinfacht.

Allgemeine Hilfestellungen zum Entwickeln einer Wearable-App findest du in den Designrichtlinien für Wear OS. Informationen zum Erstellen deiner ersten Wearable-App findest du in der Anleitung Wearable-Apps erstellen.

Erste Karten-App für Wear OS erstellen

In dieser Kurzanleitung wird vorausgesetzt, dass du mit dem Maps SDK for Android vertraut bist, dass du die Wear OS-Anleitungen zum Erstellen eines Wearable-Moduls in deiner App befolgt hast und dass du jetzt eine Karte zum Wearable-Modul hinzufügen möchtest.

Abhängigkeiten für dein Wearable-Modul hinzufügen

Folgende Abhängigkeiten müssen in der Datei build.gradle des Wear OS-Moduls deiner App enthalten sein:

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

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

Weitere Informationen zu den Abhängigkeiten findest du in der englischsprachigen Anleitung zum Hinzufügen eines Wear OS-Moduls zu einem vorhandenen Projekt.

Eine Wischgeste zum Schließen implementieren und die anfängliche Hintergrundfarbe festlegen

Es empfiehlt sich, ein SwipeDismissFrameLayout-Element zu verwenden, um die Karte auf dem Wearable-Gerät darzustellen. Mit der Klasse SwipeDismissFrameLayout kannst du die Wischgeste zum Schließen implementieren, damit Nutzer die App verlassen können, indem sie vom linken Bildschirmrand nach rechts wischen.

Eine benutzerdefinierte anfängliche Hintergrundfarbe lässt sich über das XML-Attribut map:backgroundColor festlegen. Damit bestimmst du die Farbe, die zu sehen ist, bis die tatsächlichen Kartenkacheln geladen werden.

Füge deiner Layoutdefinition die Elemente SwipeDismissFrameLayout und backgroundColor als Container von SupportMapFragment hinzu:

  <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>

Wenn du das SwipeDismissFrameLayout-Objekt in deine Aktivität einbindest, füge einen Callback hinzu und lege sein Verhalten so fest, dass die erforderliche Aktion zum Schließen wie unten gezeigt ausgeführt wird:

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)
    }

    // ...
}

      

Karte hinzufügen

Verwende wie gewohnt die Callback-Methode onMapReady(GoogleMap), um ein Handle zum GoogleMap-Objekt zu erhalten. Der Callback wird ausgelöst, sobald die Karte einsatzbereit ist. In der Callback-Methode kannst du der Karte Markierungen oder Polylinien hinzufügen, Listener ergänzen oder die Kamera verschieben. Im folgenden Beispiel wird eine Markierung in der Nähe des Opernhauses von Sydney hinzugefügt:

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))
}

      

Inaktivmodus aktivieren

Das Maps SDK for Android unterstützt den Inaktivmodus für Wearable-Apps. Apps, die den Inaktivmodus unterstützen, werden auch als Always-On-Apps bezeichnet. Der Inaktivmodus wird aktiviert, wenn der Nutzer die App nicht mehr aktiv verwendet, und sorgt dafür, dass die App weiter auf dem Wearable-Gerät angezeigt wird.

Das Maps SDK for Android ermöglicht ein vereinfachtes Rendern der Karte mit geringer Farbtiefe für die Verwendung im Inaktivmodus, und das Kartenformat wird automatisch angepasst, wenn das Gerät vom interaktiven Modus in den Inaktivmodus wechselt. Alle Markierungen, Objekte und UI-Steuerelemente werden im Inaktivmodus ausgeblendet. Das reduziert den Stromverbrauch deiner App und ermöglicht gleichzeitig ein einheitliches Erscheinungsbild wie bei anderen Apps mit Inaktivitätsdisplay, z. B. bei Zifferblättern.

So kannst du dafür sorgen, dass deine App den Inaktivmodus der Karte verwendet:

  1. Aktualisiere deine Android SDK so, dass dabei die Plattform Android 6.0 (API-Level 23) oder höher eingebunden wird, die die nötigen APIs zum Aufrufen des Inaktivmodus umfasst. Informationen zum Aktualisieren des SDK findest du in der englischsprachigen Android-Dokumentation zum Hinzufügen von SDK-Paketen.
  2. Dein Projekt muss für Android 6.0 oder höher ausgelegt sein. Setze targetSdkVersion dazu im App-Manifest auf 23 oder höher.
  3. Füge der Datei build.gradle deiner App die Wearable-Abhängigkeiten hinzu. Ein Beispiel dafür findest du auf dieser Seite.
  4. Füge den Eintrag der freigegebenen Wearable-Bibliothek dem App-Manifest hinzu, wie im Android-Schulungskurs zum Thema Sicherstellen der Sichtbarkeit der App beschrieben.
  5. Füge dem Handheld- und Wearable-App-Manifest die Berechtigung WAKE_LOCK hinzu, wie im Android-Schulungskurs zum Thema Sicherstellen der Sichtbarkeit der App beschrieben.
  6. Rufe in der Methode onCreate() deiner Aktivität die Methode AmbientModeSupport.attach() auf. Dadurch erhält das Betriebssystem die Information, dass die App immer aktiviert ist. Wenn das Gerät also in den Energiesparmodus übergeht, sollte die App in den Inaktivmodus wechseln und nicht das Zifferblatt auf dem Gerät angezeigt werden.
  7. Implementiere die Schnittstelle AmbientModeSupport.AmbientCallbackProvider in deiner Aktivität, damit sie im Inaktivmodus Statusänderungen empfangen kann.
  8. Konfiguriere deine Karte so, dass sie den Inaktivmodus unterstützt. Dazu kannst du das Attribut map:ambientEnabled="true" in der XML-Layoutdatei der Aktivität definieren oder es programmatisch einrichten, indem du GoogleMapOptions.ambientEnabled(true) angibst. So weiß die API, dass die erforderlichen Kartenkacheln für die Verwendung im Inaktivmodus vorab geladen werden müssen.
  9. Wenn die Aktivität in den Inaktivmodus wechselt, ruft das System die Methode onEnterAmbient() in deinem AmbientCallback auf. Überschreibe onEnterAmbient() und rufe SupportMapFragment.onEnterAmbient(ambientDetails) oder MapView.onEnterAmbient(ambientDetails) auf. Die API wechselt dann zum nicht interaktiven Rendern mit geringer Farbtiefe.
  10. Rufe in onExitAmbient() entsprechend SupportMapFragment.onExitAmbient() oder MapView.onExitAmbient() auf. Die API wechselt zum normalen Rendering der Karte.

Mit dem folgenden Codebeispiel wird der Inaktivmodus in der Aktivität aktiviert:

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()
            }
        }
    }
}

      

Du kannst den Bildschirm aktualisieren, während die App im Inaktivmodus ausgeführt wird. Weitere Informationen zum Aktualisieren von Inhalten und zum Inaktivmodus im Allgemeinen findest du im Android-Schulungskurs zum Sicherstellen der Sichtbarkeit der App.

Street View unter Wear OS verwenden

Street View wird auf Wearable-Geräten vollständig unterstützt.

Um den Nutzern die Möglichkeit zu geben, die App während der Anzeige eines Street View-Panoramas zu beenden, verwende die Schnittstelle StreetViewPanorama.OnStreetViewPanoramaLongClickListener, die auf eine lange Klick-/Tippbewegung reagiert. Wenn ein Nutzer lange auf eine beliebige Stelle des Street View-Bilds klickt/tippt, wird ein onStreetViewPanoramaLongClick(StreetViewPanoramaOrientation)-Ereignis empfangen. Rufe DismissOverlayView.show() auf, um eine Schaltfläche zum Beenden anzuzeigen.

Beispielcode

Auf GitHub ist eine Beispiel-App verfügbar, die du als Ausgangspunkt zum Erstellen einer App verwenden kannst. Aus dem Beispiel geht hervor, wie du eine einfache Google Maps-Karte unter Wear OS konfigurierst.

Unterstützte Funktionen in der Maps API unter Wear OS

In diesem Abschnitt wird beschrieben, wie sich die unterstützten Funktionen für Karten auf Wearable-Geräten einerseits und auf Handheld-Geräten (Smartphones und Tablets) andererseits unterscheiden. Alle API-Funktionen, die nachfolgend nicht aufgeführt sind, sollten wie dokumentiert für die gesamte API funktionieren.

Funktionen
Vollständiger interaktiver Modus und Lite-Modus

Du kannst das Maps SDK for Android im vollständigen interaktiven Modus oder im Lite-Modus verwenden. Der Lite-Modus empfiehlt sich, wenn du die Performance des Wearable-Geräts optimieren möchtest und für deine App Interaktionen wie Gesten oder das Verschieben/Vergrößern von Karten nicht unterstützt werden müssen.

Im Lite-Modus ist der Intent zum Starten der mobilen Google Maps App, wenn der Nutzer auf die Karte tippt, deaktiviert. Er kann auf einem Wearable-Gerät auch nicht aktiviert werden.

Eine vollständige Liste der Unterschiede zwischen dem Lite-Modus und dem interaktiven Modus findest du in der Dokumentation zum Lite-Modus.

Kartensymbolleiste Die Kartensymbolleiste ist deaktiviert und kann auf einem Wearable-Gerät nicht aktiviert werden.
UI-Steuerelemente Die UI-Steuerelemente sind auf Wearable-Geräten standardmäßig deaktiviert. Das gilt für die Steuerelemente für das Zoomen, den Kompass und den eigenen Standort. Um diese zu aktivieren, verwendest du wie gewohnt die UiSettings-Klasse.
Gesten Einfache Touch-Gesten können wie gewohnt verwendet werden. Beispiele: Berühren und Ziehen zum Verschieben der Karte, Doppeltippen zum Vergrößern und Zweifingertippen zum Verkleinern der Karte. Welche Multi-Touch-Gesten unterstützt werden, ist vom jeweiligen Gerät des Nutzers abhängig. Zu den Multi-Touch-Gesten gehören Zweifingerschieben zum Neigen der Karte, Zusammendrücken zum Vergrößern und Zweifingerdrehung.
Indoor-Karten und Gebäude Indoor-Karten sind auf Wearable-Geräten standardmäßig deaktiviert. Du kannst sie aktivieren, indem du GoogleMap.setIndoorEnabled(true) aufrufst. Sind Indoor-Karten aktiviert, wird in der Karte die Standardetage angezeigt. Das UI-Element zur Auswahl der Ebene (Etage) wird auf Wearable-Geräten nicht unterstützt.
Kachel-Overlays Kachel-Overlays werden auf Wearable-Geräten nicht unterstützt.

Best Practices für die Entwicklung mit der Maps API unter Wear OS

So optimierst du das Nutzererlebnis bei deiner App:

  • Die Karte sollte einen großen Teil des Bildschirms einnehmen. Damit wird die Nutzerfreundlichkeit der Karte auf den kleinen Formfaktor eines Wearable-Geräts optimiert.
  • Berücksichtige bei der Gestaltung des Nutzererlebnisses bei deiner App, dass ein Wearable-Gerät nur eine schwache Akkuleistung hat. Ein durchgängig aktiver Bildschirm und eine permanente Anzeige der Karte beeinträchtigen die Akkuleistung.