1. ก่อนเริ่มต้น
Codelab นี้จะสอนวิธีสร้างแอป Android อย่างง่ายที่ใช้ SDK การนำทางของ Google Maps Platform เพื่อไปยังจุดหมายที่กำหนดค่าไว้ล่วงหน้า
แอปของคุณจะมีลักษณะดังนี้เมื่อเสร็จสิ้น

ข้อกำหนดเบื้องต้น
- มีความรู้พื้นฐานในการพัฒนาแอป 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 นี้

เปิดใช้ Navigation SDK ในโปรเจ็กต์
เปิดใช้ API และ SDK ของ Google Maps Platform ที่จำเป็นสำหรับ Codelab นี้ใน Google Cloud Marketplace
ไปที่ API และบริการ > ไลบรารีใน Google Cloud Console แล้วค้นหา "Navigation SDK"
คุณควรเห็นผลการค้นหา 1 รายการ

คลิกผลลัพธ์ของ 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 เวอร์ชันก่อนและหลัง โค้ดแล็บจะเริ่มต้นด้วยเทมเพลตโปรเจ็กต์ที่ว่างเปล่าและสร้างขึ้นจนถึงสถานะที่เสร็จสมบูรณ์ คุณสามารถใช้โปรเจ็กต์ที่เสร็จสมบูรณ์ในที่เก็บเป็นข้อมูลอ้างอิงได้หากติดขัด
โคลนที่เก็บ 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 เป็นโปรเจ็กต์ที่มีอยู่
- จากกล่องโต้ตอบ "ยินดีต้อนรับสู่ Android Studio" ให้คลิกปุ่ม "เปิด"
- ไปที่โฟลเดอร์ที่คุณบันทึกที่เก็บที่โคลนไว้ แล้วเลือกโฟลเดอร์
Starterภายในโฟลเดอร์ระดับบนสุด "codelab-navigation-101-android-kotlin" - ตรวจสอบว่าโปรเจ็กต์สร้างและเรียกใช้ได้
เพิ่มอุปกรณ์เสมือนหรือเชื่อมต่ออุปกรณ์ฮาร์ดแวร์
หากต้องการเชื่อมต่ออุปกรณ์ Android กับคอมพิวเตอร์ ให้ทำตามวิธีการของ Android Studio เกี่ยวกับวิธีเรียกใช้แอปในอุปกรณ์ฮาร์ดแวร์ หรือจะกำหนดค่าอุปกรณ์เสมือนโดยใช้โปรแกรมจัดการอุปกรณ์เสมือน Android (AVD) ก็ได้ เมื่อเลือกโปรแกรมจำลอง ให้เลือกอิมเมจที่มี Google API
ใน Android Studio ให้คลิกตัวเลือกเมนู Run หรือไอคอนปุ่มเล่น เลือกอุปกรณ์ตามที่ได้รับแจ้ง
4. เพิ่ม Navigation SDK ลงในแอป
เพิ่มไลบรารี Navigation SDK และคีย์ API ลงในโปรเจ็กต์
หากต้องการเพิ่มไลบรารี Navigation SDK ลงในแอป คุณต้องแก้ไข build.gradle.kts ระดับแอปเพื่อดึงข้อมูล Navigation SDK จากที่เก็บ Maven ของ Google และกำหนดค่าหมายเลขเวอร์ชัน
สร้างตัวแปรในการกำหนดค่าบิลด์เพื่อจัดเก็บหมายเลขเวอร์ชัน Navigation SDK
ตั้งค่าตัวแปรใน build.gradle.kts ระดับแอปเพื่อให้มีค่าของเวอร์ชัน Navigation SDK ที่ใช้ในแอป เพื่อให้เปลี่ยนเป็นเวอร์ชันล่าสุดได้ง่ายในอนาคต
ดูหมายเลขเวอร์ชันล่าสุดได้ในบันทึกประจำรุ่นของ Navigation SDK
val navSdkVersion by extra("6.0.0")
นอกจากนี้ คุณยังแก้ไขค่าของตัวแปรนี้และตัวแปรอื่นๆ ได้โดยใช้กล่องโต้ตอบที่อยู่ในส่วนไฟล์ > โครงสร้างโปรเจ็กต์ > ตัวแปร

