Interfejs API Map Google na Wear OS

Mapa na urządzeniu do noszenia

Dzięki pakietowi Maps SDK na Androida możesz tworzyć aplikacje na urządzenia do noszenia oparte na mapach, które działają bezpośrednio na urządzeniach Wear OS by Google. Użytkownicy Twojej aplikacji mogą zobaczyć swoją lokalizację na mapie, po prostu spoglądając na nadgarstek. Mogą na przykład wyznaczyć swoją pozycję na trasie, a następnie powiększyć mapę, aby zobaczyć szczegóły, lub kliknąć znacznik, aby wyświetlić okno informacyjne dostarczone przez Twoją aplikację.

Na tej stronie opisujemy funkcje interfejsu API dostępne na urządzeniu Wear i pomagamy rozpocząć tworzenie aplikacji.

Pierwsze kroki z Wear OS

Tworzenie aplikacji na urządzenia do noszenia za pomocą pakietu Maps SDK na Androida jest zasadniczo takie samo jak tworzenie aplikacji Mapy Google na dowolne inne urządzenie z Androidem. Różnica polega na tym, że musisz zaprojektować aplikację pod kątem mniejszego rozmiaru urządzenia do noszenia, aby zoptymalizować jej użyteczność i wydajność.

Android Studio to zalecane narzędzie do tworzenia aplikacji na Wear OS, ponieważ ułatwia konfigurowanie projektu, dodawanie bibliotek i tworzenie pakietów.

Ogólne wskazówki dotyczące projektowania aplikacji na urządzenia do noszenia znajdziesz w wytycznych dotyczących projektowania na Wear OS. Pomoc w tworzeniu swojej pierwszej aplikacji na urządzenia do noszenia znajdziesz w przewodniku tworzenia aplikacji na urządzenia do noszenia.

Tworzenie pierwszej aplikacji mapowej na Wear OS

Ten krótki przewodnik zakłada, że znasz pakiet Maps SDK na Androida, że masz już moduł na urządzenia do noszenia w swojej aplikacji (zgodnie z instrukcjami dotyczącymi Wear OS) i że chcesz teraz dodać mapę do tego modułu.

Dodawanie zależności do modułu na urządzenia do noszenia

Upewnij się, że w pliku build.gradle.kts modułu Wear OS aplikacji znajdują się te zależności:

dependencies {
    // ...
    // Modern Android projects use version catalogs to manage dependencies.  To include the necessary dependencies,
    // first add the following to your libs.versions.toml file:
    //
    // [versions]
    // playServicesMaps = "20.0.0"
    // wear = "1.4.0"
    // wearable = "2.9.0"
    //
    // [libraries]
    // play-services-maps = { group = "com.google.android.gms", name = "play-services-maps", version.ref = "playServicesMaps" }
    // wear = { group = "androidx.wear", name = "wear", version.ref = "wear" }
    // wearable-compile = { group = "com.google.android.wearable", name = "wearable", version.ref = "wearable" }
    // wearable-support = { group = "com.google.android.support", name = "wearable", version.ref = "wearable" }

    compileOnly(libs.wearable.compile)
    implementation(libs.wearable.support)
    implementation(libs.play.services.maps)

    // This dependency is necessary for ambient mode
    implementation(libs.wear)

    // Android Test Dependencies
    androidTestImplementation(libs.ext.junit)
    androidTestImplementation(libs.espresso.core)
    androidTestImplementation(libs.uiautomator)
    androidTestImplementation(libs.truth)
    androidTestImplementation(libs.junit)
    
    // If your project does not use a version catalog, you can use the following dependencies instead:
    //
    //    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:20.0.0")
    //    implementation("androidx.wear:wear:1.4.0")
    //    androidTestImplementation("androidx.test.ext:junit:1.3.0")
    //    androidTestImplementation("androidx.test.espresso:espresso-core:3.7.0")
    //    androidTestImplementation("androidx.test.uiautomator:uiautomator:2.3.0")
    //    androidTestImplementation("com.google.truth:truth:1.4.5")
    //    androidTestImplementation("junit:junit:4.13.2")
}

