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:
- 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.
- Upewnij się, że projekt jest kierowany na Androida 6.0 lub nowszego, ustawiając w pliku manifestu aplikacji wartość
targetSdkVersionna 23 lub wyższą. - Dodaj zależności na urządzenia do noszenia do pliku
build.gradle.ktsaplikacji. Zobacz przykład na tej stronie. - 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.
- Dodaj uprawnienie
WAKE_LOCKdo plików manifestu aplikacji na urządzenia przenośne i do noszenia, jak opisano w lekcji szkoleniowej Androida 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 gdy urządzenie się wyłączy, powinno przejść w tryb nieaktywny, a nie wrócić do tarczy zegarka. - Zaimplementuj w aktywności interfejs
AmbientModeSupport.AmbientCallbackProvider, aby mogła ona otrzymywać informacje o zmianach 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 zrobić to programowo, ustawiającGoogleMapOptions.ambientEnabled(true). To ustawienie informuje interfejs API, że musi on wstępnie wczytać niezbędne kafelki mapy do użycia w trybie nieaktywnym. - Gdy aktywność przechodzi w tryb nieaktywny, system wywołuje metodę
onEnterAmbient()w podanym przez CiebieAmbientCallback. ZastąponEnterAmbient()i wywołajSupportMapFragment.onEnterAmbient(ambientDetails)lubMapView.onEnterAmbient(ambientDetails). Interfejs API przełącza się na nieinteraktywne renderowanie mapy w niskiej jakości kolorów. - Podobnie w
onExitAmbient()wywołajSupportMapFragment.onExitAmbient()lubMapView.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.