สร้างแอปการนำทางสำหรับ Android อย่างง่ายด้วย SDK การนำทางของแพลตฟอร์ม Google Maps

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 โดยทําตามวิธีการเริ่มต้นใช้งาน Google Maps Platform ที่ https://developers.google.com/maps/gmp-get-started

เลือกโปรเจ็กต์ Google Cloud ในคอนโซล

ใน Cloud Console ให้คลิกเมนูแบบเลื่อนลงของโปรเจ็กต์และเลือกโปรเจ็กต์ที่ต้องการใช้สำหรับ Codelab นี้

เมนูแบบเลื่อนลงของตัวเลือกโปรเจ็กต์ในคอนโซล Google Cloud

เปิดใช้ Navigation SDK ในโปรเจ็กต์

เปิดใช้ Google Maps Platform API และ SDK ที่จำเป็นสำหรับ Codelab นี้ใน Google Cloud Marketplace

ไปที่ API และ บริการ > ไลบรารีใน Google Cloud Console และค้นหา "Navigation SDK"

คุณจะเห็นผลการค้นหา 1 รายการ

หน้าจอไลบรารี API ในคอนโซล Google Cloud ที่แสดงหน้า Navigation SDK

คลิกผลการค้นหา Navigation SDK เพื่อเปิดหน้ารายละเอียดผลิตภัณฑ์ คลิกปุ่ม "เปิดใช้" เพื่อเปิดใช้ SDK ในโปรเจ็กต์

ทําขั้นตอนนี้ซ้ำสําหรับ Google Maps SDK สําหรับ Android

สร้างคีย์ API

สร้างคีย์ API ในหน้าข้อมูลเข้าสู่ระบบของ Cloud Console คุณสามารถทำตามขั้นตอนในขั้นตอนที่ 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 นี้ โปรเจ็กต์เริ่มต้นมี UI ของแอปพื้นฐานและการกำหนดค่าบิลด์ แต่ไม่มีการเพิ่ม 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 ลงในแอป คุณต้องแก้ไข app-level build.gradle.kts เพื่อดึงข้อมูล Navigation SDK จากที่เก็บ Maven ของ Google และกำหนดค่าหมายเลขเวอร์ชัน

สร้างตัวแปรในการกำหนดค่าบิลด์เพื่อจัดเก็บหมายเลขเวอร์ชัน Navigation SDK

ตั้งค่าตัวแปรใน build.gradle.kts ระดับแอปเพื่อเก็บค่าของเวอร์ชัน Navigation SDK ที่ใช้ในแอป คุณจึงเปลี่ยนไปใช้เวอร์ชันล่าสุดในอนาคตได้ง่ายๆ

ตรวจสอบบันทึกประจำรุ่น SDK การนำทางเพื่อดูหมายเลขเวอร์ชันล่าสุด

val navSdkVersion by extra("6.0.0")

นอกจากนี้ คุณยังแก้ไขค่าของตัวแปรนี้และตัวแปรอื่นๆ โดยใช้กล่องโต้ตอบที่แสดงในเมนูไฟล์ > โครงสร้างโปรเจ็กต์ > ตัวแปร

668332736b67dc82.png

เพิ่มทรัพยากร Dependency ในการกำหนดค่าบิลด์

ตอนนี้ให้เพิ่มทรัพยากร Dependency ของ API ต่อไปนี้ไปยังบล็อกทรัพยากร Dependency ในระดับแอป build.gradle.kts.เวอร์ชันที่ใช้จะเป็นค่า ${navSdkVersion} ซึ่งคุณเพิ่งตั้งค่าใน build.gradle.kts ระดับแอป