Więcej informacji o zależnościach znajdziesz w przewodniku Dodawanie modułu Wear OS do istniejącego projektu.

Implementowanie gestu przesunięcia, aby zamknąć aplikację, i ustawianie początkowego koloru tła

Zalecamy używanie elementu SwipeDismissFrameLayout do wyświetlania mapy na urządzeniu do noszenia. Za pomocą klasy SwipeDismissFrameLayout możesz zaimplementować gest przesunięcia, aby zamknąć aplikację, dzięki czemu użytkownicy będą mogli zamknąć aplikację, przesuwając palcem od lewej krawędzi ekranu.

Aby ustawić niestandardowy początkowy kolor tła, użyj atrybutu XML map:backgroundColor, aby zdefiniować kolor, który ma być wyświetlany do czasu wczytania rzeczywistych kafelków mapy.

Dodaj elementy SwipeDismissFrameLayout i backgroundColor do definicji układu jako kontener elementu 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>

Gdy uzyskasz obiekt SwipeDismissFrameLayout w aktywności, dodaj wywołanie zwrotne i ustaw jego zachowanie tak, aby wykonać niezbędne działanie zamykania, jak pokazano poniżej:

Kotlin

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


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

        // 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.
        try {
            val controller = AmbientModeSupport.attach(this)
            Log.d(MainActivity::class.java.simpleName, "Is ambient enabled: " + controller.isAmbient)
        } catch (e: Exception) {
            Log.w(MainActivity::class.java.simpleName, "Ambient mode unavailable on this device: ${e.message}")
        }

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

    // ...
}

      

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.
        try {
            AmbientModeSupport.AmbientController controller = AmbientModeSupport.attach(this);
            Log.d(MainActivity.class.getSimpleName(), "Is ambient enabled: " + controller.isAmbient());
        } catch (Exception e) {
            Log.w(MainActivity.class.getSimpleName(), "Ambient mode unavailable on this device: " + e.getMessage());
        }

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

    // ...
}

      

Dodawanie mapy

Aby uzyskać dostęp do obiektu GoogleMap, użyj jak zwykle metody wywołania zwrotnego onMapReady(GoogleMap), . Wywołanie zwrotne jest aktywowane, gdy mapa jest gotowa do użycia. W metodzie wywołania zwrotnego możesz dodawać do mapy znaczniki lub polilinie, dodawać odbiorniki lub przesuwać kamerę. Poniższy przykład dodaje znacznik w pobliżu gmachu Sydney Opera House:

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

      

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

      

Włączanie trybu nieaktywnego

Pakiet Maps SDK na Androida obsługuje tryb nieaktywny w aplikacjach na urządzenia do noszenia. Aplikacje, które obsługują tryb nieaktywny, są czasami nazywane aplikacjami zawsze włączonymi. Tryb nieaktywny jest aktywowany, gdy użytkownik przestaje aktywnie korzystać z aplikacji, i umożliwia jej pozostanie widoczną na urządzeniu do noszenia.

Pakiet Maps SDK na Androida zapewnia uproszczone renderowanie mapy w niskiej jakości kolorów do użycia w trybie nieaktywnym, a styl mapy automatycznie dostosowuje się, gdy urządzenie przełącza się z trybu interaktywnego na tryb nieaktywny. W trybie nieaktywnym znikają wszystkie znaczniki, obiekty i elementy sterujące interfejsu. Zmniejsza to zużycie energii przez aplikację i zapewnia spójny wygląd z innymi aplikacjami w trybie nieaktywnym, takimi jak tarcze zegarka.

