בונים אפליקציית ניווט פשוטה ל-Android בעזרת ה-SDK לניווט בפלטפורמה של מפות Google

1. לפני שמתחילים

ב-Codelab הזה תלמדו איך ליצור אפליקציית Android פשוטה שמשתמשת ב-Navigation SDK של Google Maps Platform כדי לנווט ליעד שהוגדר מראש.

כך תיראה האפליקציה שלכם בסיום.

b6c535afde7abd20.png

דרישות מוקדמות

  • ידע בסיסי בפיתוח אפליקציות ל-Android ב-Kotlin
  • היכרות מסוימת עם מושגים בסיסיים ב-SDK של מפות Google, כמו מפות, מיקומים וקואורדינטות.

מה תלמדו

  • איך ליצור אפליקציית Android פשוטה שמשתמשת ב-Navigation SDK כדי לנווט ליעד.
  • איך משלבים את Navigation SDK ממאגר Google Maven המרוחק
  • איך מנהלים את הרשאות המיקום ואת הסכם המשתמש עם התנאים למשתמשי קצה של Navigation SDK
  • איך מאתחלים את ה-SDK
  • איך מגדירים יעד ומתחילים את ההנחיות לניווט.

מה תצטרכו

  • הגרסה היציבה האחרונה של Android Studio מותקנת. ה-codelab הזה נוצר באמצעות Android Studio Jellyfish. אם אתם משתמשים בגרסה אחרת, יכול להיות שהמראה והפריסה של הממשק והרכיבים יהיו שונים.
  • חשבון Google ופרויקט שמופעל בו חיוב.
  • מכשיר Android במצב פיתוח עם ניפוי באגים ב-USB מופעל, או אמולטור Android. לא משנה באיזו אפשרות תבחרו, היא צריכה לעמוד בדרישות המינימליות של Navigation SDK

2. להגדרה

אם עדיין אין לכם חשבון ב-Google Cloud Platform ופרויקט בענן עם חיוב מופעל, אתם צריכים להגדיר את הפרויקט ב-Google Cloud לפי ההוראות לתחילת העבודה עם Google Maps Platform https://developers.google.com/maps/gmp-get-started

בוחרים את פרויקט הענן ב-Google Cloud במסוף.

ב-Cloud Console, לוחצים על התפריט הנפתח של הפרויקט ובוחרים את הפרויקט שבו רוצים להשתמש ב-codelab הזה.

התפריט הנפתח לבחירת הפרויקט במסוף Google Cloud.

הפעלת Navigation SDK בפרויקט

מפעילים את ממשקי ה-API וערכות ה-SDK של Google Maps Platform שנדרשים ל-Codelab הזה ב-Google Cloud Marketplace.

במסוף Google Cloud, עוברים אל APIs & Services (ממשקי API ושירותים) > Library (ספרייה) ומחפשים את Navigation SDK.

אמורה להופיע תוצאת חיפוש אחת.

צילום מסך של API Library במסוף Google Cloud, שבו מוצג הדף של Navigation SDK.

לוחצים על התוצאה של Navigation SDK כדי לפתוח את דף פרטי המוצר. לוחצים על הלחצן Enable (הפעלה) כדי להפעיל את ה-SDK בפרויקט.

חוזרים על התהליך הזה עבור Google Maps SDK ל-Android.

יצירת מפתח API

יוצרים מפתח API בדף Credentials במסוף Cloud. אפשר לפעול לפי השלבים שבשלב 3 בקטע 'מדריך למתחילים' במאמר תחילת העבודה עם Google Maps Platform. כל הבקשות אל Google Maps Platform דורשות מפתח API.

3. קבלת קבצי הפרויקט לדוגמה

בקטע הזה מוסבר איך להגדיר פרויקט בסיסי ריק ב-Android Studio על ידי שיבוט קבצים ממאגר GitHub של ה-codelab הזה. במאגר Github יש גרסאות של קוד ה-codelab לפני ואחרי השינויים. ה-codelab יתחיל עם תבנית פרויקט ריקה ויתפתח למצב הסופי. אם נתקעתם, תוכלו להשתמש בפרויקט המוגמר במאגר כהפניה.

משכפלים את מאגר Github הזה כדי לקבל את הקוד ל-Codelab הזה.

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

