Interfejs API Map Google na Wear OS

Mapa na urządzeniu do noszenia

Za pomocą pakietu SDK Map Google na Androida możesz utworzyć opartą na mapie aplikację do noszenia, która działa bezpośrednio na urządzeniach z Wear OS by Google. Użytkownicy Twojej aplikacji mogą sprawdzać swoją lokalizację na mapie, spoglądając na nadgarstki. Mogą na przykład wyznaczyć swoją pozycję na trasie, a następnie powiększyć widok lub kliknąć znacznik, aby wyświetlić okno informacyjne wyświetlane przez aplikację.

Na tej stronie opisujemy funkcje interfejsu API dostępne na urządzeniach Wear i pomagamy Ci w tworzeniu aplikacji.

Pierwsze kroki z Wear OS

Tworzenie aplikacji do noszenia za pomocą pakietu SDK Map Google na Androida przypomina tworzenie aplikacji Mapy Google na dowolne urządzenie z Androidem. Różnica polega na tym, że urządzenie do noszenia jest w mniejszym formacie, co zapewnia łatwość obsługi i wydajność.

Do tworzenia aplikacji na Wear OS zalecane jest narzędzie Android Studio, które zapewnia konfigurację projektu, uwzględnianie biblioteki i ułatwienia tworzenia pakietów.

Ogólną pomoc przy projektowaniu aplikacji na urządzenia do noszenia znajdziesz w wytycznych dotyczących projektowania aplikacji na Wear OS. Aby dowiedzieć się, jak utworzyć pierwszą aplikację na urządzenia do noszenia, zapoznaj się z przewodnikiem na temat tworzenia aplikacji do noszenia.

Tworzenie pierwszej aplikacji z mapami na Wear OS

W tym krótkim przewodniku przyjęto założenie, że znasz pakiet SDK Map Google na Androida, postępujesz zgodnie z instrukcjami na temat Wear OS, aby utworzyć moduł do noszenia w aplikacji, i chcesz dodać do niego mapę.

Dodaję zależności dla modułu Wear

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

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.2.0'

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

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

Wdrażanie gestu przesuwania, aby zamknąć, i ustawianie początkowego koloru tła

Do wyświetlania mapy na urządzeniu do noszenia zalecamy używanie aplikacji SwipeDismissFrameLayout. Za pomocą klasy SwipeDismissFrameLayout możesz zaimplementować gest przesuwania, by zmniejszyć, dający użytkownikom możliwość zamknięcia aplikacji przez przesunięcie palcem od najbardziej lewej krawędzi ekranu.

Aby ustawić niestandardowy początkowy kolor tła, użyj atrybutu XML map:backgroundColor w celu określenia koloru, który będzie wyświetlany do czasu rzeczywistego załadowania kafelków mapy.

Dodaj do definicji układu elementy SwipeDismissFrameLayout i backgroundColor 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 w aktywności obiekt SwipeDismissFrameLayout, dodaj wywołanie zwrotne i ustaw jego działanie tak, by wykonać niezbędne działanie odrzucenia, jak pokazano poniżej:

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

    // ...
}

      

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

    // ...
}

      

Dodawanie mapy

Aby uzyskać uchwyt do obiektu GoogleMap, użyj metody wywołania zwrotnego onMapReady(GoogleMap) w zwykły sposób. Wywołanie zwrotne jest wywoływane, gdy mapa jest gotowa do użycia. W metodzie wywołania zwrotnego możesz dodawać do mapy znaczniki lub linie łamane, dodawać detektory i przesuwać kamerę. Poniższy przykład pokazuje oznaczenie w pobliżu Opery w Sydney:

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łączam dźwięki otoczenia

Pakiet SDK Map Google na Androida obsługuje tryb nieaktywny w aplikacjach do noszenia. Aplikacje, które obsługują dźwięki otoczenia, są czasami określane jako zawsze włączone. Tryb nieaktywny włącza się, gdy użytkownik nie korzysta już z aplikacji, i pozostaje widoczna na urządzeniu do noszenia.

Pakiet SDK Map Google na Androida upraszcza renderowanie mapy w trybie nieaktywnym, a styl mapy dostosowuje się automatycznie przy przełączaniu się z urządzenia interaktywnego na tryb nieaktywny. Wszystkie znaczniki, obiekty i elementy sterujące znikają w trybie nieaktywnym. Zmniejsza to zużycie energii przez aplikację i zapewnia spójny wygląd i styl z innymi aplikacjami nieaktywnymi, takimi jak tarcze zegarka.

