Tworzenie prostej aplikacji nawigacyjnej na Androida za pomocą pakietu SDK nawigacji Google Maps Platform

1. Zanim zaczniesz

Z tego ćwiczenia dowiesz się, jak utworzyć prostą aplikację na Androida, która korzysta z pakietu Navigation SDK w Google Maps Platform, aby nawigować do wstępnie skonfigurowanego miejsca docelowego.

Tak będzie wyglądać Twoja aplikacja po zakończeniu pracy.

b6c535afde7abd20.png

Wymagania wstępne

  • Znajomość podstaw tworzenia aplikacji na Androida w języku Kotlin
  • Znajomość podstawowych pojęć związanych z pakietem Google Maps SDK, takich jak mapy, lokalizacje i współrzędne.

Czego się nauczysz

  • Jak utworzyć prostą aplikację na Androida, która korzysta z pakietu Navigation SDK do nawigowania do miejsca docelowego.
  • Integracja pakietu SDK do nawigacji z zewnętrznego repozytorium Google Maven
  • Jak zarządzać uprawnieniami do lokalizacji i umową użytkownika z warunkami dotyczącymi użytkowników pakietu Navigation SDK
  • Inicjowanie pakietu SDK
  • Jak ustawić cel podróży i rozpocząć nawigację.

Czego potrzebujesz

  • Zainstalowana najnowsza stabilna wersja Androida Studio. Ten codelab został utworzony w Android Studio Jellyfish. Jeśli używasz innej wersji, wygląd i układ interfejsu oraz komponentów mogą się różnić.
  • konto Google i projekt z włączonymi płatnościami,
  • urządzenie z Androidem w trybie programisty z włączonym debugowaniem USB lub emulator Androida; Niezależnie od tego, którą opcję wybierzesz, musi ona spełniać minimalne wymagania dotyczące pakietu Navigation SDK.

2. Konfiguracja

Jeśli nie masz jeszcze konta Google Cloud Platform i projektu w chmurze z włączonymi płatnościami, skonfiguruj projekt Google Cloud, postępując zgodnie z instrukcjami na stronie Wprowadzenie do Google Maps Platform: https://developers.google.com/maps/gmp-get-started

Wybierz projekt Google Cloud w konsoli.

W konsoli Google Cloud kliknij menu projektu i wybierz projekt, którego chcesz użyć w tym module.

Menu wyboru projektu w konsoli Google Cloud.

Włączanie Navigation SDK w projekcie

Włącz interfejsy API i pakiety SDK Google Maps Platform wymagane w tym samouczku w Google Cloud Marketplace.

W konsoli Google Cloud otwórz Interfejsy API i usługi > Biblioteka i wyszukaj „Navigation SDK”.

Powinien wyświetlić się 1 wynik wyszukiwania.

Ekran Biblioteka interfejsów API w konsoli Google Cloud z wyświetloną stroną pakietu Navigation SDK.

Kliknij wynik Navigation SDK, aby otworzyć stronę z informacjami o produkcie. Kliknij przycisk Włącz, aby włączyć pakiet SDK w projekcie.

Powtórz ten proces w przypadku Google Maps SDK na Androida.

Utwórz klucz interfejsu API

Wygeneruj klucz interfejsu API na stronie Dane logowania w konsoli Cloud. Wykonaj czynności opisane w kroku 3 sekcji „Szybki start” w artykule Pierwsze kroki z Google Maps Platform. Wszystkie żądania wysyłane do Google Maps Platform wymagają klucza interfejsu API.

3. Pobieranie przykładowych plików projektu

W tej sekcji opisujemy, jak skonfigurować podstawowy pusty projekt Android Studio, klonując pliki z repozytorium GitHub na potrzeby tego laboratorium. Repozytorium GitHub zawiera wersje kodu modułu przed i po zmianach. Ten przewodnik zaczyna się od pustego szablonu projektu i prowadzi do jego ukończenia. Jeśli utkniesz, możesz użyć gotowego projektu w repozytorium jako materiału referencyjnego.