אם לא התקנתם את git, לחצו על הלחצן הזה כדי לקבל את הקוד:

כדי שתוכלו להתחיל לעבוד כמה שיותר מהר, במאגר יש קוד לתחילת הדרך בתיקייה Starter שיעזור לכם לעקוב אחרי ההוראות ב-Codelab הזה. פרויקט המתחילים מספק ממשק משתמש בסיסי לאפליקציה ותצורת build, אבל לא נוסף אליו Navigation SDK. יש גם פרויקט Solution מוכן מראש, למקרה שתרצו לדלג קדימה או לבדוק את ההתקדמות שלכם בכל שלב.

פתיחת המאגר המשוכפל ב-Android Studio

אחרי שמשכפלים את המאגר באופן מקומי, משתמשים ב-Android Studio כדי לפתוח את התיקייה Starter כפרויקט קיים.

  1. בתיבת הדו-שיח 'ברוכים הבאים ל-Android Studio', לוחצים על הלחצן 'פתיחה'.
  2. עוברים לתיקייה שבה שמרתם את המאגר המשוכפל ובוחרים את התיקייה Starter בתוך התיקייה codelab-navigation-101-android-kotlin ברמה העליונה.
  3. בודקים שהפרויקט נבנה ומופעל.

הוספה של מכשיר וירטואלי או חיבור של מכשיר פיזי

כדי לחבר מכשיר Android למחשב, פועלים לפי ההוראות של Android Studio בנושא הפעלת אפליקציות במכשיר חומרה. אפשרות נוספת היא להגדיר מכשיר וירטואלי באמצעות מנהל המכשירים הווירטואליים (AVD) של Android. כשבוחרים אמולטור, חשוב לוודא שבוחרים תמונה שכוללת את Google APIs.

ב-Android Studio, לוחצים על האפשרות 'הפעלה' בתפריט או על סמל לחצן ההפעלה. בוחרים מכשיר לפי ההנחיות.

4. הוספת Navigation SDK לאפליקציה

הוספה של ספריית Navigation SDK ומפתח ה-API לפרויקט

כדי להוסיף את ספריית Navigation SDK לאפליקציה, צריך לשנות את קובץ ה-build ברמת האפליקציה build.gradle.kts כדי לאחזר את Navigation SDK ממאגר Google Maven ולהגדיר מספר גרסה.

יוצרים משתנה בהגדרות ה-build כדי לאחסן את מספר הגרסה של Navigation SDK.

מגדירים משתנה בקובץ build.gradle.kts ברמת האפליקציה שיכיל את הערך של גרסת Navigation SDK שבה נעשה שימוש באפליקציה, כדי שיהיה קל לעבור לגרסה האחרונה בעתיד.

מספר הגרסה העדכני מופיע בהערות הגרסה של Navigation SDK.

val navSdkVersion by extra("6.0.0")

אפשר גם לשנות את הערכים של המשתנה הזה ושל משתנים אחרים באמצעות תיבת הדו-שיח שנמצאת ב'קובץ' > 'מבנה הפרויקט' > 'משתנים':

668332736b67dc82.png

הוספת תלות להגדרת ה-build

עכשיו מוסיפים את התלות הבאה ב-API לבלוק התלויות בקובץ build.gradle.kts. ברמת האפליקציה. הגרסה שתשמש תהיה הערך של ${navSdkVersion} שהגדרתם זה עתה בקובץ build.gradle.kts ברמת האפליקציה:

dependencies {

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

...

הוספת מפתח API

שימוש בפלאגין Secrets Gradle לניהול מפתח ה-API

מומלץ להשתמש בתוסף Secrets Gradle כדי לנהל את מפתח ה-API באפליקציה בצורה מאובטחת. התוסף נוסף לתבנית הפרויקט הראשונית כתלות בקובץ build.gradle.kts ברמה העליונה.

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

פותחים את הקובץ secrets.properties בספרייה ברמה העליונה ומחליפים את הערך YOUR_API_KEY במפתח ה-API שלכם. שומרים את המפתח בקובץ הזה כי secrets.properties לא נכלל בבדיקה במערכת לניהול גרסאות.

MAPS_API_KEY=YOUR_API_KEY

מידע נוסף בנושא הזה זמין במאמר הוספת מפתח API לאפליקציה במסמכי התיעוד של Navigation SDK.

אימות התוכן של הקובץ local.defaults.properties

הפרויקט הריק מכיל גם קובץ local.defaults.properties בספרייה ברמה העליונה, באותה תיקייה שבה נמצא קובץ secrets.properties. פותחים אותו ומסתכלים על הקוד הבא.

MAPS_API_KEY=DEFAULT_API_KEY

המאפיין הזה נועד לספק ערך גיבוי למאפיין MAPS_API_KEY למקרה ש-secrets.properties לא יתווסף לפרויקט, כדי שהבנייה לא תיכשל. אין צורך לערוך את הקובץ הזה. אם ההגדרה של secrets.properties MAPS_API_KEY לא נמצאת, ערך ברירת המחדל יגרום להפסקת הפעלת האפליקציה בזמן הריצה, עם שגיאה במפתח ה-API.

בודקים שקובץ ה-Manifest של Android משתמש במפתח ה-API שציינתם

פותחים את הקובץ app/src/main/AndroidManifest.xml. אפשר לראות שהמאפיין MAPS_API_KEY משמש להגדרת מפתח ה-API של האפליקציה:

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

פותחים את קובץ build.gradle.kts ברמת האפליקציה ומחפשים את הנכס secrets.

ההגדרה propertiesFileName של הפלאגין צריכה להיות secrets.properties, והערך של defaultPropertiesFileName צריך להיות 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"
}

שומרים את כל הקבצים ומסנכרנים את הפרויקט עם Gradle.

5. הגדרת הרשאות שניתנות לאפליקציה והוספת ממשק משתמש בסיסי

שליחת בקשה להרשאת מיקום מדויק

ה-SDK של הניווט מסתמך על אותות GPS כדי לפעול, ולכן האפליקציה צריכה לבקש מהמשתמשים להעניק גישה לנתוני מיקום מדויקים. מוסיפים את ההרשאה לגישה למיקום מדויק כצאצא של רכיב <manifest> בקובץ 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>

מידע נוסף על הרשאות מיקום ב-Android זמין בקטע בקשת הרשאות מיקום בתיעוד למפתחים של Android.

כדי להריץ את האפליקציה במכשיר Android 14, צריך לבקש את ההרשאה 'מיקום של שירות שפועל בחזית' על ידי הוספת התג uses-permission הבא באותו מיקום שבו נמצאת ההרשאה לגישה למיקום מדויק:

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

הוספת פעילות הפעלה עם ממשק משתמש בסיסי

כשהאפליקציה פועלת, היא צריכה להריץ קוד במהלך ההפעלה כדי לבדוק אם המשתמש נתן הרשאה לגשת למיקום שלו, ולטפל בכל תרחיש אפשרי. אם ההרשאה עדיין לא ניתנה, האפליקציה צריכה לבקש אותה. כדי לעשות את זה, מוסיפים לאפליקציה ממשק משתמש בסיסי. ב-Codelab הזה נעשה שימוש בממשק המשתמש שנוצר כשיוצרים פעילות חדשה וריקה של Views ב-Android Studio. תצטרכו להתאים את הקוד הזה כדי לבצע את בדיקת הרשאת המיקום לפני שמוסיפים קוד לפעילות של ממשק המשתמש לניווט.

פותחים את הקובץ MainActivity.kt בעורך הקוד ובודקים את הקוד, שכולל ממשק משתמש בסיסי.

שליחת בקשה להרשאות גישה למיקום בזמן ריצה

האפליקציה תצטרך להפעיל את הבקשה לגישה למיקום מדויק לפני שה-SDK של הניווט יאותחל.

כדי לוודא שהבדיקה הזו מתבצעת כשהאפליקציה מופעלת, מוסיפים קוד מסוים למחלקה MainActivity, בשיטה onCreate() שהוחלפה של הפעילות.

הקוד הבא בודק אם המשתמש העניק הרשאת מיקום מדויק. אם לא, המערכת מבקשת את ההרשאה. מוסיפים את הקוד הזה בתוך השיטה 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

מוסיפים פונקציה חדשה למחלקה MainActivity, שנקראת onLocationPermissionGranted, שתטפל בתוצאה כשהמשתמש ייתן הרשאה לשתף את המיקום שלו. בשלבים הבאים נוסיף כאן קוד כדי להפעיל פעילות ניווט חדשה.

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