Aby sprawdzić, czy aplikacja używa trybu nieaktywnego mapy, wykonaj te czynności:

  1. Zaktualizuj pakiet SDK Androida, tak 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 na Androida dotyczącej dodawania pakietów SDK.
  2. Upewnij się, że Twój projekt jest kierowany na Androida 6.0 lub nowszego, ustawiając w pliku manifestu aplikacjitargetSdkVersion wartość 23 lub wyższą.
  3. Dodaj zależności do urządzenia do noszenia do pliku build.gradle aplikacji. Zobacz przykład na tej stronie.
  4. Dodaj wpis biblioteki udostępnionej do noszenia do pliku manifestu aplikacji na urządzenia do noszenia zgodnie z opisem w klasie treningowej Androida na temat utrzymywania widoczności aplikacji.
  5. Dodaj uprawnienie WAKE_LOCK do plików manifestu aplikacji na urządzenia mobilne i urządzenia do noszenia zgodnie z opisem w klasie 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, tak aby po wyłączeniu urządzenia aplikacja mogła wejść w tryb nieaktywny, zamiast wracać do tarczy zegarka.
  7. Zaimplementuj interfejs AmbientModeSupport.AmbientCallbackProvider w swojej aktywności, aby mógł odbierać zmiany stanu trybu nieaktywnego.
  8. Ustaw mapę tak, by 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 automatycznie, ustawiając wartość GoogleMapOptions.ambientEnabled(true). To ustawienie informuje interfejs API, że musi wstępnie wczytać kafelki mapy niezbędne do użycia w trybie nieaktywnym.
  9. Gdy aktywność przełącza się w tryb nieaktywny, system wywołuje metodę onEnterAmbient() w podanym przez Ciebie elemencie AmbientCallback. Zastąp onEnterAmbient() i wywołaj SupportMapFragment.onEnterAmbient(ambientDetails) lub MapView.onEnterAmbient(ambientDetails). Interfejs API przełącza się na nieinteraktywne renderowanie mapy w niskim kolorze.
  10. I podobnie w wywołaniu onExitAmbient() SupportMapFragment.onExitAmbient() lub MapView.onExitAmbient(). Interfejs API przełączy się na normalne renderowanie mapy.

Ten przykładowy kod włącza dźwięki otoczenia w aktywności:

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

      

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

      

Ekran możesz zaktualizować, gdy aplikacja działa w trybie nieaktywnym. Więcej informacji o aktualizowaniu treści i o trybie nieaktywnym znajdziesz na zajęciach na temat utrzymywania widoczności aplikacji na Androidzie.

Korzystanie ze Street View na Wear OS

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

Aby umożliwić użytkownikom wyjście z aplikacji podczas oglądania panoramy Street View, skorzystaj z interfejsu StreetViewPanorama.OnStreetViewPanoramaLongClickListener i nasłuchuj gestu dłuższego kliknięcia. Gdy użytkownik kliknie i przytrzyma zdjęcie w Street View, otrzymasz zdarzenie onStreetViewPanoramaLongClick(StreetViewPanoramaOrientation). Zadzwoń na DismissOverlayView.show(), aby wyświetlić przycisk wyjścia.

Przykładowy kod

Na GitHub dostępna jest przykładowa aplikacja, która może być punktem wyjścia dla aplikacji. Ten przykład pokazuje, jak skonfigurować podstawową aplikację Google na Wear OS.

Obsługiwane funkcje interfejsu API Map Google na Wear OS

W tej sekcji przedstawiamy różnice pod względem obsługiwanych funkcji map na urządzeniach do noszenia w porównaniu z urządzeniami mobilnymi (telefonami i tabletami). Wszystkie funkcje interfejsu API, których nie wymieniono poniżej, powinny działać jak w przypadku pełnej wersji interfejsu API.

Funkcje
Tryb w pełni interaktywny i wersja uproszczona

Pakietu SDK Map Google na Androida możesz używać w trybie w pełni interaktywnym lub w wersji uproszczonej. Wybierz wersję uproszczoną, jeśli chcesz zoptymalizować wydajność na urządzeniu do noszenia, a aplikacja nie musi obsługiwać interakcji, takich jak gesty, przesuwanie i powiększanie mapy.

W wersji uproszczonej zamiar uruchomienia aplikacji mobilnej Mapy Google po kliknięciu mapy przez użytkownika jest wyłączony i nie można go 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. Obejmują one sterowanie powiększeniem, kompasem i moją lokalizacją. Możesz je włączyć jak zwykle za pomocą klasy UiSettings.
Gesty Gesty polegające na jednym naciśnięciu działają zgodnie z oczekiwaniami. Można na przykład dotknąć i przeciągnąć mapę, aby ją przesunąć, kliknąć dwukrotnie, aby powiększyć, lub kliknąć 2 palcami, aby pomniejszyć. Obsługa gestów wielodotykowych zależy od urządzenia użytkownika. Przykłady gestów wymagających użycia wielu dotyku to przesuwanie 2 palcami, aby przechylić mapę, ściąganie i rozsuwanie mapy, aby powiększyć widok, i obrót 2 palcami.
Mapy i budynki obiektów Mapy obiektów są domyślnie wyłączone na urządzeniu do noszenia. Możesz je włączyć, wywołując tę funkcję: GoogleMap.setIndoorEnabled(true). Jeśli włączone są mapy obiektów, na mapie wyświetli się domyślny poziom piętra. Element interfejsu selektora poziomów nie jest obsługiwany na urządzeniach do noszenia.
Nakładki z fragmentami mapy Nakładki z kafelkami nie są obsługiwane na urządzeniach do noszenia.

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

Jak zapewnić użytkownikom maksymalną wygodę korzystania z aplikacji:

  • Mapa powinna zajmować dużą część ekranu. Jest to konieczne, aby zoptymalizować łatwość obsługi mapy na małym urządzeniu do noszenia.
  • Projektując aplikację, weź pod uwagę fakt, że urządzenia do noszenia mają słabą baterię. Pozostawienie aktywnego ekranu i widoczności mapy ma wpływ na zużycie baterii.