dependencies {

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

...

เพิ่มคีย์ API

ใช้ปลั๊กอินข้อมูลลับ Gradle เพื่อจัดการคีย์ API

เราขอแนะนำให้ใช้ปลั๊กอิน Secrets Gradle เพื่อจัดการคีย์ API ในแอปอย่างปลอดภัย เพิ่มปลั๊กอินลงในเทมเพลตโปรเจ็กต์เริ่มต้นเป็นทรัพยากร Dependency ในไฟล์ 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 ที่คุณระบุ

เปิดแอป/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. กำหนดค่าสิทธิ์ของแอปและเพิ่ม UI พื้นฐาน

ขอสิทธิ์เข้าถึงตำแหน่งที่แน่นอน

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

เพิ่มกิจกรรมการเปิดตัวด้วย UI พื้นฐาน

เมื่อแอปทำงาน จะต้องมีโค้ดที่ทำงานในช่วงเริ่มต้นเพื่อตรวจสอบว่าผู้ใช้ได้ให้สิทธิ์เข้าถึงตำแหน่งของตนหรือไม่ และจัดการกับแต่ละสถานการณ์ที่เป็นไปได้ รวมถึงขอสิทธิ์ในกรณีที่ยังไม่ได้รับการให้สิทธิ์ โดยให้เพิ่มอินเทอร์เฟซผู้ใช้พื้นฐานลงในแอป Codelab นี้ใช้ UI ที่สร้างขึ้นเมื่อคุณสร้างกิจกรรม Views ใหม่ที่ไม่มีข้อมูลใน Android Studio คุณจะปรับเปลี่ยนการตั้งค่านี้เพื่อตรวจสอบสิทธิ์เข้าถึงตำแหน่งก่อนเพิ่มโค้ดลงในกิจกรรมสำหรับ UI การนำทาง

เปิดไฟล์ MainActivity.kt ในโปรแกรมแก้ไขโค้ดและตรวจสอบโค้ด ซึ่งจะแสดง UI พื้นฐาน

ขอสิทธิ์เข้าถึงตำแหน่งขณะรันไทม์

แอปของคุณจะต้องทริกเกอร์คำขอเข้าถึงตำแหน่งที่แน่นอนก่อนที่ Navigation 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. เพิ่มอินเทอร์เฟซผู้ใช้สำหรับการไปยังส่วนต่างๆ

การเพิ่ม UI การนําทางทำได้ 2 วิธี ได้แก่ 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 ให้ประกาศตัวแปร 2 รายการเพื่ออ้างอิงออบเจ็กต์ Listener เหตุการณ์ ดังนี้
private var arrivalListener: Navigator.ArrivalListener? = null
private var routeChangedListener: Navigator.RouteChangedListener? = null
  1. เพิ่มเมธอด registerNavigationListeners() เพื่อตั้งค่า Listeners เมื่อเริ่มต้นใช้งาน Navigator วิธีนี้จะเรียกใช้ Navigator.clearDestinations() เพื่อรีเซ็ต NavigationView เมื่อเหตุการณ์ 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. เพิ่มการเรียก 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. ในเมธอด navigateToPlace() ให้ใช้เมธอด Waypoint.builder() เพื่อสร้าง Waypoint จากรหัสสถานที่ที่ส่งไปยังเมธอดดังกล่าว จัดการ 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() เพื่อตั้งค่าปลายทางโดยใช้ Waypoint:
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)
   )
}

การเปลี่ยนแปลงเหล่านี้รวมถึงการปรับปรุงต่อไปนี้

  • การซ่อนแถบการทำงานเพื่อเพิ่มพื้นที่สูงสุดสำหรับ UI การนำทาง
  • การเปิดใช้การนำทางด้วยเสียงเพื่อพูดการแจ้งเตือนและคำแนะนำการนำทาง
  • การตั้งค่าเครื่องจำลองสำหรับการแก้ไขข้อบกพร่องโดยระบุตัวคูณความเร็ว
  1. ค้นหารหัสสถานที่ที่จะใช้เป็นปลายทาง ทางที่ดีที่สุดคือไม่ไกลจากสถานที่ตั้งของผู้ใช้จนเกินไป ใช้ยูทิลิตีเครื่องมือค้นหารหัสสถานที่ของ Google Maps Platform หรือรับรหัสสถานที่จากการเรียก Places API

หากกำลังจำลองการนำทาง คุณสามารถตั้งค่าตำแหน่งของผู้ใช้ในโค้ดหรือนำมาจากอุปกรณ์ที่เชื่อมต่อได้ Codelab จะถือว่าคุณกำลังจำลองสถานที่ตั้งในลอนดอน สหราชอาณาจักร

  1. เพิ่มออบเจ็กต์ที่แสดงร่วมกันลงในคลาส MainActivity เพื่อจัดเก็บตำแหน่งเริ่มต้นและรหัสสถานที่ Codelab จะใช้สถานที่เริ่มต้นในลอนดอนและรหัสสถานที่ของ Trafalgar Square
