1. ก่อนเริ่มต้น
โค้ดแล็บนี้จะสอนวิธีสร้างแอป Android แบบง่ายที่ใช้ Google Maps Platform Navigation SDK เพื่อไปยังปลายทางที่กำหนดค่าไว้ล่วงหน้า
นี่คือหน้าตาของแอปเมื่อคุณดำเนินการเสร็จสิ้น
ข้อกำหนดเบื้องต้น
- ความรู้เกี่ยวกับการพัฒนาแอป 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 ในโปรเจ็กต์
เปิดใช้ Google Maps Platform API และ SDK ที่จำเป็นสำหรับ 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 ทั้งก่อนและหลังเวอร์ชัน 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 ในวิธีเรียกใช้แอปในอุปกรณ์ฮาร์ดแวร์ หรือจะกำหนดค่าอุปกรณ์เสมือนโดยใช้โปรแกรมจัดการอุปกรณ์เสมือน (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")
นอกจากนี้ คุณยังแก้ไขค่าของตัวแปรนี้และตัวแปรอื่นๆ โดยใช้กล่องโต้ตอบที่แสดงในเมนูไฟล์ > โครงสร้างโปรเจ็กต์ > ตัวแปร
เพิ่มทรัพยากร 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
- เปิดไฟล์และเปลี่ยนเป็นมุมมองโค้ด
- แทนที่เนื้อหาทั้งหมดของไฟล์ด้วยเลย์เอาต์ใหม่ของ
NavigationView
ภายในRelativeLayout
ดังตัวอย่างด้านล่าง เนื่องจากคุณจะเพิ่มมุมมองการนำทางลงในแอปเท่านั้น เลย์เอาต์แบบง่ายก็เพียงพอแล้ว - กำหนดรหัส 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 ให้ทำการเปลี่ยนแปลงต่อไปนี้
- ประกาศตัวแปรในคลาส
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
เพื่อจัดการการเรียกกลับ
โปรดทราบว่าเมื่อเริ่มต้น Navigation API ระบบจะเรียกใช้เมธอด NavigationListener.onNavigatorReady
โดยส่งออบเจ็กต์ Navigator
เป็นพารามิเตอร์ โค้ดด้านบนจะอัปเดตตัวแปร mNavigator
ที่คุณประกาศไว้ก่อนหน้านี้ด้วยออบเจ็กต์ Navigator
ที่เริ่มต้นซึ่งส่งผ่านมายังเมธอดนี้
สุดท้าย เพิ่มการเรียกไปยังเมธอด initializeNavigationApi
จากเมธอด onLocationPermissionGranted
private fun onLocationPermissionGranted() {
initializeNavigationApi()
}
8. เพิ่ม Listener สําหรับเหตุการณ์การนําทางที่สําคัญ
เมื่อผู้ใช้ทําตามคําแนะนํา Navigation SDK จะเรียกเหตุการณ์ที่แจ้งให้แอปทราบเกี่ยวกับการเปลี่ยนแปลงสถานะที่สําคัญระหว่างเส้นทาง เช่น เมื่อผู้ใช้เปลี่ยนเส้นทางหรือไปถึงจุดหมาย ในไฟล์ MainActivity.kt ให้เพิ่ม Listener เพื่อจัดการเหตุการณ์เหล่านี้
- ภายในคลาส
MainActivity
ให้ประกาศตัวแปร 2 รายการเพื่ออ้างอิงออบเจ็กต์ Listener เหตุการณ์ ดังนี้
private var arrivalListener: Navigator.ArrivalListener? = null
private var routeChangedListener: Navigator.RouteChangedListener? = null
- เพิ่มเมธอด
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)
}
}
- เพิ่มการเรียก
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
เพื่อระบุCameraPerspective
GoogleMap
มีการเข้าถึงผ่านเมธอด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()
เพื่อตั้งค่าปลายทางโดยใช้ 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
จะระบุว่าพบเส้นทางไปยังปลายทางหรือไม่ และช่วยให้คุณจัดการสถานะข้อผิดพลาดต่างๆ ได้หากไม่พบเส้นทาง
- เปลี่ยนแปลงการกำหนดค่าเพิ่มเติมเพื่อปรับปรุงประสบการณ์การนำทางของผู้ใช้ ดังนี้
// 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 จะใช้สถานที่เริ่มต้นในลอนดอนและรหัสสถานที่ของ Trafalgar Square
companion object{
const val TRAFALGAR_SQUARE ="ChIJH-tBOc4EdkgRJ8aJ8P1CUxo" //London, UK
val startLocation = LatLng(51.345678, -0.1234456)
}
- เพิ่มการเรียกใช้เมธอด
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 รายการแรก โปรดดูข้อมูลเพิ่มเติมที่การใช้งานและการเรียกเก็บเงิน
การตั้งค่าตำแหน่ง
โดยค่าเริ่มต้น อุปกรณ์จำลองอาจตั้งค่าตำแหน่งเป็นวิทยาเขตของ Google ในเมืองเมาน์เทนวิว รัฐแคลิฟอร์เนีย เว้นแต่คุณจะตั้งค่าตำแหน่งในโค้ดหรือใช้กล่องโต้ตอบพร็อพเพอร์ตี้โปรแกรมจำลอง
หากเป็นเช่นนั้น คุณอาจพบว่าแอปไม่พบเส้นทางไปยังรหัสสถานที่ที่คุณกำหนดค่าไว้ (โดยค่าเริ่มต้นคือ Sydney Opera House, Sydney, Australia) ซึ่งจะมีการระบุโดยข้อความที่ระบุว่า "ไม่พบเส้นทาง" ซึ่งแสดงตามเมธอด showToast()
การเขียนโค้ดตำแหน่งเริ่มต้นแบบฮาร์ดโค้ด
หากต้องการตั้งค่าตำแหน่งอื่นในโค้ด ให้เพิ่มบรรทัดต่อไปนี้ในเมธอด navigateToPlace()
ใน MainActivity.kt ก่อนเรียก mNavigator.startGuidance()
:
mNavigator?.simulator?.setUserLocation(startLocation)
การเริ่มโปรแกรมจำลองในตำแหน่งเริ่มต้นที่คุณเลือก
หากต้องการตั้งค่าตำแหน่งอื่นในโปรแกรมจำลองอุปกรณ์ ให้เปิดโปรแกรมจำลองหากยังไม่ได้เปิดอยู่ แล้วคลิกเมนู 3 จุดที่มีเคล็ดลับเครื่องมือ "การควบคุมแบบขยาย" กล่องโต้ตอบที่เปิดขึ้นจะมีตัวเลือกเมนูสำหรับ "ตำแหน่ง"
ตัวอย่างเช่น หากคุณใช้รหัสสถานที่ของโรงอุปรากรซิดนีย์เป็นปลายทาง ให้เลือกสถานที่ในซิดนีย์ ออสเตรเลีย เช่น ค้นหา "หาดนพรัตน์" เลือกคำแนะนำและคลิก "บันทึกตำแหน่ง" ที่ด้านล่างขวาของกล่องโต้ตอบ คุณยังสามารถคลิก "บันทึกจุด" เพื่อเพิ่มสถานที่ตั้งลงในรายการที่บันทึกไว้เพื่อใช้ในอนาคต
หากคุณตั้งค่ารหัสสถานที่อื่นเป็นปลายทาง ให้เลือกสถานที่ใกล้เคียงกับรหัสนั้นเพื่อให้เส้นทางจำลองเป็นเส้นทางที่สมจริงและไม่ยาวจนเกินไปเพื่อให้แก้ไขข้อบกพร่องได้ง่าย
รีสตาร์ทแอป แล้วระบบจะนําไปยังปลายทาง
11. ยินดีด้วย
คุณดำเนินการ Codelab เสร็จสมบูรณ์แล้ว เยี่ยมมาก คุณมาถึงจุดหมายแล้ว
12. สู่ขั้นต่อไป
หากต้องการพัฒนาแอปให้ก้าวไปอีกขั้น ลองดูหัวข้อต่อไปนี้เพื่อเป็นแรงบันดาลใจ
- ฟังเหตุการณ์การนำทางเพิ่มเติม เพิ่มโค้ดเพื่อแสดงข้อความหากคนขับเปลี่ยนเส้นทางหรือเมื่อคนขับมาถึง
- ปรับแต่งอินเทอร์เฟซการนำทาง
- หากต้องการลองทำโจทย์ที่ยากขึ้น ให้ลองดูว่าคุณเพิ่มตัวควบคุมเครื่องมือเลือกสถานที่ของ Places API เพื่ออนุญาตให้ผู้ใช้กำหนดปลายทางได้หรือไม่ เคล็ดลับ: แอปเดโม Navigation SDK ใน GitHub มีตัวอย่างการใช้งาน
- ป้องกันปัญหาที่อาจเกิดขึ้นในการเรียกใช้ออบเจ็กต์ Navigator และ GoogleMap แบบไม่พร้อมกันโดยใช้แนวทางที่ใช้ในแอปสาธิตการนำทาง SDK ใน GitHub ในสถานการณ์แอปที่ซับซ้อนมากขึ้น ออบเจ็กต์เหล่านี้อาจเริ่มต้นไม่เสร็จสิ้นเมื่อโค้ดทำงาน เคล็ดลับ: คุณสามารถเพิ่มคลาส InitializedNavScope ที่ท้ายไฟล์ MainActivity.kt เพื่อการติดตั้งใช้งานที่รวดเร็ว