Aby mieć pewność, że Twoja aplikacja korzysta z trybu nieaktywnego mapy:

  1. Zaktualizuj Android SDK, aby zawierał platformę Android 6.0 (API 23) lub nowszą, która udostępnia interfejsy API umożliwiające przechodzenie aktywności w tryb nieaktywny. Informacje o tym, jak zaktualizować pakiet SDK, znajdziesz w dokumentacji Androida na temat dodawania pakietów SDK.
  2. Upewnij się, że projekt jest kierowany na Androida 6.0 lub nowszego, ustawiając w pliku manifestu aplikacji wartość targetSdkVersion na 23 lub wyższą.
  3. Dodaj zależności na urządzenia do noszenia do pliku build.gradle.kts aplikacji. Zobacz przykład na tej stronie.
  4. Dodaj wpis biblioteki udostępnionej na urządzenia do noszenia do pliku manifestu aplikacji na urządzenia do noszenia, jak opisano w lekcji szkoleniowej Androida na temat utrzymywania widoczności aplikacji.
  5. Dodaj uprawnienie WAKE_LOCK do plików manifestu aplikacji na urządzenia przenośne i do noszenia, jak opisano w lekcji szkoleniowej Androida na temat utrzymywania widoczności aplikacji.
  6. W metodzie onCreate() aktywności wywołaj metodę AmbientModeSupport.attach(). Informuje to system operacyjny, że aplikacja jest zawsze włączona, więc gdy urządzenie się wyłączy, powinno przejść w tryb nieaktywny, a nie wrócić do tarczy zegarka.
  7. Zaimplementuj w aktywności interfejs AmbientModeSupport.AmbientCallbackProvider, aby mogła ona otrzymywać informacje o zmianach stanu trybu nieaktywnego.
  8. Ustaw mapę tak, aby obsługiwała tryb nieaktywny. Możesz to zrobić, ustawiając atrybut map:ambientEnabled="true" w pliku układu XML aktywności lub zrobić to programowo, ustawiając GoogleMapOptions.ambientEnabled(true). To ustawienie informuje interfejs API, że musi on wstępnie wczytać niezbędne kafelki mapy do użycia w trybie nieaktywnym.
  9. Gdy aktywność przechodzi w tryb nieaktywny, system wywołuje metodę onEnterAmbient() w podanym przez Ciebie AmbientCallback. Zastąp onEnterAmbient() i wywołaj SupportMapFragment.onEnterAmbient(ambientDetails) lub MapView.onEnterAmbient(ambientDetails). Interfejs API przełącza się na nieinteraktywne renderowanie mapy w niskiej jakości kolorów.
  10. Podobnie w onExitAmbient() wywołaj SupportMapFragment.onExitAmbient() lub MapView.onExitAmbient(). Interfejs API przełącza się na normalne renderowanie mapy.

Ten przykładowy kod włącza tryb nieaktywny w aktywności:

Kotlin

class AmbientActivity : AppCompatActivity(), AmbientModeSupport.AmbientCallbackProvider {

    private lateinit var mapFragment: SupportMapFragment

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