Sklonuj to repozytorium GitHub, aby uzyskać kod na potrzeby tego ćwiczenia.

git clone https://github.com/googlemaps-samples/codelab-navigation-101-android-kotlin.git

Jeśli nie masz zainstalowanego narzędzia git, kliknij ten przycisk, aby pobrać kod:

Aby jak najszybciej zacząć, w repozytorium znajdziesz w folderze Starter kod startowy, który pomoże Ci w wykonaniu tego ćwiczenia. Projekt początkowy zawiera podstawowy interfejs aplikacji i konfigurację kompilacji, ale nie ma dodanego pakietu Navigation SDK. Dostępny jest też gotowy Solution projekt, jeśli chcesz przejść dalej lub w dowolnym momencie sprawdzić swoje postępy.

Otwórz sklonowane repozytorium w Android Studio

Po sklonowaniu repozytorium lokalnie otwórz folder Starter w Androidzie Studio jako istniejący projekt.

  1. W oknie Witamy w Android Studio kliknij przycisk Otwórz.
  2. Przejdź do folderu, w którym zapisano sklonowane repozytorium, i wybierz folder Starter w folderze najwyższego poziomu „codelab-navigation-101-android-kotlin”.
  3. Sprawdź, czy projekt się kompiluje i działa.

Dodawanie urządzenia wirtualnego lub podłączanie urządzenia

Aby połączyć urządzenie z Androidem z komputerem, postępuj zgodnie z instrukcjami Android Studio dotyczącymi uruchamiania aplikacji na urządzeniu. Możesz też skonfigurować urządzenie wirtualne za pomocą Menedżera urządzenia wirtualnego z Androidem (AVD). Wybierając emulator, pamiętaj, aby wybrać obraz, który zawiera interfejsy API Google.

W Android Studio kliknij opcję menu Uruchom lub ikonę przycisku odtwarzania. Wybierz urządzenie zgodnie z instrukcjami.

4. Dodawanie pakietu Navigation SDK do aplikacji

Dodawanie biblioteki Navigation SDK i klucza interfejsu API do projektu

Aby dodać bibliotekę Navigation SDK do aplikacji, musisz zmodyfikować plik kompilacji na poziomie aplikacji build.gradle.kts, aby pobrać pakiet Navigation SDK z repozytorium Maven i skonfigurować numer wersji.

Utwórz w konfiguracji kompilacji zmienną do przechowywania numeru wersji pakietu Navigation SDK.

Skonfiguruj w build.gradle.kts na poziomie aplikacji zmienną, która będzie zawierać wartość wersji pakietu Navigation SDK używanej w aplikacji. Dzięki temu w przyszłości łatwo będzie można zmienić ją na najnowszą wersję.

Najnowszy numer wersji znajdziesz w informacjach o wersji pakietu Navigation SDK.

val navSdkVersion by extra("6.0.0")

Wartości tej i innych zmiennych możesz też modyfikować w oknie dialogowym, które znajdziesz w sekcji Plik > Struktura projektu > Zmienne:

668332736b67dc82.png

Dodawanie zależności do konfiguracji kompilacji

Teraz dodaj do sekcji zależności w pliku build.gradle.kts. na poziomie aplikacji tę zależność interfejsu API. Użyta wersja będzie wartością zmiennej ${navSdkVersion}, którą właśnie ustawiono w pliku build.gradle.kts na poziomie aplikacji:

dependencies {

   // Include the Google Navigation SDK.
   api("com.google.android.libraries.navigation:navigation:${navSdkVersion}")

...

Dodawanie klucza interfejsu API

Zarządzanie kluczem interfejsu API za pomocą wtyczki Gradle obiektów tajnych

Zalecamy używanie wtyczki Gradle obiektów tajnych do bezpiecznego zarządzania kluczem interfejsu API w aplikacji. Wtyczka została dodana do początkowego szablonu projektu jako zależność w pliku build.gradle.kts najwyższego poziomu.

// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
    id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin") version "2.0.1" apply false
    //... other plugin definitions here
}

