Tạo ứng dụng chỉ đường đơn giản trên Android bằng SDK điều hướng trên Nền tảng Google Maps

1. Trước khi bắt đầu

Lớp học lập trình này hướng dẫn bạn tạo một ứng dụng Android đơn giản sử dụng SDK điều hướng của Nền tảng Google Maps để điều hướng tới một điểm đến được định cấu hình trước.

Đây là giao diện của ứng dụng sau khi bạn hoàn thành.

b6c535afde7abd20.png

Điều kiện tiên quyết

  • Có kiến thức về phát triển ứng dụng Android cơ bản bằng Kotlin
  • Quen thuộc với một số khái niệm cơ bản về SDK Google Maps, chẳng hạn như bản đồ, vị trí, toạ độ.

Kiến thức bạn sẽ học được

  • Cách tạo một ứng dụng Android đơn giản sử dụng SDK điều hướng để điều hướng tới một đích đến.
  • Cách tích hợp SDK điều hướng từ kho lưu trữ Google Maven từ xa
  • Cách quản lý quyền truy cập thông tin vị trí và thoả thuận của người dùng với các điều khoản dành cho người dùng cuối của SDK điều hướng
  • Cách khởi chạy SDK
  • Cách đặt điểm đến và bắt đầu chỉ dẫn đường đi.

Bạn cần có

  • Đã cài đặt phiên bản ổn định mới nhất của Android Studio. Lớp học lập trình này được tạo bằng Android Studio Jellyfish. Nếu bạn đang sử dụng một phiên bản khác, thì giao diện và bố cục của giao diện và các thành phần có thể thay đổi.
  • Tài khoản Google và Dự án đã bật tính năng thanh toán.
  • Thiết bị Android ở chế độ Nhà phát triển và đã bật tính năng gỡ lỗi qua USB hoặc trình mô phỏng Android. Bất kỳ phiên bản nào bạn chọn đều phải đáp ứng các yêu cầu tối thiểu đối với SDK điều hướng

2. Bắt đầu thiết lập

Nếu bạn chưa có tài khoản Google Cloud Platform và dự án đã bật tính năng thanh toán, hãy thiết lập dự án trên Google Cloud theo hướng dẫn Bắt đầu sử dụng Google Maps Platform https://developers.google.com/maps/gmp-get-started

Chọn dự án Google Cloud trong bảng điều khiển

Trong Cloud Console, hãy nhấp vào trình đơn thả xuống dự án rồi chọn dự án bạn muốn sử dụng cho lớp học lập trình này.

Trình đơn thả xuống của bộ chọn dự án trong Google Cloud Console.

Bật SDK điều hướng trong dự án của bạn

Bật các API và SDK của Nền tảng Google Maps cần thiết cho lớp học lập trình này trong Google Cloud Marketplace.

Chuyển đến phần API và dịch vụ > Thư viện trong Google Cloud Console rồi tìm "Navigation SDK".

Bạn sẽ thấy một kết quả tìm kiếm.

Màn hình Thư viện API trong bảng điều khiển Google Cloud, cho thấy trang SDK điều hướng.

Nhấp vào kết quả SDK điều hướng để mở trang Chi tiết sản phẩm. Nhấp vào nút Bật để bật SDK trên dự án của bạn.

Lặp lại quy trình này cho SDK Google Maps cho Android.

Tạo khoá API

Tạo khoá API trong trang Thông tin xác thực của Cloud Console. Bạn có thể làm theo các bước ở bước 3 của phần bắt đầu nhanh trong bài viết Bắt đầu sử dụng Nền tảng Google Maps. Tất cả các yêu cầu gửi đến Nền tảng Google Maps đều cần có khoá API.

3. Tải tệp dự án mẫu

Phần này mô tả cách thiết lập một dự án Android Studio trống cơ bản bằng cách nhân bản các tệp từ kho lưu trữ GitHub cho lớp học lập trình này. Kho lưu trữ GitHub chứa các phiên bản trước và sau của mã nguồn của lớp học lập trình này. Lớp học lập trình này sẽ bắt đầu bằng một mẫu dự án trống và xây dựng tới trạng thái hoàn tất. Bạn có thể tham khảo dự án đã hoàn thiện trong kho lưu trữ nếu gặp khó khăn.

Sao chép kho lưu trữ GitHub này để lấy mã cho lớp học lập trình này.

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

Nếu bạn chưa cài đặt git, hãy nhấp vào nút này để lấy mã:

Để giúp bạn bắt đầu nhanh nhất có thể, kho lưu trữ này chứa một số mã khởi đầu trong thư mục Starter để giúp bạn theo dõi lớp học lập trình này. Dự án khởi đầu cung cấp giao diện người dùng và cấu hình bản dựng cơ bản của ứng dụng nhưng không thêm SDK điều hướng. Ngoài ra, còn có một dự án Solution đã hoàn tất trong trường hợp bạn muốn chuyển sang phần sau hoặc kiểm tra tiến trình của mình bất cứ lúc nào.

Mở kho lưu trữ được sao chép trong Android Studio

Sau khi bạn sao chép kho lưu trữ cục bộ, hãy sử dụng Android Studio để mở thư mục Starter dưới dạng một dự án hiện có.

  1. Trong hộp thoại Welcome to Android Studio (Chào mừng bạn đến với Android Studio), hãy nhấp vào nút Open (Mở).
  2. Chuyển đến thư mục mà bạn đã lưu kho lưu trữ được sao chép rồi chọn thư mục Starter bên trong "codelab-navigation-101-android-kotlin" cấp cao nhất .
  3. Kiểm tra để đảm bảo dự án tạo và chạy.

Thêm thiết bị ảo hoặc kết nối thiết bị phần cứng

Để kết nối thiết bị Android với máy tính, hãy làm theo hướng dẫn của Android Studio về cách Chạy ứng dụng trên thiết bị phần cứng. Ngoài ra, bạn có thể định cấu hình một thiết bị ảo bằng Trình quản lý thiết bị Android ảo (AVD). Khi chọn trình mô phỏng, hãy nhớ chọn một hình ảnh có chứa API của Google.

Trong Android Studio, hãy nhấp vào mục trình đơn Run (Chạy) hoặc biểu tượng nút phát. Chọn một thiết bị theo lời nhắc.

4. Thêm SDK điều hướng vào ứng dụng của bạn

Thêm thư viện SDK điều hướng và khoá API vào dự án của bạn

Để thêm thư viện SDK điều hướng vào ứng dụng, bạn cần sửa đổi build.gradle.kts cấp ứng dụng để tìm nạp SDK điều hướng từ kho lưu trữ Google Maven và định cấu hình số phiên bản.

Tạo một biến trong cấu hình bản dựng để lưu trữ số phiên bản SDK điều hướng.

Thiết lập một biến trong build.gradle.kts cấp ứng dụng để chứa giá trị của phiên bản SDK điều hướng được sử dụng trong ứng dụng, nhờ đó, bạn có thể dễ dàng thay đổi sang phiên bản mới nhất trong tương lai.

Hãy xem ghi chú phát hành SDK điều hướng để biết số phiên bản mới nhất.

val navSdkVersion by extra("6.0.0")

Bạn cũng có thể sửa đổi giá trị của biến này và các biến khác bằng cách sử dụng hộp thoại có trong phần File (Tệp) > Project Structure (Cấu trúc dự án) > Variables (Biến):

668332736b67dc82.pngS

Thêm phần phụ thuộc vào cấu hình bản dựng

Bây giờ, hãy thêm phần phụ thuộc API sau vào khối phần phụ thuộc trong build.gradle.kts. cấp ứng dụng. Phiên bản được sử dụng sẽ là giá trị của ${navSdkVersion} mà bạn vừa đặt trong build.gradle.kts cấp ứng dụng:

dependencies {

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

...

Thêm khoá API

Sử dụng trình bổ trợ Secrets (Khoá bí mật) cho Gradle để quản lý khoá API

Bạn nên sử dụng trình bổ trợ Khoá bí mật cho Gradle để quản lý khoá API trong ứng dụng của mình một cách an toàn. Trình bổ trợ này đã được thêm vào mẫu dự án ban đầu dưới dạng phần phụ thuộc trong tệp build.gradle.kts cấp cao nhất.

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

Mở tệp secrets.properties trong thư mục cấp cao nhất, sau đó thay thế YOUR_API_KEY bằng khoá API. Lưu trữ khoá của bạn trong tệp này vì secrets.properties không được đưa vào hệ thống quản lý phiên bản.

MAPS_API_KEY=YOUR_API_KEY

Để biết thêm thông tin về chủ đề này, hãy xem phần Thêm khoá API vào ứng dụng trong tài liệu về SDK điều hướng.

Xác minh nội dung của local.defaults.properties

Dự án trống cũng chứa một tệp local.defaults.properties trong thư mục cấp cao nhất, cùng thư mục với tệp secrets.properties. Hãy mở tệp đó và quan sát mã sau.

MAPS_API_KEY=DEFAULT_API_KEY

Mã này tồn tại để cung cấp giá trị dự phòng cho thuộc tính MAPS_API_KEY trong trường hợp secrets.properties không được thêm vào dự án, nhờ đó các bản dựng sẽ không bị lỗi. Bạn không cần phải chỉnh sửa tệp này. Nếu không tìm thấy định nghĩa secrets.properties của MAPS_API_KEY, thì giá trị mặc định sẽ khiến ứng dụng ngừng chạy trong thời gian chạy, kèm theo lỗi khoá API.

Kiểm tra để đảm bảo Tệp kê khai Android đang sử dụng khoá API mà bạn chỉ định

Mở app/src/main/AndroidManifest.xml. Bạn sẽ thấy thuộc tính MAPS_API_KEY được dùng để đặt khoá API cho ứng dụng:

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

Mở tệp build.gradle.kts ở cấp ứng dụng rồi tìm thuộc tính secrets.

Bạn phải đặt chế độ cài đặt propertiesFileName của trình bổ trợ thành secrets.properties, còn defaultPropertiesFileName phải đọc là 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"
}

Lưu tất cả các tệp và đồng bộ hoá dự án của bạn với Gradle.

5. Định cấu hình quyền cho ứng dụng và thêm giao diện người dùng cơ bản

Yêu cầu quyền truy cập thông tin vị trí chính xác

SDK điều hướng phụ thuộc vào tín hiệu GPS để hoạt động, do đó ứng dụng của bạn sẽ cần yêu cầu người dùng cấp quyền truy cập vào dữ liệu vị trí chính xác. Thêm quyền truy cập thông tin vị trí chính xác ở dạng phần tử con của phần tử <manifest> trong 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>

Bạn có thể đọc thêm về quyền truy cập thông tin vị trí trên Android trong phần Yêu cầu quyền truy cập thông tin vị trí trong tài liệu dành cho nhà phát triển Android.

Để chạy ứng dụng trên thiết bị Android 14, hãy yêu cầu quyền truy cập thông tin vị trí của dịch vụ trên nền trước bằng cách thêm thẻ uses-permission sau vào cùng một vị trí với quyền truy cập thông tin vị trí chính xác:

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

Thêm hoạt động khởi chạy có giao diện người dùng cơ bản

Khi chạy, ứng dụng của bạn sẽ cần mã thực thi trong quá trình khởi động để kiểm tra xem người dùng đã cấp quyền truy cập thông tin vị trí của họ hay chưa, đồng thời xử lý từng tình huống có thể xảy ra, yêu cầu cấp quyền nếu người dùng chưa cấp. Để làm việc này, hãy thêm một giao diện người dùng cơ bản vào ứng dụng. Lớp học lập trình này sử dụng giao diện người dùng được tạo khi bạn tạo một hoạt động Khung hiển thị mới, trống trong Android Studio. Bạn sẽ điều chỉnh mã này để thực hiện việc kiểm tra quyền truy cập thông tin vị trí trước khi thêm mã vào hoạt động cho giao diện người dùng chỉ đường.

Mở tệp MainActivity.kt trong trình soạn thảo mã rồi kiểm tra mã, trong đó cho thấy giao diện người dùng cơ bản.

Yêu cầu cấp quyền truy cập thông tin vị trí trong thời gian chạy

Ứng dụng của bạn sẽ cần kích hoạt yêu cầu truy cập thông tin vị trí chính xác trước khi khởi chạy SDK Điều hướng.

Để đảm bảo việc kiểm tra này diễn ra khi ứng dụng khởi động, hãy thêm một số mã vào lớp MainActivity, trong phương thức onCreate() bị ghi đè của Hoạt động.

Mã sau đây kiểm tra xem người dùng đã cấp quyền truy cập thông tin vị trí chính xác hay chưa. Nếu chưa thì hệ thống sẽ yêu cầu bạn cấp quyền. Hãy thêm mã này vào bên trong phương thức 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

Thêm một hàm mới vào lớp MainActivity, có tên là onLocationPermissionGranted. Hàm này sẽ xử lý kết quả khi người dùng cấp quyền chia sẻ thông tin vị trí của họ. Trong các bước tiếp theo, chúng ta sẽ thêm mã tại đây để khởi chạy một hoạt động điều hướng mới.

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