companion object{
   const val TRAFALGAR_SQUARE ="ChIJH-tBOc4EdkgRJ8aJ8P1CUxo" //London, UK
   val startLocation = LatLng(51.345678, -0.1234456)
}
  1. เพิ่มการเรียกใช้เมธอด navigateToPlace() จาก Callback ของ 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 ในเมืองเมาน์เทนวิว รัฐแคลิฟอร์เนีย เว้นแต่คุณจะตั้งค่าตำแหน่งในโค้ดหรือใช้กล่องโต้ตอบพร็อพเพอร์ตี้โปรแกรมจำลอง

หากเป็นเช่นนั้น คุณอาจพบว่าแอปไม่พบเส้นทางไปยังรหัสสถานที่ที่คุณกำหนดค่าไว้ (โดยค่าเริ่มต้นคือ Sydney Opera House, Sydney, Australia) ซึ่งจะมีการระบุโดยข้อความที่ระบุว่า "ไม่พบเส้นทาง" ซึ่งแสดงตามเมธอด showToast()

มุมมองแผนที่ของแอปการนำทางที่แสดงสำนักงานของ Google ในเมืองเมาน์เทนวิว รัฐแคลิฟอร์เนีย

การเขียนโค้ดตำแหน่งเริ่มต้นแบบฮาร์ดโค้ด

หากต้องการตั้งค่าตำแหน่งอื่นในโค้ด ให้เพิ่มบรรทัดต่อไปนี้ในเมธอด navigateToPlace() ใน MainActivity.kt ก่อนเรียก mNavigator.startGuidance():

mNavigator?.simulator?.setUserLocation(startLocation)

การเริ่มโปรแกรมจำลองในตำแหน่งเริ่มต้นที่คุณเลือก

หากต้องการตั้งค่าตำแหน่งอื่นในโปรแกรมจำลองอุปกรณ์ ให้เปิดโปรแกรมจำลองหากยังไม่ได้เปิดอยู่ แล้วคลิกเมนู 3 จุดที่มีเคล็ดลับเครื่องมือ "การควบคุมแบบขยาย" กล่องโต้ตอบที่เปิดขึ้นจะมีตัวเลือกเมนูสำหรับ "ตำแหน่ง"

ตัวอย่างเช่น หากคุณใช้รหัสสถานที่ของโรงอุปรากรซิดนีย์เป็นปลายทาง ให้เลือกสถานที่ในซิดนีย์ ออสเตรเลีย เช่น ค้นหา "หาดนพรัตน์" เลือกคำแนะนำและคลิก "บันทึกตำแหน่ง" ที่ด้านล่างขวาของกล่องโต้ตอบ คุณยังสามารถคลิก "บันทึกจุด" เพื่อเพิ่มสถานที่ตั้งลงในรายการที่บันทึกไว้เพื่อใช้ในอนาคต

กล่องโต้ตอบ Extended Controls ในโปรแกรมจัดการอุปกรณ์ Android ซึ่งแสดงเครื่องมือเลือกสถานที่และแผนที่ที่มีศูนย์กลางอยู่ที่ชายหาดบอนไดในออสเตรเลีย

หากคุณตั้งค่ารหัสสถานที่อื่นเป็นปลายทาง ให้เลือกสถานที่ใกล้เคียงกับรหัสนั้นเพื่อให้เส้นทางจำลองเป็นเส้นทางที่สมจริงและไม่ยาวจนเกินไปเพื่อให้แก้ไขข้อบกพร่องได้ง่าย

รีสตาร์ทแอป แล้วระบบจะนําไปยังปลายทาง

ภาพหน้าจอของแอปการนําทางที่แนะนำเส้นทางไปยังจุดหมาย

11. ยินดีด้วย

คุณดำเนินการ Codelab เสร็จสมบูรณ์แล้ว เยี่ยมมาก คุณมาถึงจุดหมายแล้ว

55812f33256c0596.png

12. สู่ขั้นต่อไป

หากต้องการพัฒนาแอปให้ก้าวไปอีกขั้น ลองดูหัวข้อต่อไปนี้เพื่อเป็นแรงบันดาลใจ