Otwórz plik secrets.properties w katalogu najwyższego poziomu, a następnie zastąp YOUR_API_KEY kluczem interfejsu API. Przechowuj klucz w tym pliku, ponieważ secrets.properties jest wykluczony z systemu kontroli wersji.

MAPS_API_KEY=YOUR_API_KEY

Więcej informacji na ten temat znajdziesz w artykule Dodawanie klucza interfejsu API do aplikacji w dokumentacji pakietu Navigation SDK.

Sprawdź zawartość pliku local.defaults.properties

Pusty projekt zawiera też plik local.defaults.properties w katalogu najwyższego poziomu, czyli w tym samym folderze co plik secrets.properties. Otwórz go i sprawdź poniższy kod.

MAPS_API_KEY=DEFAULT_API_KEY

Jest to wartość zapasowa dla właściwości MAPS_API_KEY na wypadek, gdyby właściwość secrets.properties nie została dodana do projektu, aby kompilacje nie kończyły się niepowodzeniem. Nie musisz edytować tego pliku. Jeśli secrets.properties definicja MAPS_API_KEY nie zostanie znaleziona, wartość domyślna spowoduje zatrzymanie działania aplikacji w czasie wykonywania z błędem klucza API.

Sprawdź, czy plik manifestu Androida używa określonego przez Ciebie klucza interfejsu API

Otwórz plik app/src/main/AndroidManifest.xml. Zauważysz, że właściwość MAPS_API_KEY służy do ustawiania klucza interfejsu API aplikacji:

<meta-data
    android:name="com.google.android.geo.API_KEY"
    android:value="${MAPS_API_KEY}" />

Otwórz plik build.gradle.kts na poziomie aplikacji i znajdź właściwość secrets.

Ustawienie propertiesFileName wtyczki powinno mieć wartość secrets.properties, a wartość defaultPropertiesFileName powinna być równa local.defaults.properties.

secrets {
    // Optionally specify a different file name containing your secrets.
    // The plugin defaults to "local.properties"
    propertiesFileName = "secrets.properties"

    // A properties file containing default secret values. This file can be
    // checked in version control.
    defaultPropertiesFileName = "local.defaults.properties"
}

Zapisz wszystkie pliki i zsynchronizuj projekt z Gradle.

5. Konfigurowanie uprawnień aplikacji i dodawanie podstawowego interfejsu

Prośba o dostęp do dokładnej lokalizacji

Pakiet SDK do nawigacji zależy od sygnałów GPS, więc aplikacja musi poprosić użytkownika o przyznanie dostępu do dokładnych danych o lokalizacji. Dodaj uprawnienie dostępu do dokładnej lokalizacji jako element podrzędny elementu <manifest> w pliku AndroidManifest.xml.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" >
   <uses-permission 
      android:name="android.permission.ACCESS_FINE_LOCATION"
   />
</manifest>

Więcej informacji o uprawnieniach do lokalizacji na Androidzie znajdziesz w sekcji Request location permissions (Prośba o uprawnienia do lokalizacji) w dokumentacji dla deweloperów aplikacji na Androida.

Aby uruchomić aplikację na urządzeniu z Androidem 14, poproś o dostęp do lokalizacji usługi działającej na pierwszym planie, dodając ten tag uses-permission w tym samym miejscu co uprawnienie dostępu do dokładnej lokalizacji:

<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />

Dodawanie aktywności uruchamiania z podstawowym interfejsem

Podczas uruchamiania aplikacji będzie potrzebny kod, który sprawdzi, czy użytkownik przyznał uprawnienia dostępu do lokalizacji, i obsłuży każdy możliwy scenariusz, w razie potrzeby prosząc o przyznanie uprawnień. Aby to zrobić, dodaj do aplikacji podstawowy interfejs. W tym laboratorium używamy interfejsu, który jest tworzony podczas tworzenia w Androidzie Studio nowej, pustej aktywności Views. Dostosujesz ten kod, aby przed dodaniem kodu do aktywności interfejsu nawigacji sprawdzić dostęp do lokalizacji.