Tạo dự án. Nếu bạn gặp lỗi bản dựng, hãy tìm và khắc phục các lỗi đó.

Chạy dự án trên một thiết bị ảo mới. Bạn sẽ thấy hộp thoại yêu cầu cấp quyền xuất hiện khi ứng dụng cài đặt và khởi động.

6. Thêm giao diện người dùng điều hướng

Có hai cách để thêm Giao diện người dùng điều hướng: SupportNavigationFragment hoặc NavigationView.

Để đơn giản hoá, lớp học lập trình này sử dụng NavigationView.

Chỉnh sửa bố cục

Chỉnh sửa res/layout/activity_main.xml để thêm bố cục cho NavigationView.

  1. Mở tệp và chuyển sang Chế độ xem mã.
  2. Thay thế toàn bộ nội dung của tệp bằng bố cục mới của NavigationView bên trong RelativeLayout như trong ví dụ bên dưới. Vì bạn sẽ chỉ thêm một thành phần hiển thị điều hướng vào ứng dụng, nên một bố cục đơn giản là đủ.
  3. Đặt mã nhận dạng cho NavigationView là "@+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>

Thiết lập hoạt động Điều hướng

Trong Android Studio, hãy mở tệp MainActivity.kt trong trình chỉnh sửa.

Thêm một số mã thiết lập cơ bản để đảm bảo trải nghiệm điều hướng hoạt động chính xác trong ứng dụng của bạn. Trong tệp MainActivity.kt, hãy thực hiện những thay đổi sau:

  1. Khai báo một biến trong lớp MainActivity để tham chiếu đến NavigationView:
private lateinit var navView: NavigationView
  1. Thêm mã vào phương thức onCreate() để lấy thông tin tham chiếu đến NavigationView:
navView = findViewById(R.id.navigation_view)
navView.onCreate(savedInstanceState)
  1. Thêm một số mã vào phương thức onCreate() để đảm bảo màn hình luôn bật trong quá trình hướng dẫn điều hướng:
// Ensure the screen stays on during nav.
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
  1. Chỉnh sửa mã gọi ViewCompat.setOnApplyWindowInsetsListener để tham chiếu mã nhận dạng của 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. Thêm phương thức showToast() vào lớp để hiển thị phản hồi cho người dùng:
private fun showToast(errorMessage: String) {
   Toast.makeText(this@MainActivity, errorMessage, Toast.LENGTH_LONG).show()
}

7. Khởi chạy SDK điều hướng

Giờ đây, khi đã hoàn tất việc thiết lập hoạt động Điều hướng cơ bản, bạn có thể khởi chạy SDK Điều hướng. Để thực hiện việc này, hãy thêm mã sau vào tệp 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")
               }
           }
       },
   )

}

Mã này tạo một phương thức mới có tên là initializeNavigationApi(). Phương thức này tham chiếu đến đối tượng Navigator bằng cách gọi NavigationApi.getNavigator() và triển khai NavigatorListener để xử lý lệnh gọi lại.

Lưu ý rằng khi khởi chạy API điều hướng, phương thức NavigationListener.onNavigatorReady sẽ được gọi, trong đó đối tượng Navigator được truyền dưới dạng tham số. Đoạn mã ở trên sẽ cập nhật biến mNavigator mà bạn đã khai báo trước đó bằng đối tượng Navigator đã khởi tạo được truyền vào phương thức này.

Cuối cùng, hãy thêm lệnh gọi vào phương thức initializeNavigationApi từ phương thức onLocationPermissionGranted.

private fun onLocationPermissionGranted() {
   initializeNavigationApi()
}

8. Thêm trình nghe cho các sự kiện điều hướng chính

Khi người dùng của bạn làm theo hướng dẫn, SDK điều hướng sẽ kích hoạt các sự kiện có thể thông báo cho ứng dụng về những thay đổi quan trọng đối với trạng thái trên đường đi, chẳng hạn như khi người dùng đi lại hoặc đến điểm đến. Trong tệp MainActivity.kt, hãy thêm trình nghe để xử lý các sự kiện sau:

  1. Trong lớp MainActivity, hãy khai báo hai biến để tham chiếu đến các đối tượng trình nghe sự kiện:
private var arrivalListener: Navigator.ArrivalListener? = null
private var routeChangedListener: Navigator.RouteChangedListener? = null
  1. Thêm phương thức registerNavigationListeners() để thiết lập trình nghe khi Trình điều hướng được khởi động. Phương thức này gọi Navigator.clearDestinations() để đặt lại NavigationView khi sự kiện Đến được kích hoạt:
/**
* 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. Thêm lệnh gọi đến registerNavigationListeners() từ mã gọi lại onNavigatorReady trong phương thức initializeNavigationApi:
override fun onNavigatorReady(navigator: Navigator) {
   // store a reference to the Navigator object
   mNavigator = navigator

   //listen for events en route
   registerNavigationListeners()


}
  1. Định cấu hình giao diện người dùng. Bạn có thể kiểm soát nhiều khía cạnh của giao diện người dùng điều hướng khi chạy hướng dẫn. Một tuỳ chỉnh quan trọng là vị trí camera. Thêm lệnh gọi vào phương thức setTaskRemovedBehaviour của đối tượng navigator trả về trong onNavigatorReady như sau. Thao tác này sẽ chấm dứt hướng dẫn và thông báo nếu ứng dụng bị vuốt đi:
// 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. Thêm lệnh gọi vào GoogleMap.followMyLocation để chỉ định CameraPerspective. Truy cập vào GoogleMap thông qua phương thức NavigatorView.getMapAsync() như sau:
navView.getMapAsync {
   googleMap  ->
   googleMap.followMyLocation(GoogleMap.CameraPerspective.TILTED)
}
  1. Để đảm bảo điều hướng hoạt động trơn tru trong suốt vòng đời của ứng dụng, hãy triển khai các phương thức sau trong lớp 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. Đặt điểm đến

Bây giờ, bạn đã sẵn sàng để đặt một điểm đến và bắt đầu hướng dẫn đi theo chỉ dẫn. Trong tệp MainActivity.kt, hãy thực hiện những thay đổi sau:

  1. Thêm một phương thức navigateToPlace() mới để thiết lập đích điều hướng và chấp nhận tham số placeId.
/**
* Requests directions from the user's current location to a specific place (provided by the
* Place ID).
*/
private fun navigateToPlace(placeId: String) {

}
  1. Trong phương thức navigateToPlace(), hãy sử dụng phương thức Waypoint.builder() để tạo Waypoint từ mã địa điểm được truyền vào phương thức. Xử lý UnsupportedPlaceIdException mà ứng dụng này có thể gửi trong các trường hợp Mã địa điểm không phân giải thành một địa chỉ chính xác:
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. Thêm mã sau vào phương thức navigateToPlace() để đặt đích đến bằng 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")
   }
}

Đối tượng Navigator có một phương thức setDestinations() có thể nhận nhiều tham số. Lựa chọn cơ bản nhất là cung cấp Waypoint. Giá trị này sẽ mặc định là chế độ di chuyển DRIVING, phù hợp với xe 4 bánh. Phương thức setDestinations() trả về một đối tượng ListenableResultFuture chứa đối tượng RouteStatus. RouteStatus sẽ cho biết liệu có tìm thấy tuyến đường đến đích hay không và cho phép bạn xử lý nhiều trạng thái lỗi nếu không.

  1. Thực hiện các thay đổi bổ sung về cấu hình để cải thiện trải nghiệm điều hướng của người dùng:
// 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)
   )
}

Những thay đổi này bao gồm các điểm cải tiến sau:

  • Ẩn Thanh thao tác để tối đa hoá không gian cho Giao diện người dùng điều hướng.
  • Bật hướng dẫn bằng giọng nói để đọc cảnh báo và hướng dẫn di chuyển.
  • Thiết lập Trình mô phỏng để gỡ lỗi bằng cách chỉ định hệ số tốc độ.
  1. Tìm một Mã địa điểm sẽ đóng vai trò là đích đến của bạn. Vị trí lý tưởng là vị trí không quá xa vị trí của người dùng. Hãy sử dụng tiện ích Trình tìm mã địa điểm trên Nền tảng Google Maps hoặc lấy Mã địa điểm từ lệnh gọi API Địa điểm.

Nếu đang mô phỏng hoạt động chỉ đường, bạn có thể thiết lập vị trí của người dùng trong mã hoặc lấy thông tin đó từ thiết bị đã kết nối. Lớp học lập trình này sẽ giả định rằng bạn đang mô phỏng một vị trí ở London, Vương quốc Anh.

  1. Thêm đối tượng đồng hành vào lớp MainActivity để lưu trữ vị trí bắt đầu và mã địa điểm. Lớp học lập trình này sẽ sử dụng vị trí bắt đầu tại London và Mã địa điểm của Quảng trường Trafalgar:
companion object{
   const val TRAFALGAR_SQUARE ="ChIJH-tBOc4EdkgRJ8aJ8P1CUxo" //London, UK
   val startLocation = LatLng(51.345678, -0.1234456)
}
  1. Thêm một lệnh gọi vào phương thức navigateToPlace() từ lệnh gọi lại onNavigatorReady bên trong phương thức initializeNavigationApi và thêm một nhánh logic sẽ thực thi ở chế độ Gỡ lỗi để thiết lập vị trí của người dùng:
// 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. Tạo bản dựng và chạy mã

Trong lần đầu tiên chạy ứng dụng, bạn cần cấp quyền truy cập thông tin vị trí cho ứng dụng và chấp nhận điều khoản sử dụng SDK chỉ đường.

Lưu ý: việc chạy ứng dụng sẽ gọi phương thức setDestinations() và sẽ tính phí sau 1000 đích đến đầu tiên được sử dụng. Xem phần Sử dụng và thanh toán để biết thêm thông tin.

93aa433000a14dfc.png.

Hộp thoại điều khoản người dùng cuối của SDK Điều hướng.

Đặt vị trí

Theo mặc định, vị trí của thiết bị được mô phỏng có thể được đặt thành khuôn viên của Google ở Mountain View, California, trừ phi bạn đã đặt vị trí trong mã hoặc sử dụng hộp thoại thuộc tính của trình mô phỏng.

Nếu có, bạn có thể thấy ứng dụng không tìm thấy tuyến đường đến Mã địa điểm mà bạn đã định cấu hình (theo mặc định là Nhà hát Opera Sydney, Sydney, Úc). Điều này sẽ được biểu thị bằng thông báo "Không tìm thấy tuyến đường", được hiển thị bằng phương thức showToast().

Chế độ xem bản đồ của ứng dụng Điều hướng cho thấy văn phòng của Google ở Mountain View, California.

Lập trình cứng vị trí bắt đầu

Để đặt một vị trí khác trong mã, hãy thêm dòng sau vào phương thức navigateToPlace() trong MainActivity.kt, trước lệnh gọi đến mNavigator.startGuidance():

mNavigator?.simulator?.setUserLocation(startLocation)

Khởi động trình mô phỏng tại vị trí mặc định mà bạn chọn

Để đặt một vị trí khác trong trình mô phỏng thiết bị, hãy khởi động trình mô phỏng nếu trình mô phỏng chưa chạy rồi nhấp vào trình đơn có biểu tượng 3 dấu chấm có chú giải công cụ "Extended Controls" (Chế độ điều khiển mở rộng). Hộp thoại mở ra có một lựa chọn trong trình đơn cho "Vị trí".

Ví dụ: nếu bạn đang sử dụng Mã địa điểm của Nhà hát Opera Sydney làm điểm đến, hãy chọn một vị trí ở Sydney, Úc. Ví dụ: hãy tìm "Bondi beach" (Bãi biển Bondi), chọn một đề xuất rồi nhấp vào "Lưu vị trí" ở dưới cùng bên phải của hộp thoại. Bạn cũng có thể nhấp vào "Điểm lưu" để thêm vị trí vào danh sách đã lưu để sử dụng sau này.

Hộp thoại Extended Controls (Chế độ điều khiển mở rộng) trong Android Device Manager (Trình quản lý thiết bị Android), hiển thị một bộ chọn địa điểm và bản đồ tập trung vào bãi biển Trái Đất ở Úc.

Nếu bạn đặt một Mã địa điểm khác làm đích đến, hãy chọn một vị trí lân cận để tuyến đường được mô phỏng là tuyến đường thực tế và không quá dài để dễ dàng gỡ lỗi.

Khởi động lại ứng dụng và ứng dụng sẽ điều hướng đến đích đến.

Ảnh chụp màn hình ứng dụng Chỉ đường hướng dẫn đến đích.

11. Xin chúc mừng!

Bạn đã hoàn tất lớp học lập trình này. Tốt lắm! Bạn đã đến nơi! Chúc bạn lập trình vui vẻ :-)

55812f33256c0596.png

12. Mở rộng phạm vi

Nếu bạn muốn phát triển ứng dụng của mình hơn nữa, hãy xem các chủ đề sau để lấy cảm hứng.