יוצרים את הפרויקט. אם יש שגיאות בבנייה, צריך למצוא ולתקן אותן.

מריצים את הפרויקט במכשיר וירטואלי חדש. תיבת הדו-שיח של בקשת ההרשאה אמורה להופיע כשהאפליקציה מותקנת ומתחילה לפעול.

6. הוספת ממשק משתמש לניווט

יש שתי דרכים להוסיף ממשק משתמש של ניווט: SupportNavigationFragment או NavigationView.

לצורך פשטות, ב-codelab נעשה שימוש ב-NavigationView.

עריכת הפריסה

עורכים את res/layout/activity_main.xml כדי להוסיף פריסה ל-NavigationView.

  1. פותחים את הקובץ ועוברים לתצוגת הקוד.
  2. מחליפים את כל התוכן של הקובץ בפריסה חדשה של NavigationView בתוך RelativeLayout, כמו בדוגמה שלמטה. מכיוון שרק תוסיפו תצוגת ניווט לאפליקציה, פריסה פשוטה תספיק.
  3. נותנים ל-NavigationView מזהה של @+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>

הגדרה של פעילות הניווט

ב-Android Studio, פותחים את הקובץ MainActivity.kt בעורך.

מוסיפים קוד הגדרה בסיסי כדי לוודא שחוויית הניווט פועלת בצורה תקינה באפליקציה. בקובץ MainActivity.kt, מבצעים את השינויים הבאים:

  1. מצהירים על משתנה במחלקה MainActivity כדי להפנות אל NavigationView:
private lateinit var navView: NavigationView
  1. מוסיפים קוד לשיטה onCreate() כדי לקבל הפניה אל NavigationView:
navView = findViewById(R.id.navigation_view)
navView.onCreate(savedInstanceState)
  1. מוסיפים קוד לשיטה onCreate() כדי לוודא שהמסך יישאר דולק במהלך ההנחיות לניווט:
// Ensure the screen stays on during nav.
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
  1. עורכים את הקוד שקורא ל-ViewCompat.setOnApplyWindowInsetsListener כדי להפנות למזהה של 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. מוסיפים שיטה showToast() לכיתה כדי להציג משוב למשתמש:
private fun showToast(errorMessage: String) {
   Toast.makeText(this@MainActivity, errorMessage, Toast.LENGTH_LONG).show()
}

7. אתחול Navigation SDK

אחרי שמשלימים את ההגדרה הבסיסית של פעילות הניווט, אפשר לאתחל את Navigation SDK. כדי לעשות את זה, מוסיפים את הקוד הבא לקובץ MainActivity.kt:

/** 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")
               }
           }
       },
   )

}

הקוד הזה יוצר שיטה חדשה שנקראת initializeNavigationApi(). השיטה הזו מקבלת הפניה לאובייקט Navigator על ידי קריאה ל-NavigationApi.getNavigator(), ומטמיעה NavigatorListener כדי לטפל בקריאה החוזרת.

שימו לב: כשמפעילים את Navigation API, הפונקציה NavigationListener.onNavigatorReady מופעלת, ואובייקט Navigator מועבר כפרמטר. הקוד שלמעלה יעדכן את המשתנה mNavigator שהצהרתם עליו קודם לכן באובייקט Navigator שאותחל ומועבר לשיטה הזו.

לבסוף, מוסיפים קריאה לשיטה initializeNavigationApi מהשיטה onLocationPermissionGranted.

private fun onLocationPermissionGranted() {
   initializeNavigationApi()
}

8. הוספת פונקציות listener לאירועי ניווט באמצעות מקשים

כשהמשתמשים פועלים לפי ההנחיות, Navigation SDK מפעיל אירועים שיכולים להודיע לאפליקציה על שינויים חשובים בסטטוס במהלך הנסיעה, למשל כשהמשתמש משנה את המסלול או מגיע ליעד. בקובץ MainActivity.kt, מוסיפים פונקציות listener לטיפול באירועים האלה:

  1. בתוך המחלקה MainActivity, מצהירים על שני משתנים להפניה לאובייקטים של event listener:
private var arrivalListener: Navigator.ArrivalListener? = null
private var routeChangedListener: Navigator.RouteChangedListener? = null
  1. מוסיפים registerNavigationListeners() method כדי להגדיר את ה-listeners כשה-Navigator מאותחל. ה-method הזו קוראת ל-Navigator.clearDestinations() כדי לאפס את NavigationView כשמופעל אירוע ההגעה:
/**
* 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. מוסיפים קריאה ל-registerNavigationListeners() מקוד הקריאה החוזרת onNavigatorReady בשיטה initializeNavigationApi:
override fun onNavigatorReady(navigator: Navigator) {
   // store a reference to the Navigator object
   mNavigator = navigator

   //listen for events en route
   registerNavigationListeners()


}
  1. הגדרת ממשק המשתמש. אתם יכולים לשלוט בהיבטים שונים של ממשק המשתמש של הניווט כשההנחיה פועלת. אחד מהשינויים החשובים שאפשר לבצע הוא מיקום המצלמה. מוסיפים קריאה לשיטה setTaskRemovedBehaviour של האובייקט navigator שמוחזר ב-onNavigatorReady באופן הבא. הפעולה הזו תפסיק את ההנחיות וההתראות אם תסירו את האפליקציה בהחלקה:
// 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. מוסיפים קריאה ל-GoogleMap.followMyLocation כדי לציין CameraPerspective. הגישה אל GoogleMap מתבצעת באמצעות השיטה NavigatorView.getMapAsync() באופן הבא:
navView.getMapAsync {
   googleMap  ->
   googleMap.followMyLocation(GoogleMap.CameraPerspective.TILTED)
}
  1. כדי לוודא שהניווט פועל בצורה חלקה לאורך מחזור החיים של האפליקציה, מטמיעים את השיטות הבאות במחלקה MainActivity:
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. הגדרת יעד

עכשיו אפשר להגדיר יעד ולהתחיל בניווט. בקובץ MainActivity.kt, מבצעים את השינויים הבאים:

  1. מוסיפים שיטה חדשה navigateToPlace() שמגדירה את יעד הניווט ומקבלת פרמטר placeId.
/**
* Requests directions from the user's current location to a specific place (provided by the
* Place ID).
*/
private fun navigateToPlace(placeId: String) {

}
  1. ב-method‏ navigateToPlace(), משתמשים ב-method‏ Waypoint.builder() כדי ליצור Waypoint ממזהה המקום שמועבר ל-method. צריך לטפל ב-UnsupportedPlaceIdException שהפונקציה הזו יכולה להחזיר, במקרים שבהם מזהה המקום לא מוביל לכתובת מדויקת:
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. כדי להגדיר יעד באמצעות ציון דרך, מוסיפים את הקוד הבא לשיטה navigateToPlace():
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")
   }
}

לאובייקט Navigator יש שיטה setDestinations() שיכולה לקבל מגוון פרמטרים. האפשרות הבסיסית ביותר היא לספק Waypoint. ברירת המחדל היא מצב נסיעה של DRIVING, שמתאים לרכבים עם 4 גלגלים. השיטה setDestinations() מחזירה אובייקט ListenableResultFuture שמכיל אובייקט RouteStatus. הסמל RouteStatus יציין אם נמצא מסלול ליעד, ויאפשר לכם לטפל במצבי שגיאה שונים אם לא נמצא מסלול.

  1. מבצעים שינויים נוספים בהגדרות כדי לשפר את חוויית המשתמש בניווט:
// 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)
   )
}

השינויים האלה כוללים את השיפורים הבאים:

  • הסתרת סרגל הפעולות כדי למקסם את המקום לממשק המשתמש של הניווט.
  • הפעלת הנחיות קוליות להשמעת התראות והוראות ניווט.
  • הגדרת הסימולטור לניפוי באגים על ידי ציון מכפיל מהירות.
  1. מאתרים מזהה מקום שישמש כיעד. המיקום הזה צריך להיות קרוב ככל האפשר למיקום של המשתמש. אפשר להשתמש ב-Google Maps Platform Place ID Finder utility או לקבל מזהה מקום מקריאה ל-Places API.

אם אתם מדמים ניווט, אתם יכולים להגדיר את מיקום המשתמש בקוד או לקחת אותו מהמכשיר המחובר. ה-Codelab יניח שאתם מדמים מיקום בלונדון, בריטניה.

  1. מוסיפים אובייקט נלווה לכיתה MainActivity כדי לאחסן מיקום התחלה ומזהה מקום. ב-Codelab הזה נשתמש במיקום התחלתי בלונדון ובמזהה המקום של כיכר טרפלגר:
companion object{
   const val TRAFALGAR_SQUARE ="ChIJH-tBOc4EdkgRJ8aJ8P1CUxo" //London, UK
   val startLocation = LatLng(51.345678, -0.1234456)
}
  1. מוסיפים קריאה לשיטה navigateToPlace() מהקריאה החוזרת onNavigatorReady בתוך השיטה initializeNavigationApi, ומוסיפים ענף של לוגיקה שיפעל במצב ניפוי באגים, שיגדיר את מיקום המשתמש:
// 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. איך בונים ומריצים את הקוד

בפעם הראשונה שמריצים את האפליקציה, צריך לתת לה הרשאות מיקום ולאשר את תנאי השימוש ב-Navigation SDK.

הערה: הפעלת האפליקציה תפעיל את השיטה setDestinations(), שגוררת חיוב אחרי השימוש ב-1,000 היעדים הראשונים. מידע נוסף זמין במאמר בנושא שימוש וחיוב.

93aa433000a14dfc.png

תיבת הדו-שיח של התנאים וההגבלות למשתמש הקצה ב-Navigation SDK.

הגדרת המיקום

כברירת מחדל, יכול להיות שהמיקום של המכשיר המדומה מוגדר לקמפוס של Google ב-Mountain View שבקליפורניה, אלא אם הגדרתם מיקום בקוד או באמצעות תיבת הדו-שיח של מאפייני האמולטור.

אם כן, יכול להיות שהאפליקציה לא תמצא מסלול למזהה המקום שהגדרתם (כברירת מחדל, בית האופרה של סידני, סידני, אוסטרליה). הדבר יצוין בהודעה 'לא נמצא מסלול', שתוצג על ידי שיטת showToast().

תצוגת המפה באפליקציית הניווט שמציגה את המשרד של Google במאונטיין ויו, קליפורניה.

קידוד קשיח של מיקום ההתחלה

כדי להגדיר מיקום אחר בקוד, מוסיפים את השורה הבאה לשיטה navigateToPlace() ב-MainActivity.kt, לפני הקריאה ל-mNavigator.startGuidance():

mNavigator?.simulator?.setUserLocation(startLocation)

הפעלת האמולטור במיקום ברירת מחדל לבחירתכם

כדי להגדיר מיקום אחר באמולטור המכשיר, מפעילים את האמולטור אם הוא לא פועל כבר, ולוחצים על תפריט 3 הנקודות עם תיאור הכלי 'אמצעי בקרה מתקדמים'. בתיבת הדו-שיח שנפתחת יש אפשרות בתפריט בשם 'מיקום'.

לדוגמה, אם אתם משתמשים במזהה המקום של בית האופרה של סידני כיעד, אתם צריכים לבחור מיקום בסידני, אוסטרליה. לדוגמה, מחפשים את "Bondi beach", בוחרים הצעה ולוחצים על "שמירת מיקום" בפינה השמאלית התחתונה של תיבת הדו-שיח. אפשר גם ללחוץ על 'שמירת נקודה' כדי להוסיף את המיקום לרשימה שמורה לשימוש עתידי.

תיבת הדו-שיח &#39;אמצעי בקרה מתקדמים&#39; בניהול מכשיר Android, שבה מוצג כלי לבחירת מקום ומפה שמרכזה בחוף בונדי באוסטרליה.

אם הגדרתם מזהה מקום אחר כיעד, בחרו מיקום קרוב אליו כדי שהמסלול המדומה יהיה ריאלי ולא ארוך מדי, וכך יהיה קל יותר לבצע ניפוי באגים.

מפעילים מחדש את האפליקציה, ועכשיו היא אמורה לנווט ליעד.

צילום מסך של אפליקציית הניווט עם הנחיות להגעה ליעד.

‫11. מעולה!

סיימתם את ה-Codelab הזה. הגעתם ליעד! שיהיה בהצלחה :-)

55812f33256c0596.png

12. עוד צעד אחד קדימה

אם אתם רוצים לפתח את האפליקציה שלכם עוד יותר, כדאי לעיין בנושאים הבאים כדי לקבל השראה.