Otwórz plik MainActivity.kt w edytorze kodu i sprawdź kod, który przedstawia podstawowy interfejs.

Wysyłanie prośby o uprawnienia dostępu do lokalizacji w czasie działania

Aplikacja musi wywołać prośbę o dostęp do dokładnej lokalizacji przed zainicjowaniem pakietu Navigation SDK.

Aby to sprawdzanie odbywało się podczas uruchamiania aplikacji, dodaj kod do klasy MainActivity w zastąpionej metodzie onCreate() aktywności.

Poniższy kod sprawdza, czy użytkownik przyznał dostęp do lokalizacji. Jeśli nie, prosi o uprawnienia. Dodaj ten kod w metodzie onCreate().

    val permissions =
      if (VERSION.SDK_INT >= VERSION_CODES.TIRAMISU) {
        arrayOf(permission.ACCESS_FINE_LOCATION, permission.POST_NOTIFICATIONS)
      } else {
        arrayOf(permission.ACCESS_FINE_LOCATION)
      }

    if (permissions.any { !checkPermissionGranted(it) }) {

      if (permissions.any { shouldShowRequestPermissionRationale(it) }) {
        // Display a dialogue explaining the required permissions.
      }

      val permissionsLauncher =
        registerForActivityResult(
          RequestMultiplePermissions(),
          { permissionResults ->
            if (permissionResults.getOrDefault(permission.ACCESS_FINE_LOCATION, false)) {
              onLocationPermissionGranted()
            } else {
              finish()
            }
          },
        )

      permissionsLauncher.launch(permissions)
    } else {
      android.os.Handler(Looper.getMainLooper()).postDelayed({ onLocationPermissionGranted() }, SPLASH_SCREEN_DELAY_MILLIS)
    }
  }

  private fun checkPermissionGranted(permissionToCheck: String): Boolean =
    ContextCompat.checkSelfPermission(this, permissionToCheck) == PackageManager.PERMISSION_GRANTED

Dodaj do klasy MainActivity nową funkcję o nazwie onLocationPermissionGranted, która będzie obsługiwać wynik, gdy użytkownik przyzna uprawnienia do udostępniania lokalizacji. W kolejnych krokach dodamy tutaj kod, który uruchomi nową aktywność nawigacyjną.

private fun onLocationPermissionGranted() {
   //code to initialize Navigation SDK will go here
}

Utwórz projekt. Jeśli wystąpią błędy kompilacji, znajdź je i popraw.

Uruchom projekt na nowym urządzeniu wirtualnym. Gdy aplikacja zostanie zainstalowana i uruchomiona, powinno pojawić się okno z prośbą o uprawnienia.

6. Dodawanie interfejsu użytkownika do nawigacji

Interfejs nawigacji możesz dodać na 2 sposoby: SupportNavigationFragment lub NavigationView.

Dla uproszczenia w tym laboratorium używamy znaku NavigationView.

Edytowanie układu

Edytuj res/layout/activity_main.xml, aby dodać układ do widoku NavigationView.

  1. Otwórz plik i przełącz się na widok kodu.
  2. Zastąp całą zawartość pliku nowym układem NavigationViewRelativeLayout, jak w przykładzie poniżej. Wystarczy prosty układ, ponieważ dodasz tylko widok nawigacji do aplikacji.
  3. Nadaj widokowi NavigationView identyfikator „@+id/navigation_view”.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="match_parent">
 <com.google.android.libraries.navigation.NavigationView
     android:id="@+id/navigation_view"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
      />
</RelativeLayout>

Konfigurowanie aktywności Nawigacja

W Android Studio otwórz w edytorze plik MainActivity.kt.

Dodaj podstawowy kod konfiguracji, aby zapewnić prawidłowe działanie nawigacji w aplikacji. W pliku MainActivity.kt wprowadź te zmiany:

  1. Zadeklaruj zmienną w klasie MainActivity, aby odwoływać się do NavigationView:
private lateinit var navView: NavigationView
  1. Dodaj do metody onCreate() kod, aby uzyskać odwołanie do NavigationView:
navView = findViewById(R.id.navigation_view)
navView.onCreate(savedInstanceState)
  1. Dodaj do metody onCreate() kod, który zapewni, że ekran pozostanie włączony podczas nawigacji:
// Ensure the screen stays on during nav.
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
  1. Zmodyfikuj kod, który wywołuje ViewCompat.setOnApplyWindowInsetsListener, aby odwoływał się do identyfikatora NavigationView.
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.navigation_view)) { v, insets ->
  val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
  v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
  insets
}
  1. Dodaj do klasy metodę showToast(), aby wyświetlać użytkownikowi opinie:
private fun showToast(errorMessage: String) {
   Toast.makeText(this@MainActivity, errorMessage, Toast.LENGTH_LONG).show()
}

7. Inicjowanie pakietu Navigation SDK

Po zakończeniu podstawowej konfiguracji aktywności Navigation możesz zainicjować pakiet SDK Navigation. Aby to zrobić, dodaj do pliku MainActivity.kt ten kod:

/** Starts the Navigation API, capturing a reference when ready. */
@SuppressLint("MissingPermission")
private fun initializeNavigationApi() {
   NavigationApi.getNavigator(
       this,
       object : NavigatorListener {
           override fun onNavigatorReady(navigator: Navigator) {
               // store a reference to the Navigator object
               mNavigator = navigator
               // code to start guidance will go here
           }

           override fun onError(@NavigationApi.ErrorCode errorCode: Int) {
               when (errorCode) {
                   NavigationApi.ErrorCode.NOT_AUTHORIZED -> {
                       // Note: If this message is displayed, you may need to check that
                       // your API_KEY is specified correctly in AndroidManifest.xml
                       // and is been enabled to access the Navigation API
                       showToast(
                           "Error loading Navigation API: Your API key is " +
                                   "invalid or not authorized to use Navigation."
                       )
                   }
                   NavigationApi.ErrorCode.TERMS_NOT_ACCEPTED -> {
                       showToast(
                           "Error loading Navigation API: User did not " +
                                   "accept the Navigation Terms of Use."
                       )
                   }
                   else -> showToast("Error loading Navigation API: $errorCode")
               }
           }
       },
   )

}

Ten kod tworzy nową metodę o nazwie initializeNavigationApi(). Ta metoda pobiera odwołanie do obiektu Navigator, wywołując metodę NavigationApi.getNavigator(), i implementuje interfejs NavigatorListener do obsługi wywołania zwrotnego.

Zwróć uwagę, że po zainicjowaniu interfejsu Navigation API zostanie wywołana metoda NavigationListener.onNavigatorReady z obiektem Navigator przekazanym jako parametr. Powyższy kod zaktualizuje zadeklarowaną wcześniej zmienną mNavigator za pomocą zainicjowanego obiektu Navigator, który jest przekazywany do tej metody.

Na koniec dodaj wywołanie metody initializeNavigationApi z metody onLocationPermissionGranted.

private fun onLocationPermissionGranted() {
   initializeNavigationApi()
}

8. Dodawanie detektorów kluczowych zdarzeń nawigacyjnych

Gdy użytkownicy postępują zgodnie z wskazówkami, pakiet Navigation SDK uruchamia zdarzenia, które mogą powiadamiać aplikację o kluczowych zmianach stanu na trasie, np. gdy użytkownik zmieni trasę lub dotrze do celu. W pliku MainActivity.kt dodaj detektory do obsługi tych zdarzeń:

  1. W klasie MainActivity zadeklaruj 2 zmienne, które będą odwoływać się do obiektów detektora zdarzeń:
private var arrivalListener: Navigator.ArrivalListener? = null
private var routeChangedListener: Navigator.RouteChangedListener? = null
  1. Dodaj metodę registerNavigationListeners(), aby skonfigurować odbiorniki po zainicjowaniu obiektu Navigator. Ta metoda wywołuje funkcję Navigator.clearDestinations(), aby zresetować NavigationView po wywołaniu zdarzenia Arrival:
/**
* Registers a number of example event listeners that show an on screen message when certain
* navigation events occur (e.g. the driver's route changes or the destination is reached).
*/
private fun registerNavigationListeners() {
   withNavigatorAsync {
       arrivalListener =
           Navigator.ArrivalListener { // Show an onscreen message
               showToast("User has arrived at the destination!")
               mNavigator?.clearDestinations()
           }
       mNavigator?.addArrivalListener(arrivalListener)

       routeChangedListener =
           Navigator.RouteChangedListener { // Show an onscreen message when the route changes
               showToast("onRouteChanged: the driver's route changed")
           }
       mNavigator?.addRouteChangedListener(routeChangedListener)
   }
}
  1. Dodaj wywołanie funkcji registerNavigationListeners() z kodu wywołania zwrotnego onNavigatorReady w metodzie initializeNavigationApi:
override fun onNavigatorReady(navigator: Navigator) {
   // store a reference to the Navigator object
   mNavigator = navigator

   //listen for events en route
   registerNavigationListeners()


}
  1. Skonfiguruj interfejs. Gdy nawigacja jest włączona, możesz kontrolować różne aspekty interfejsu nawigacji. Jedną z ważnych opcji dostosowywania jest pozycja kamery. Dodaj wywołanie metody setTaskRemovedBehaviour obiektu navigator zwróconego w onNavigatorReady w ten sposób: Jeśli aplikacja zostanie przesunięta, wskazówki i powiadomienia zostaną zakończone:
// Disables the guidance notifications and shuts down the app and background service
// when the user dismisses/swipes away the app from Android's recent tasks.
navigator.setTaskRemovedBehavior(Navigator.TaskRemovedBehavior.QUIT_SERVICE)
  1. Dodaj wywołanie GoogleMap.followMyLocation, aby określić CameraPerspective. Dostęp do GoogleMap uzyskuje się za pomocą metody NavigatorView.getMapAsync() w ten sposób:
navView.getMapAsync {
   googleMap  ->
   googleMap.followMyLocation(GoogleMap.CameraPerspective.TILTED)
}
  1. Aby zapewnić płynne działanie funkcji nawigacji w całym cyklu życia aplikacji, zaimplementuj w klasie MainActivity te metody:
override fun onSaveInstanceState(savedInstanceState: Bundle) {
   super.onSaveInstanceState(savedInstanceState)

   navView.onSaveInstanceState(savedInstanceState)
}

override fun onTrimMemory(level: Int) {
   super.onTrimMemory(level)
   navView.onTrimMemory(level)
}

override fun onStart() {
   super.onStart()
   navView.onStart()
}

override fun onResume() {
   super.onResume()
   navView.onResume()
}

override fun onPause() {
   navView.onPause()
   super.onPause()
}

override fun onConfigurationChanged(configuration: Configuration) {
   super.onConfigurationChanged(configuration)
   navView.onConfigurationChanged(configuration)
}

override fun onStop() {
   navView.onStop()
   super.onStop()
}

override fun onDestroy() {
   navView.onDestroy()
   withNavigatorAsync {
       // Unregister event listeners to avoid memory leaks.
       if (arrivalListener != null) {
           navigator.removeArrivalListener(arrivalListener)
       }
       if (routeChangedListener != null) {
           navigator.removeRouteChangedListener(routeChangedListener)
       }

       navigator.simulator?.unsetUserLocation()
       navigator.cleanup()
   }
   super.onDestroy()
}

9. Ustaw miejsce docelowe

Możesz teraz ustawić miejsce docelowe i rozpocząć nawigację. W pliku MainActivity.kt wprowadź te zmiany:

  1. Dodaj nową metodę navigateToPlace(), która ustawia miejsce docelowe nawigacji i akceptuje parametr placeId.
/**
* Requests directions from the user's current location to a specific place (provided by the
* Place ID).
*/
private fun navigateToPlace(placeId: String) {

}
  1. W metodzie navigateToPlace() użyj metody Waypoint.builder(), aby utworzyć obiekt Waypoint na podstawie identyfikatora miejsca przekazanego do metody. Obsłuż UnsupportedPlaceIdException, które może zostać zgłoszone w sytuacjach, gdy identyfikator miejsca nie jest przypisany do dokładnego adresu:
val waypoint: Waypoint? =
// Set a destination by using a Place ID (the recommended method)
try {
   Waypoint.builder().setPlaceIdString(placeId).build()
} catch (e: Waypoint.UnsupportedPlaceIdException) {
   showToast("Place ID was unsupported.")
   return
}
  1. Dodaj do metody navigateToPlace() ten kod, aby ustawić miejsce docelowe za pomocą punktu na trasie:
val pendingRoute = mNavigator?.setDestination(waypoint)

// Set an action to perform when a route is determined to the destination
pendingRoute?.setOnResultListener { code ->
   when (code) {
       RouteStatus.OK -> {
           // Code to start guidance will go here
       }

       RouteStatus.ROUTE_CANCELED -> showToast("Route guidance canceled.")
       RouteStatus.NO_ROUTE_FOUND,
       RouteStatus.NETWORK_ERROR ->
           // TODO: Add logic to handle when a route could not be determined
           showToast("Error starting guidance: $code")

       else -> showToast("Error starting guidance: $code")
   }
}

Obiekt Navigator ma metodę setDestinations(), która może przyjmować różne parametry. Najprostszą opcją jest podanie Waypoint. Domyślnie będzie to tryb transportu DRIVING, odpowiedni dla samochodów 4-kołowych. Metoda setDestinations() zwraca obiekt ListenableResultFuture zawierający obiekt RouteStatus. Ikona RouteStatus wskaże, czy znaleziono trasę do miejsca docelowego, i umożliwi Ci obsługę różnych stanów błędów, jeśli nie.

  1. Wprowadź dodatkowe zmiany w konfiguracji, aby poprawić wrażenia użytkowników nawigacji:
// Hide the toolbar to maximize the navigation UI
supportActionBar?.hide()

// Enable voice audio guidance (through the device speaker)
mNavigator?.setAudioGuidance(Navigator.AudioGuidance.VOICE_ALERTS_AND_GUIDANCE)


// Simulate vehicle progress along the route (for demo/debug builds)
if (BuildConfig.DEBUG) {
   mNavigator?.simulator?.simulateLocationsAlongExistingRoute(
       SimulationOptions().speedMultiplier(5f)
   )
}

Zmiany te obejmują następujące ulepszenia:

  • Ukrywanie paska działań, aby zmaksymalizować miejsce na interfejs nawigacji.
  • włączenie wskazówek głosowych, które będą odczytywać alerty i wskazówki nawigacji;
  • Konfigurowanie symulatora na potrzeby debugowania przez określenie mnożnika prędkości.
  1. Znajdź identyfikator miejsca, które będzie Twoim miejscem docelowym. Najlepiej, aby znajdował się on w pobliżu lokalizacji użytkownika. Użyj narzędzia Google Maps Platform Place ID Finder lub uzyskaj identyfikator miejsca z wywołania interfejsu Places API.

Jeśli symulujesz nawigację, możesz ustawić lokalizację użytkownika w kodzie lub pobrać ją z podłączonego urządzenia. W tym laboratorium kodowym założymy, że symulujesz lokalizację w Londynie w Wielkiej Brytanii.

  1. Dodaj do klasy MainActivity obiekt towarzyszący, aby przechowywać lokalizację początkową i identyfikator miejsca. W ćwiczeniach z programowania użyjemy lokalizacji początkowej w Londynie i identyfikatora miejsca Trafalgar Square:
companion object{
   const val TRAFALGAR_SQUARE ="ChIJH-tBOc4EdkgRJ8aJ8P1CUxo" //London, UK
   val startLocation = LatLng(51.345678, -0.1234456)
}
  1. Dodaj wywołanie metody navigateToPlace() z wywołania zwrotnego onNavigatorReady w metodzie initializeNavigationApi i dodaj gałąź logiki, która będzie wykonywana w trybie debugowania i ustawi lokalizację użytkownika:
// Disables the guidance notifications and shuts down the app and background service
// when the user dismisses/swipes away the app from Android's recent tasks.
navigator.setTaskRemovedBehavior(Navigator.TaskRemovedBehavior.QUIT_SERVICE)

mNavigator = navigator

if (BuildConfig.DEBUG) {
   mNavigator?.simulator?.setUserLocation(MainActivity.startLocation)
}
//listen for events en route
registerNavigationListeners()

navView.getMapAsync {
   googleMap  ->
   googleMap.followMyLocation(GoogleMap.CameraPerspective.TILTED)
}

//navigate to a destination
navigateToPlace(MainActivity.TRAFALGAR_SQUARE)

10. Tworzenie i uruchamianie kodu

Przy pierwszym uruchomieniu aplikacji musisz przyznać jej uprawnienia do lokalizacji i zaakceptować warunki korzystania z pakietu Navigation SDK.

Uwaga: uruchomienie aplikacji spowoduje wywołanie metody setDestinations(), która po użyciu pierwszych 1000 miejsc docelowych wiąże się z opłatą. Więcej informacji znajdziesz w artykule Wykorzystanie i rozliczenia.

93aa433000a14dfc.png

Okno dialogowe warunków korzystania z usługi Navigation SDK.

Ustawianie lokalizacji

Domyślnie emulowane urządzenie może mieć ustawioną lokalizację w kampusie Google w Mountain View w Kalifornii, chyba że lokalizacja została ustawiona w kodzie lub w oknie właściwości emulatora.

Jeśli tak jest, aplikacja może nie znaleźć trasy do skonfigurowanego identyfikatora miejsca (domyślnie jest to Opera w Sydney w Australii). Wskaże to komunikat „Nie znaleziono trasy” wyświetlany przez metodę showToast().

Widok mapy w aplikacji Nawigacja przedstawiający biuro Google w Mountain View w Kalifornii.

Zakodowanie na stałe lokalizacji początkowej

Aby ustawić inną lokalizację w kodzie, dodaj ten wiersz do metody navigateToPlace() w pliku MainActivity.kt przed wywołaniem funkcji mNavigator.startGuidance():

mNavigator?.simulator?.setUserLocation(startLocation)

Uruchamianie emulatora w wybranej domyślnej lokalizacji

Aby ustawić inną lokalizację w emulatorze urządzenia, uruchom go, jeśli jeszcze nie działa, i kliknij menu z 3 kropkami z etykietką „Rozszerzone ustawienia”. W wyświetlonym oknie znajduje się opcja menu „Lokalizacja”.

Jeśli np. jako miejsce docelowe używasz identyfikatora miejsca Sydney Opera House, wybierz lokalizację w Sydney w Australii. Na przykład wyszukaj „Bondi Beach”, wybierz sugestię i w prawym dolnym rogu okna kliknij „Zapisz lokalizację”. Możesz też kliknąć „Zapisz punkt”, aby dodać lokalizację do zapisanej listy do wykorzystania w przyszłości.

Okno dialogowe Rozszerzone elementy sterujące w Menedżerze urządzeń z Androidem, w którym widać selektor miejsca i mapę wyśrodkowaną na plaży Bondi w Australii.

Jeśli jako miejsce docelowe ustawisz inny identyfikator miejsca, wybierz lokalizację w pobliżu, aby symulowana trasa była realistyczna i nie za długa, co ułatwi debugowanie.

Uruchom ponownie aplikację. Powinna teraz przejść do miejsca docelowego.

Zrzut ekranu aplikacji do nawigacji, która podaje wskazówki dotyczące miejsca docelowego.

11. Gratulacje!

To koniec tego ćwiczenia. Gratulacje – dotarliśmy do celu! Pozdrawiamy :-)

55812f33256c0596.png

12. Możesz zrobić jeszcze więcej

Jeśli chcesz dalej rozwijać swoją aplikację, zapoznaj się z poniższymi tematami, aby znaleźć inspirację.