เพิ่มการอ้างอิงในการกำหนดค่าบิลด์
ตอนนี้ให้เพิ่มทรัพยากร 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 ที่คุณระบุ
เปิด 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. กำหนดค่าสิทธิ์ของแอปและเพิ่ม 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 พื้นฐาน
ขอสิทธิ์เข้าถึงตำแหน่งที่รันไทม์
แอปของคุณจะต้องทริกเกอร์คำขอเข้าถึงตำแหน่งที่แน่นอนก่อนที่จะเริ่มต้น 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
- เปิดไฟล์และเปลี่ยนเป็นมุมมองโค้ด
- แทนที่เนื้อหาทั้งหมดของไฟล์ด้วยเลย์เอาต์ใหม่ของ
NavigationViewภายในRelativeLayoutดังตัวอย่างด้านล่าง เนื่องจากคุณจะเพิ่มเพียงมุมมองการนำทางลงในแอปเท่านั้น เลย์เอาต์ที่เรียบง่ายจึงเพียงพอ - กำหนดรหัส "
@+id/navigation_view" ให้กับ NavigationView
<?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 ให้ทำการเปลี่ยนแปลงต่อไปนี้
- ประกาศตัวแปรใน
MainActivityคลาสเพื่ออ้างอิงNavigationView
private lateinit var navView: NavigationView
- เพิ่มโค้ดบางส่วนลงในเมธอด
onCreate()เพื่อรับการอ้างอิงไปยังNavigationView
navView = findViewById(R.id.navigation_view)
navView.onCreate(savedInstanceState)
- เพิ่มโค้ดบางส่วนลงในเมธอด
onCreate()เพื่อให้แน่ใจว่าหน้าจอจะเปิดอยู่ระหว่างคำแนะนำการนำทาง
// Ensure the screen stays on during nav.
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
- แก้ไขโค้ดที่เรียกใช้
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
}
- เพิ่ม
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 เพื่อจัดการ Callback
โปรดทราบว่าเมื่อมีการเริ่มต้น Navigation API ระบบจะเรียกใช้เมธอด NavigationListener.onNavigatorReady โดยส่งออบเจ็กต์ Navigator เป็นพารามิเตอร์ โค้ดด้านบนจะอัปเดตตัวแปร mNavigator ที่คุณประกาศไว้ก่อนหน้านี้ด้วยออบเจ็กต์ Navigator ที่เริ่มต้นแล้วซึ่งส่งไปยังเมธอดนี้
สุดท้าย ให้เพิ่มการเรียกไปยังเมธอด initializeNavigationApi จากเมธอด onLocationPermissionGranted
private fun onLocationPermissionGranted() {
initializeNavigationApi()
}
8. เพิ่ม Listener สำหรับเหตุการณ์การนำทางที่สำคัญ
เมื่อผู้ใช้ปฏิบัติตามคำแนะนำ SDK การนำทางจะเริ่มเหตุการณ์ที่แจ้งเตือนแอปเกี่ยวกับการเปลี่ยนแปลงสถานะที่สำคัญระหว่างเส้นทางได้ เช่น เมื่อผู้ใช้เปลี่ยนเส้นทางหรือมาถึงจุดหมาย ในไฟล์ MainActivity.kt ให้เพิ่ม Listener เพื่อจัดการเหตุการณ์ต่อไปนี้
- ภายในคลาส
MainActivityให้ประกาศตัวแปร 2 รายการเพื่ออ้างอิงออบเจ็กต์ Listener เหตุการณ์ ดังนี้
private var arrivalListener: Navigator.ArrivalListener? = null
private var routeChangedListener: Navigator.RouteChangedListener? = null
- เพิ่ม
registerNavigationListeners()เพื่อตั้งค่า Listener เมื่อเริ่มต้น Navigator เมธอดนี้จะเรียกใช้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)
}
}
- เพิ่มการเรียกไปยัง
registerNavigationListeners()จากโค้ดเรียกกลับonNavigatorReadyในเมธอดinitializeNavigationApiดังนี้
override fun onNavigatorReady(navigator: Navigator) {
// store a reference to the Navigator object
mNavigator = navigator
//listen for events en route
registerNavigationListeners()
}
- กำหนดค่าอินเทอร์เฟซผู้ใช้ คุณสามารถควบคุมแง่มุมต่างๆ ของอินเทอร์เฟซผู้ใช้การนำทางเมื่อคำแนะนำกำลังทำงาน การปรับแต่งที่สำคัญอย่างหนึ่งคือตำแหน่งกล้อง เพิ่มการเรียกไปยังเมธอด
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)
- เพิ่มการโทรไปยัง
GoogleMap.followMyLocationเพื่อระบุCameraPerspectiveGoogleMapจะเข้าถึงได้ผ่านวิธีการNavigatorView.getMapAsync()ดังนี้
navView.getMapAsync {
googleMap ->
googleMap.followMyLocation(GoogleMap.CameraPerspective.TILTED)
}
- หากต้องการให้ฟังก์ชันการนำทางทำงานได้อย่างราบรื่นตลอดวงจรของแอป ให้ใช้เมธอดต่อไปนี้ในคลาส
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 ให้ทำการเปลี่ยนแปลงต่อไปนี้
- เพิ่ม
navigateToPlace()ใหม่ที่ตั้งค่าปลายทางการนำทางและยอมรับพารามิเตอร์placeId
/**
* Requests directions from the user's current location to a specific place (provided by the
* Place ID).
*/
private fun navigateToPlace(placeId: String) {
}
- ในเมธอด
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
}
- เพิ่มโค้ดต่อไปนี้ลงในเมธอด
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 จะระบุว่าพบเส้นทางไปยังจุดหมายหรือไม่ และช่วยให้คุณจัดการสถานะข้อผิดพลาดต่างๆ ได้หากไม่พบ
- ทำการเปลี่ยนแปลงการกำหนดค่าเพิ่มเติมเพื่อปรับปรุงประสบการณ์ของผู้ใช้ในการนำทาง
// 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 การนำทาง
- เปิดใช้คำแนะนำด้วยเสียงเพื่อพูดการแจ้งเตือนและวิธีการนำทาง
- ตั้งค่าโปรแกรมจำลองสำหรับการแก้ไขข้อบกพร่องโดยการระบุตัวคูณความเร็ว
- ค้นหารหัสสถานที่ที่จะทำหน้าที่เป็นปลายทาง โดยควรอยู่ไม่ไกลจากตำแหน่งของผู้ใช้ ใช้เครื่องมือค้นหารหัสสถานที่ของ Google Maps Platform หรือรับรหัสสถานที่จากการเรียก Places API
หากจำลองการนำทาง คุณสามารถตั้งค่าตำแหน่งของผู้ใช้ในโค้ดหรือรับจากอุปกรณ์ที่เชื่อมต่อ Codelab นี้จะถือว่าคุณจำลองตำแหน่งในลอนดอน สหราชอาณาจักร
- เพิ่มออบเจ็กต์คู่ไปยังคลาส
MainActivityเพื่อจัดเก็บสถานที่เริ่มต้นและรหัสสถานที่ Codelab จะใช้ตำแหน่งเริ่มต้นในลอนดอนและรหัสสถานที่ของจัตุรัสทราฟัลการ์
companion object{
const val TRAFALGAR_SQUARE ="ChIJH-tBOc4EdkgRJ8aJ8P1CUxo" //London, UK
val startLocation = LatLng(51.345678, -0.1234456)
}
- เพิ่มการเรียกไปยังเมธอด
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 รายการแรก ดูข้อมูลเพิ่มเติมได้ที่การใช้งานและการเรียกเก็บเงิน


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