        // 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.
        try {
            val controller = AmbientModeSupport.attach(this)
            Log.d(AmbientActivity::class.java.simpleName, "Is ambient enabled: " + controller.isAmbient)
        } catch (e: Exception) {
            Log.w(AmbientActivity::class.java.simpleName, "Ambient mode unavailable on this device: ${e.message}")
        }

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

      

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.
        try {
            AmbientModeSupport.AmbientController controller = AmbientModeSupport.attach(this);
            Log.d(AmbientActivity.class.getSimpleName(), "Is ambient enabled: " + controller.isAmbient());
        } catch (Exception e) {
            Log.w(AmbientActivity.class.getSimpleName(), "Ambient mode unavailable on this device: " + e.getMessage());
        }

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

      

Możesz aktualizować ekran, gdy aplikacja jest w trybie nieaktywnym. Więcej informacji o aktualizowaniu treści i trybie nieaktywnym znajdziesz w lekcji szkoleniowej Androida na temat utrzymywania widoczności aplikacji.

Korzystanie ze Street View na Wear OS

Street View jest w pełni obsługiwany na urządzeniach do noszenia.

Aby umożliwić użytkownikom zamykanie aplikacji podczas wyświetlania panoramy Street View, użyj interfejsu StreetViewPanorama.OnStreetViewPanoramaLongClickListener , aby nasłuchiwać gestu długiego kliknięcia. Gdy użytkownik długo kliknie w dowolnym miejscu obrazu Street View, otrzymasz zdarzenie onStreetViewPanoramaLongClick(StreetViewPanoramaOrientation). Aby wyświetlić przycisk wyjścia, wywołaj DismissOverlayView.show().

Przykładowy kod

W GitHub jest dostępna przykładowa aplikacja, której możesz użyć jako punktu wyjścia dla swojej aplikacji. Pokazuje ona, jak skonfigurować podstawową Mapę Google na Wear OS.

Obsługiwane funkcje interfejsu API Map Google na Wear OS

W tej sekcji opisujemy różnice w obsługiwanych funkcjach map na urządzeniach do noszenia w porównaniu z urządzeniami przenośnymi (telefonami i tabletami). Wszystkie funkcje interfejsu API, które nie są wymienione poniżej, powinny działać zgodnie z dokumentacją pełnego interfejsu API.

Funkcje
Tryb w pełni interaktywny i tryb uproszczony

Możesz używać pakietu Maps SDK na Androida w trybie interaktywnym lub w wersji uproszczonej. Rozważ wersję uproszczoną, jeśli chcesz zoptymalizować wydajność na urządzeniu do noszenia, a Twoja aplikacja nie musi obsługiwać interakcji, takich jak gesty, przesuwanie i powiększanie mapy.

W wersji uproszczonej intencja uruchomienia aplikacji mobilnej Mapy Google, gdy użytkownik kliknie mapę, jest wyłączona i nie można jej włączyć na urządzeniu do noszenia.

Pełną listę różnic między wersją uproszczoną a trybem w pełni interaktywnym znajdziesz w dokumentacji wersji uproszczonej.

Pasek narzędzi mapy Pasek narzędzi mapy jest wyłączony i nie można go włączyć na urządzeniu do noszenia.
Elementy sterujące interfejsu Elementy sterujące interfejsu są domyślnie wyłączone na urządzeniach do noszenia. Obejmuje to elementy sterujące powiększeniem, kompasem i moją lokalizacją. Możesz je włączyć za pomocą UiSettings klasy jak zwykle.
Gesty Gesty jednym palcem działają zgodnie z oczekiwaniami. Przykłady to dotknięcie i przeciągnięcie, aby przesunąć mapę, dwukrotne kliknięcie aby powiększyć, oraz dotknięcie dwoma palcami, aby pomniejszyć. Obsługa gestów wielodotykowych różni się w zależności od urządzenia użytkownika. Przykłady gestów wielodotykowych to przesunięcie dwoma palcami, aby przechylić mapę, ściągnięcie, aby powiększyć, oraz obrót dwoma palcami.
Mapy obiektów i budynki Mapy obiektów są domyślnie wyłączone na urządzeniu do noszenia. Możesz je włączyć, wywołując GoogleMap.setIndoorEnabled(true). Jeśli mapy obiektów są włączone, mapa będzie wyświetlać domyślny poziom. Element interfejsu użytkownika do wybierania poziomu picker nie jest obsługiwany na urządzeniach do noszenia.
Nakładki z kafelkami Nakładki z kafelkami są nie są obsługiwane na urządzeniach do noszenia.

Sprawdzone metody programowania za pomocą interfejsu API Map Google na Wear OS

Jak zapewnić użytkownikom najlepsze wrażenia w aplikacji:

  • Mapa powinna zajmować dużą część ekranu. Jest to konieczne, aby zoptymalizować użyteczność mapy na małym urządzeniu do noszenia.
  • Projektując wrażenia użytkownika w aplikacji, weź pod uwagę, że urządzenie do noszenia ma słabą baterię. Utrzymywanie aktywnego ekranu i widocznej mapy będzie miało wpływ na wydajność baterii.