Dzięki pakietowi Maps SDK na Androida możesz utworzyć aplikację na urządzenia do noszenia opartą na mapach, która działa bezpośrednio na urządzeniach z Wear OS by Google. Użytkownicy Twojej aplikacji mogą zobaczyć swoją lokalizację na mapie, spoglądając na nadgarstek. Mogą na przykład wyznaczyć swoją pozycję na trasie, a następnie powiększyć widok, aby zobaczyć szczegóły, lub kliknąć znacznik, aby wyświetlić okno informacyjne dostarczone przez 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 Map Google na dowolne inne urządzenie z Androidem. Różnica polega na tym, że projektujesz aplikację na mniejsze urządzenie do noszenia, aby zoptymalizować jej użyteczność i wydajność.
Android Studio to zalecane narzędzie do tworzenia aplikacji na Wear OS, ponieważ ułatwia konfigurację projektu, dołączanie bibliotek i pakowanie.
Ogólne wskazówki dotyczące projektowania aplikacji na urządzenia do noszenia znajdziesz w wytycznych dotyczących projektowania na Wear OS. Jeśli potrzebujesz pomocy przy tworzeniu pierwszej aplikacji na urządzenia do noszenia, zapoznaj się z przewodnikiem na temat tworzenia aplikacji na urządzenia do noszenia.
Tworzenie pierwszej aplikacji z mapami na Wear OS
W tym krótkim przewodniku zakładamy, że znasz pakiet Maps SDK na Androida, że postępujesz zgodnie z przewodnikami po Wear OS, aby utworzyć moduł do noszenia w aplikacji, i że chcesz teraz dodać mapę do modułu do noszenia.
Dodawanie zależności do modułu Wear
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.1.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.1.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 palcem w celu zamknięcia i ustawianie początkowego koloru tła
Zalecamy używanie SwipeDismissFrameLayout do wyświetlania mapy na urządzeniu do noszenia. Za pomocą klasy SwipeDismissFrameLayout możesz zaimplementować gest przesunięcia w celu zamknięcia, który umożliwia użytkownikom zamknięcie aplikacji przez przesunięcie 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 momentu załadowania 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>Po uzyskaniu obiektu SwipeDismissFrameLayout w aktywności dodaj wywołanie zwrotne i ustaw jego działanie tak, aby wykonywało niezbędne działanie odrzucenia, 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
Użyj metody wywołania zwrotnego onMapReady(GoogleMap) jak zwykle, aby uzyskać uchwyt do obiektu 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 linie łamane, dodawać detektory lub przesuwać kamerę. Poniższy przykład dodaje znacznik 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łączanie oświetlenia kinowego
Pakiet Maps SDK na Androida obsługuje tryb nieaktywny w aplikacjach na urządzenia do noszenia. Aplikacje obsługujące tryb nieaktywny są czasami nazywane aplikacjami zawsze aktywnymi. Tryb nieaktywny jest aktywowany, gdy użytkownik nie korzysta już aktywnie z aplikacji, i umożliwia jej pozostanie widoczną na urządzeniu do noszenia.
Pakiet Maps SDK na Androida udostępnia uproszczone renderowanie mapy z ograniczoną liczbą kolorów do użycia w trybie nieaktywnym. Styl mapy dostosowuje się automatycznie, gdy urządzenie przechodzi z trybu interaktywnego do nieaktywnego. 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 i styl z innymi aplikacjami w trybie ambient, takimi jak tarcze zegarka.
Aby upewnić się, że aplikacja korzysta z trybu nieaktywnego mapy:
- Zaktualizuj pakiet Android SDK, aby uwzględnić 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 dotyczącej dodawania pakietów SDK.
- Upewnij się, że projekt jest kierowany na Androida 6.0 lub nowszego, ustawiając
targetSdkVersionna 23 lub więcej w manifeście aplikacji. - Dodaj zależności urządzenia do noszenia do pliku
build.gradle.ktsaplikacji. Zobacz przykład na tej stronie. - Dodaj wpis o udostępnionej bibliotece na urządzenie do noszenia do pliku manifestu aplikacji na takie urządzenie, jak opisano w szkoleniu na temat utrzymywania widoczności aplikacji.
- Dodaj uprawnienie
WAKE_LOCKdo plików manifestu aplikacji na urządzenia przenośne i do noszenia, zgodnie z opisem w szkoleniu na temat utrzymywania widoczności aplikacji. - W metodzie
onCreate()aktywności wywołaj metodęAmbientModeSupport.attach(). Informuje to system operacyjny, że aplikacja jest zawsze włączona, więc po wyłączeniu urządzenia powinno ono przejść w tryb nieaktywny, a nie wracać do tarczy zegarka. - Zaimplementuj interfejs
AmbientModeSupport.AmbientCallbackProviderw aktywności, aby mogła ona otrzymywać zmiany stanu trybu nieaktywnego. - 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 programowo, ustawiającGoogleMapOptions.ambientEnabled(true). To ustawienie informuje interfejs API, że musi wstępnie wczytać niezbędne kafelki mapy do użycia w trybie nieaktywnym. - Gdy aktywność przełącza się w tryb nieaktywny, system wywołuje metodę
onEnterAmbient()w podanym przez Ciebie obiekcieAmbientCallback. ZastąponEnterAmbient()i zadzwoń pod numerSupportMapFragment.onEnterAmbient(ambientDetails)lubMapView.onEnterAmbient(ambientDetails). Interfejs API przełącza się na nieinteraktywne renderowanie mapy z małą liczbą kolorów. - Podobnie w
onExitAmbient()zadzwoń pod numerSupportMapFragment.onExitAmbient()lubMapView.onExitAmbient(). Interfejs API przełącza się na normalne renderowanie mapy.
Poniższy 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 = 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 szkoleniu dotyczącym Androida na temat utrzymywania widoczności aplikacji.
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 wyświetlania panoramy Street View, użyj interfejsu StreetViewPanorama.OnStreetViewPanoramaLongClickListener, który wykrywa gest długiego kliknięcia. Gdy użytkownik kliknie i przytrzyma wybrane miejsce na zdjęciu Street View, otrzymasz zdarzenie onStreetViewPanoramaLongClick(StreetViewPanoramaOrientation). Wywołaj DismissOverlayView.show(), aby wyświetlić przycisk wyjścia.
Przykładowy kod
Przykładowa aplikacja jest dostępna na GitHub. Możesz jej użyć jako punktu wyjścia dla swojej aplikacji. Przykład pokazuje, jak skonfigurować podstawową Mapę Google na Wear OS.
Funkcje obsługiwane w interfejsie API Map Google na Wear OS
W tej sekcji opisano 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 zostały wymienione poniżej, powinny działać zgodnie z dokumentacją pełnego interfejsu API.
| Funkcje | |
|---|---|
| Tryb w pełni interaktywny i wersja uproszczona | Pakietu Maps SDK na Androida możesz używać w trybie interaktywnym lub w wersji uproszczonej. Jeśli chcesz zoptymalizować działanie aplikacji na urządzeniu do noszenia, a aplikacja nie musi obsługiwać interakcji, takich jak gesty czy przesuwanie i powiększanie mapy, rozważ użycie wersji uproszczonej. 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ć, używając klasy UiSettings w zwykły sposób.
|
| Gesty | Gesty wykonywane jednym palcem działają zgodnie z oczekiwaniami. Przykłady: dotknięcie i przeciągnięcie, aby przesunąć mapę, dwukrotne kliknięcie, aby powiększyć, i kliknię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 m.in. przesuwanie 2 palcami w celu przechylenia mapy, ściąganie i rozciąganie palców w celu powiększenia oraz obracanie 2 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 piętra.
Element interfejsu selektor poziomu nie jest obsługiwany na urządzeniach do noszenia. |
| Nakładki z fragmentami mapy | Nakładki kafelkowe nie są obsługiwane na urządzeniach do noszenia. |
Sprawdzone metody programowania z użyciem 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 ekranie urządzenia do noszenia.
- Projektując interfejs aplikacji, weź pod uwagę fakt, że urządzenie do noszenia ma słabą baterię. Utrzymywanie aktywnego ekranu i widocznej mapy wpłynie na wydajność baterii.