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

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

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

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

b6c535afde7abd20.png

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

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

מה תלמדו

  • איך יוצרים אפליקציית 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 לפי ההוראות במאמר https://developers.google.com/maps/gmp-get-started (תחילת העבודה עם הפלטפורמה של מפות Google).

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

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

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

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

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

ניווט לממשקי ה-API שירותים > בספרייה במסוף Google Cloud ומחפשים את Navigation SDK.

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

המסך של ספריית ה-API במסוף Google Cloud, שבו מוצג הדף Navigation SDK.

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

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

יצירת מפתח API

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

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

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

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

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 להפעלת אפליקציות במכשיר חומרה. לחלופין, אפשר להגדיר מכשיר וירטואלי באמצעות מנהל מכשיר Android וירטואלי (AVD). כשבוחרים אמולטור, חשוב לבחור תמונה שכוללת את Google APIs.

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

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

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

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

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

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

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

val navSdkVersion by extra("6.0.0")

אפשר גם לשנות את הערכים של המשתנה הזה ומשתנים אחרים באמצעות תיבת הדו-שיח שמופיעה בקטע File (קובץ) > Project Structure (מבנה הפרויקט) > Variables (משתנים):

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

בודקים שהמניפסט של 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. הגדרת הרשאות הניתנות לאפליקציה והוספת ממשק משתמש בסיסי

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

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

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

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

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

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

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

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

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

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

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

כדי לשמור על פשטות, ה-Codelab משתמש ב-NavigationView.

עריכת הפריסה

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

  1. פותחים את הקובץ ומעבירים אותו לתצוגת קוד.
  2. מחליפים את כל התוכן של הקובץ בפריסה חדשה של NavigationView בתוך RelativeLayout, כמו בדוגמה הבאה. בדיוק כמו שמוסיפים תצוגת ניווט לאפליקציה, אפשר לעשות זאת באמצעות פריסה פשוטה.
  3. יש לתת לניווט את המזהה "@+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. צריך להוסיף קוד ל-method onCreate() כדי לקבל הפניה אל NavigationView:
navView = findViewById(R.id.navigation_view)
navView.onCreate(savedInstanceState)
  1. מוסיפים קוד ל-method 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. אתחול ה-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 מופעל, תתבצע קריאה ל-method‏ NavigationListener.onNavigatorReady, עם אובייקט Navigator שמוענק כפרמטר. הקוד שלמעלה יעדכן את המשתנה mNavigator שהצהרת עליו קודם, עם האובייקט Navigator המאתחל שיועבר ל-method הזה.

לבסוף, מוסיפים קריאה ל-method‏ initializeNavigationApi מ-method‏ onLocationPermissionGranted.

private fun onLocationPermissionGranted() {
   initializeNavigationApi()
}

8. הוספת מאזינים לאירועי ניווט מרכזיים

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

  1. במחלקה MainActivity, צריך להצהיר על שני משתנים שיפנו לאובייקטים של event listener:
private var arrivalListener: Navigator.ArrivalListener? = null
private var routeChangedListener: Navigator.RouteChangedListener? = null
  1. יש להוסיף שיטת registerNavigationListeners() כדי להגדיר את המאזינים כשהניווט מופעל. השיטה הזו קוראת לפונקציה 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. מגדירים את ממשק המשתמש. אתם יכולים לשלוט בהיבטים שונים של ממשק המשתמש של הניווט כשההוראות פועלות. אחת מההתאמות האישיות החשובות היא מיקום המצלמה. מוסיפים קריאה ל-method 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 באמצעות ה-method 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. בשיטה navigateToPlace(), משתמשים בשיטה 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. כדי להגדיר יעד באמצעות נקודת ה-Waypoint, צריך להוסיף את הקוד הבא ל-method 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 יש method 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 או לקבל מזהה מקום מקריאה ל-Places API.

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

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

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

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

כתיבה קבועה של מיקום ההתחלה

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

mNavigator?.simulator?.setUserLocation(startLocation)

הפעלת הסימולטור במיקום ברירת המחדל שבחרתם

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

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

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

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

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

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

11. מעולה!

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

55812f33256c0596.png

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

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