การเขียนโค้ดตำแหน่งเริ่มต้นแบบฮาร์ดโค้ด
หากต้องการตั้งค่าสถานที่อื่นในโค้ด ให้เพิ่มบรรทัดต่อไปนี้ในเมธอด navigateToPlace() ใน MainActivity.kt ก่อนการเรียกใช้ mNavigator.startGuidance()
mNavigator?.simulator?.setUserLocation(startLocation)
การเริ่มต้นโปรแกรมจำลองที่ตำแหน่งเริ่มต้นที่คุณเลือก
หากต้องการตั้งค่าตำแหน่งอื่นในโปรแกรมจำลองอุปกรณ์ ให้เริ่มโปรแกรมจำลองหากยังไม่ได้เรียกใช้ แล้วคลิกเมนู 3 จุดที่มีเคล็ดลับเครื่องมือ "การควบคุมเพิ่มเติม" กล่องโต้ตอบที่เปิดขึ้นจะมีตัวเลือกเมนูสำหรับ "ตำแหน่ง"
เช่น หากคุณใช้รหัสสถานที่ของโรงอุปรากรซิดนีย์เป็นปลายทาง ให้เลือกสถานที่ตั้งในซิดนีย์ ประเทศออสเตรเลีย เช่น ค้นหา "หาดบอนได" เลือกคำแนะนำ แล้วคลิก "บันทึกสถานที่" ที่ด้านขวาล่างของกล่องโต้ตอบ นอกจากนี้ คุณยังคลิก "บันทึกจุด" เพื่อเพิ่มสถานที่ลงในรายการที่บันทึกไว้เพื่อใช้ในอนาคตได้ด้วย

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

11. ยินดีด้วย
คุณทำ Codelab นี้เสร็จแล้ว เก่งมาก คุณมาถึงจุดหมายแล้ว ขอให้สนุกกับการเขียนโค้ด :-)

12. สู่ขั้นต่อไป
หากต้องการพัฒนาแอปให้ดียิ่งขึ้น โปรดดูหัวข้อต่อไปนี้เพื่อรับแรงบันดาลใจ
- ฟังเหตุการณ์การนำทางเพิ่มเติม เพิ่มโค้ดเพื่อแสดงข้อความหากคนขับเปลี่ยนเส้นทางหรือเมื่อมาถึง
- ปรับแต่งอินเทอร์เฟซการนำทาง
- หากต้องการความท้าทายที่ยิ่งใหญ่กว่านี้ ลองเพิ่มตัวควบคุมเครื่องมือเลือกสถานที่ของ Places API เพื่ออนุญาตให้ผู้ใช้ตั้งค่าปลายทาง เคล็ดลับ: แอปตัวอย่างของ Navigation SDK ใน GitHub มีการใช้งานตัวอย่าง
- ป้องกันปัญหาที่อาจเกิดขึ้นในการเรียกออบเจ็กต์ Navigator และ GoogleMap แบบไม่พร้อมกันโดยใช้วิธีการที่ใช้ในแอปตัวอย่าง Navigation SDK ใน Github ในสถานการณ์แอปที่ซับซ้อนมากขึ้น ออบเจ็กต์เหล่านี้อาจยังเริ่มต้นไม่เสร็จเมื่อโค้ดของคุณทำงาน เคล็ดลับ: คุณสามารถเพิ่มคลาส InitializedNavScope ที่ส่วนท้ายของไฟล์ MainActivity.kt เพื่อการติดตั้งใช้งานที่รวดเร็วมาก