Bắt đầu với SDK Trình điều khiển dành cho Android

Bạn có thể sử dụng SDK Trình điều khiển để cung cấp tính năng điều hướng và theo dõi nâng cao cho ứng dụng Tiến trình đặt hàng và Chuyến đi của mình. SDK trình điều khiển cung cấp thông tin cập nhật về vị trí xe và nhiệm vụ cho Công cụ nhóm giải pháp gọi xe và giao hàng theo yêu cầu.

SDK trình điều khiển giúp các dịch vụ Fleet Engine và các dịch vụ tuỳ chỉnh của bạn biết vị trí và trạng thái của xe. Ví dụ: xe có thể là ONLINE hoặc OFFLINE, và vị trí của xe thay đổi khi một chuyến đi diễn ra.

Yêu cầu tối thiểu về hệ thống

Thiết bị di động phải chạy Android 6.0 (API cấp 23) trở lên.

Cấu hình bản dựng và phần phụ thuộc

SDK trình điều khiển phiên bản 4.99 trở lên có trong kho lưu trữ Google Maven.

Gradle

Thêm đoạn mã sau vào tệp build.gradle của bạn:

repositories {
    ...
    google()
}

Maven

Thêm đoạn mã sau vào tệp pom.xml của bạn:

<project>
  ...
  <repositories>
    <repository>
      <id>google-maven-repository</id>
      <url>https://maven.google.com</url>
    </repository>
  </repositories>
  ...
</project>

Cấu hình dự án

Để sử dụng SDK Trình điều khiển, ứng dụng của bạn phải nhắm đến minSdkVersion 23 trở lên.

Để chạy một ứng dụng tạo bằng SDK Trình điều khiển, thiết bị Android phải cài đặt Dịch vụ Google Play.

Thiết lập dự án phát triển

Cách thiết lập dự án phát triển và nhận khoá API cho dự án trên Google Cloud Console:

  1. Tạo một dự án mới trên Google Cloud Console hoặc chọn một dự án hiện có để sử dụng với SDK Driver. Hãy chờ vài phút cho đến khi dự án mới xuất hiện trên Google Cloud Console.

  2. Để chạy ứng dụng minh hoạ, dự án của bạn phải có quyền truy cập vào SDK bản đồ dành cho Android. Trong Google Cloud Console, hãy chọn API và Dịch vụ > Thư viện, sau đó tìm và bật SDK Maps cho Android.

  3. Lấy khoá API cho dự án bằng cách chọn API và Dịch vụ > Thông tin xác thực > Tạo thông tin xác thực > Khoá API. Để biết thêm thông tin về cách tải khoá API, hãy xem phần Tải khoá API.

Thêm SDK Trình điều khiển vào ứng dụng của bạn

SDK Trình điều khiển có sẵn trong kho lưu trữ Google Maven. Kho lưu trữ bao gồm các tệp Mô hình đối tượng dự án (.pom) của SDK và Javadocs. Cách thêm SDK Trình điều khiển vào ứng dụng:

  1. Thêm phần phụ thuộc sau vào cấu hình Gradle hoặc Maven, thay thế phần giữ chỗ VERSION_NUMBER cho phiên bản SDK Trình điều khiển mong muốn.

    Gradle

    Thêm phần sau vào build.gradle:

    dependencies {
      ...
      implementation 'com.google.android.libraries.mapsplatform.transportation:transportation-driver:VERSION_NUMBER'
    }
    

    Maven

    Thêm phần sau vào pom.xml:

    <dependencies>
      ...
      <dependency>
        <groupId>com.google.android.libraries.mapsplatform.transportation</groupId>
        <artifactId>transportation-driver</artifactId>
        <version>VERSION_NUMBER</version>
      </dependency>
    </dependencies>
    
  2. SDK trình điều khiển phụ thuộc vào SDK điều hướng, phần phụ thuộc này được định cấu hình theo cách mà nếu cần một phiên bản cụ thể của SDK điều hướng thì cần phải xác định rõ ràng trong tệp cấu hình bản dựng như sau, việc bỏ qua khối mã được đề cập sẽ cho phép dự án luôn tải phiên bản mới nhất của SDK điều hướng xuống trong phiên bản phát hành chính. Xin lưu ý rằng hành vi kết hợp của các phiên bản mới nhất của SDK trình điều khiển và SDK điều hướng đã trải qua quá trình kiểm thử nghiêm ngặt trước khi phát hành.

    Sắp xếp cấu hình phần phụ thuộc của môi trường phát triển và phát hành cho phù hợp.

    Gradle

    Thêm phần sau vào build.gradle:

    dependencies {
      ...
      implementation 'com.google.android.libraries.navigation:navigation:5.0.0'
    }
    

    Maven

    Thêm phần sau vào pom.xml:

    <dependencies>
      ...
      <dependency>
        <groupId>com.google.android.libraries.navigation</groupId>
        <artifactId>navigation</artifactId>
        <version>5.0.0</version>
      </dependency>
    </dependencies>
    

Thêm khoá API vào ứng dụng của bạn

Sau khi thêm SDK Trình điều khiển vào ứng dụng, hãy thêm khoá API vào ứng dụng. Bạn phải sử dụng khoá API của dự án đã nhận được khi thiết lập dự án phát triển.

Phần này mô tả cách lưu trữ khoá API để ứng dụng của bạn có thể tham chiếu khoá API đó một cách an toàn hơn. Bạn không nên kiểm tra khoá API trong hệ thống quản lý phiên bản. Bạn nên lưu trữ tệp này trong tệp local.properties, nằm trong thư mục gốc của dự án. Để biết thêm thông tin về tệp local.properties, hãy xem các tệp thuộc tính Gradle.

Để đơn giản hoá tác vụ này, bạn có thể sử dụng Trình bổ trợ Secrets Gradle cho Android.

Cách cài đặt trình bổ trợ và lưu trữ khoá API:

  1. Mở tệp build.gradle ở cấp cơ sở và thêm mã sau vào phần tử dependencies trong buildscript.

    Groovy

    buildscript {
        dependencies {
            // ...
            classpath "com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.0"
        }
    }
    

    Kotlin

    buildscript {
        dependencies {
            // ...
            classpath("com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.0")
        }
    }
    
  2. Mở tệp build.gradle ở cấp ứng dụng và thêm mã sau vào phần tử plugins.

    Groovy

    id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin'
    

    Kotlin

    id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin")
    
  3. Nếu bạn sử dụng Android Studio, hãy đồng bộ hoá dự án với Gradle.

  4. Mở local.properties trong thư mục cấp dự án rồi thêm đoạn mã sau. Thay thế YOUR_API_KEY bằng khoá API.

    MAPS_API_KEY=YOUR_API_KEY
    
  5. Trong tệp AndroidManifest.xml, hãy chuyển đến com.google.android.geo.API_KEY rồi cập nhật thuộc tính android:value như sau:

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

Ví dụ sau đây trình bày một tệp kê khai hoàn chỉnh cho một ứng dụng mẫu:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.driverapidemo">
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/_AppTheme">

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

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

Đưa các thuộc tính bắt buộc vào ứng dụng của bạn

Nếu sử dụng SDK trình điều khiển trong ứng dụng của mình, bạn phải đưa văn bản phân bổ và giấy phép nguồn mở vào mục thông báo pháp lý của ứng dụng. Bạn nên thêm các thông tin phân bổ dưới dạng một mục trong trình đơn độc lập hoặc trong một mục trong trình đơn Giới thiệu.

Bạn có thể tìm thấy thông tin về giấy phép tại tệp "third_party_ tảng.txt" trong tệp AAR đã huỷ lưu trữ.

Hãy tham khảo https://developers.google.com/android/guides/opensource để biết cách thêm thông báo nguồn mở.

Phần phụ thuộc

Nếu sử dụng ProGuard để tối ưu hoá các bản dựng, bạn có thể cần thêm các dòng sau vào tệp cấu hình ProGuard:

-dontwarn com.google.**
-dontwarn okio.**

Cấp độ API tối thiểu được hỗ trợ là 23.

Khởi chạy SDK

Bạn phải có mã nhà cung cấp (thường là mã dự án trên Google Cloud) để khởi động đối tượng DriverContext. Để biết thêm thông tin chi tiết về cách thiết lập dự án Google Cloud, hãy xem phần Xác thực và uỷ quyền.

Trước khi sử dụng SDK Trình điều khiển, trước tiên, bạn phải khởi chạy SDK điều hướng. Cách khởi chạy SDK:

  1. Lấy đối tượng Navigator từ NavigationApi.

    Java

    NavigationApi.getNavigator(
        this, // Activity
        new NavigationApi.NavigatorListener() {
          @Override
          public void onNavigatorReady(Navigator navigator) {
            // Keep a reference to the Navigator (used to configure and start nav)
            this.navigator = navigator;
          }
        }
    );
    

    Kotlin

    NavigationApi.getNavigator(
      this, // Activity
      object : NavigatorListener() {
        override fun onNavigatorReady(navigator: Navigator) {
          // Keep a reference to the Navigator (used to configure and start nav)
          this@myActivity.navigator = navigator
        }
      },
    )
    
  2. Tạo đối tượng DriverContext, điền sẵn các trường bắt buộc.

    Java

    DriverContext driverContext = DriverContext.builder(application)
        .setProviderId(providerId)
        .setVehicleId(vehicleId)
        .setAuthTokenFactory(authTokenFactory)
        .setNavigator(navigator)
        .setRoadSnappedLocationProvider(
            NavigationApi.getRoadSnappedLocationProvider(application))
        .build();
    

    Kotlin

    val driverContext =
      DriverContext.builder(application)
        .setProviderId(providerId)
        .setVehicleId(vehicleId)
        .setAuthTokenFactory(authTokenFactory)
        .setNavigator(navigator)
        .setRoadSnappedLocationProvider(NavigationApi.getRoadSnappedLocationProvider(application))
        .build()
    
  3. Sử dụng đối tượng DriverContext để khởi tạo *DriverApi.

    Java

    RidesharingDriverApi ridesharingDriverApi = RidesharingDriverApi.createInstance(driverContext);
    

    Kotlin

    val ridesharingDriverApi = RidesharingDriverApi.createInstance(driverContext)
    
  4. Lấy RidesharingVehicleReporter từ đối tượng API. (*VehicleReporter mở rộng NavigationVehicleReporter.)

    Java

    RidesharingVehicleReporter vehicleReporter = ridesharingDriverApi.getRidesharingVehicleReporter();
    

    Kotlin

    val vehicleReporter = ridesharingDriverApi.getRidesharingVehicleReporter()
    

Đang xác thực với AuthTokenFactory

Khi tạo thông tin cập nhật vị trí, SDK Driver SDK phải gửi các thông tin cập nhật này đến máy chủ Fleet Engine. Để xác thực các yêu cầu này, SDK Trình điều khiển sẽ gọi một thực thể AuthTokenFactory do phương thức gọi cung cấp. Nhà máy sẽ chịu trách nhiệm tạo mã thông báo xác thực tại thời điểm cập nhật vị trí.

Cách tạo mã thông báo chính xác sẽ tuỳ thuộc vào trường hợp của từng nhà phát triển. Tuy nhiên, việc triển khai có thể sẽ cần phải:

  • tìm nạp mã thông báo xác thực (có thể ở định dạng JSON) từ một máy chủ HTTPS
  • phân tích cú pháp và lưu mã thông báo vào bộ nhớ đệm
  • làm mới mã thông báo khi hết hạn

Để biết thông tin chi tiết về các mã thông báo mà máy chủ Fleet Engine dự kiến, hãy xem bài viết Tạo mã thông báo web JSON (JWT) để uỷ quyền.

Dưới đây là cách triển khai khung của AuthTokenFactory:

Java

class JsonAuthTokenFactory implements AuthTokenFactory {
  private String token;  // initially null
  private long expiryTimeMs = 0;

  // This method is called on a thread whose only responsibility is to send
  // location updates. Blocking is OK, but just know that no location updates
  // can occur until this method returns.
  @Override
  public String getToken(AuthTokenContext authTokenContext) {
    if (System.currentTimeMillis() > expiryTimeMs) {
      // The token has expired, go get a new one.
      fetchNewToken(authTokenContext.getVehicleId());
    }
    return token;
  }

  private void fetchNewToken(String vehicleId) {
    String url =
        new Uri.Builder()
            .scheme("https")
            .authority("yourauthserver.example")
            .appendPath("token")
            .appendQueryParameter("vehicleId", vehicleId)
            .build()
            .toString();

    try (Reader r = new InputStreamReader(new URL(url).openStream())) {
      com.google.gson.JsonObject obj
          = com.google.gson.JsonParser.parseReader(r).getAsJsonObject();
      token = obj.get("Token").getAsString();
      expiryTimeMs = obj.get("TokenExpiryMs").getAsLong();

      // The expiry time could be an hour from now, but just to try and avoid
      // passing expired tokens, we subtract 10 minutes from that time.
      expiryTimeMs -= 10 * 60 * 1000;
    } catch (IOException e) {
      // It's OK to throw exceptions here. The StatusListener you passed to
      // create the DriverContext class will be notified and passed along the failed
      // update warning.
      throw new RuntimeException("Could not get auth token", e);
    }
  }
}

Kotlin

class JsonAuthTokenFactory : AuthTokenFactory() {

  private var token: String = ""
  private var expiryTimeMs: Long = 0

  // This method is called on a thread whose only responsibility is to send
  // location updates. Blocking is OK, but just know that no location updates
  // can occur until this method returns.
  override fun getToken(context: AuthTokenContext): String {
    if (System.currentTimeMillis() > expiryTimeMs) {
      // The token has expired, go get a new one.
      fetchNewToken(authTokenContext.getVehicleId())
    }
     return token
  }

  fun fetchNewToken(vehicleId: String) {
    val url =
      Uri.Builder()
        .scheme("https")
        .authority("yourauthserver.example")
        .appendPath("token")
        .appendQueryParameter("vehicleId", vehicleId)
        .build()
        .toString()

    try {
      val reader = InputStreamReader(URL(url).openStream())

      reader.use {
        val obj = com.google.gson.JsonParser.parseReader(r).getAsJsonObject()

        token = obj.get("ServiceToken").getAsString()
        expiryTimeMs = obj.get("TokenExpiryMs").getAsLong()

        // The expiry time could be an hour from now, but just to try and avoid
        // passing expired tokens, we subtract 10 minutes from that time.
        expiryTimeMs -= 10 * 60 * 1000
      }
    } catch (e: IOException) {
      // It's OK to throw exceptions here. The StatusListener you passed to
      // create the DriverContext class will be notified and passed along the failed
      // update warning.
      throw RuntimeException("Could not get auth token", e)
    }
  }
}

Cách triển khai cụ thể này sử dụng ứng dụng HTTP Java tích hợp sẵn để tìm nạp một mã thông báo ở định dạng JSON từ máy chủ xác thực của nhà phát triển. Mã thông báo sẽ được lưu để sử dụng lại. Mã thông báo sẽ được tìm nạp lại nếu trong vòng 10 phút kể từ thời gian hết hạn.

Quá trình triển khai của bạn có thể hoạt động theo cách khác, chẳng hạn như sử dụng luồng trong nền để làm mới mã thông báo.

Các ngoại lệ trong AuthTokenFactory sẽ được coi là tạm thời, trừ phi các ngoại lệ đó xảy ra nhiều lần. Sau một số lần thử, SDK trình điều khiển sẽ giả định rằng lỗi này là vĩnh viễn và sẽ ngừng cố gắng gửi các bản cập nhật.

Báo cáo trạng thái và lỗi với StatusListener

Vì SDK Trình điều khiển thực hiện các thao tác ở chế độ nền, nên hãy sử dụng StatusListener để kích hoạt thông báo khi một số sự kiện nhất định xảy ra, chẳng hạn như lỗi, cảnh báo hoặc thông báo gỡ lỗi. Lỗi có thể mang tính tạm thời (chẳng hạn như BACKEND_CONNECTIVITY_ERROR) hoặc có thể khiến quá trình cập nhật vị trí bị dừng vĩnh viễn (chẳng hạn như VEHICLE_NOT_FOUND, cho biết lỗi cấu hình).

Bạn có thể triển khai StatusListener (không bắt buộc) như sau:

Java

class MyStatusListener implements StatusListener {
  /** Called when background status is updated, during actions such as location reporting. */
  @Override
  public void updateStatus(
      StatusLevel statusLevel, StatusCode statusCode, String statusMsg) {
    // Status handling stuff goes here.
    // StatusLevel may be DEBUG, INFO, WARNING, or ERROR.
    // StatusCode may be DEFAULT, UNKNOWN_ERROR, VEHICLE_NOT_FOUND,
    // BACKEND_CONNECTIVITY_ERROR, or PERMISSION_DENIED.
  }
}

Kotlin

class MyStatusListener : StatusListener() {
  /** Called when background status is updated, during actions such as location reporting. */
  override fun updateStatus(statusLevel: StatusLevel, statusCode: StatusCode, statusMsg: String) {
    // Status handling stuff goes here.
    // StatusLevel may be DEBUG, INFO, WARNING, or ERROR.
    // StatusCode may be DEFAULT, UNKNOWN_ERROR, VEHICLE_NOT_FOUND,
    // BACKEND_CONNECTIVITY_ERROR, or PERMISSION_DENIED.
  }
}

Lưu ý về SSL/TLS

Trong nội bộ, quy trình triển khai SDK Trình điều khiển sử dụng SSL/TLS để giao tiếp an toàn với máy chủ Fleet Engine. Các phiên bản Android cũ hơn (API phiên bản 19 trở xuống) có thể yêu cầu bản vá SecurityProvider để có thể giao tiếp với máy chủ. Bạn nên xem bài viết này để biết thêm thông tin về cách làm việc với SSL trong Android. Bài viết này cũng chứa các mã mẫu để vá trình cung cấp dịch vụ bảo mật.

Bật tính năng cập nhật vị trí

Sau khi bạn có thực thể *VehicleReporter, bạn có thể bật tính năng cập nhật vị trí một cách đơn giản:

Java

RidesharingVehicleReporter reporter = ...;

reporter.enableLocationTracking();

Kotlin

val reporter = ...

reporter.enableLocationTracking()

Thông tin cập nhật vị trí được gửi định kỳ khi trạng thái xe là ONLINE. Lưu ý rằng việc gọi reporter.enableLocationTracking() sẽ không tự động đặt trạng thái của xe thành ONLINE. Bạn phải đặt trạng thái xe một cách rõ ràng.

Theo mặc định, khoảng thời gian báo cáo là 10 giây. Bạn có thể thay đổi khoảng thời gian báo cáo bằng reporter.setLocationReportingInterval(long, TimeUnit). Khoảng thời gian tối thiểu được hỗ trợ cho một lần cập nhật là 5 giây. Việc cập nhật thường xuyên hơn có thể dẫn đến các yêu cầu và lỗi chậm hơn.

Tắt cập nhật vị trí

Khi quá trình chuyển đổi của người lái hoàn tất, người lái có thể dừng lại thông tin cập nhật về vị trí và đánh dấu xe là ngoại tuyến bằng cách gọi DeliveryVehicleReporter.disableLocationTracking hoặc RidesharingVehicleReporter.disableLocationTracking.

Lệnh gọi này sẽ khiến một bản cập nhật cuối cùng được lên lịch để phân phối ngay, cho biết rằng xe đang không kết nối mạng. Bản cập nhật này sẽ không chứa thông tin vị trí của người dùng.

Đặt trạng thái xe

Khi bạn bật tính năng cập nhật vị trí, việc đặt trạng thái xe thành ONLINE sẽ cho phép xe xuất hiện cho các truy vấn SearchVehicles; tương tự như vậy, việc đánh dấu một xe là OFFLINE sẽ đánh dấu xe là không có hàng.

Bạn có thể đặt trạng thái xe ở phía máy chủ (xem phần Cập nhật xe) hoặc trực tiếp trong SDK của trình điều khiển:

Java

RidesharingVehicleReporter reporter = ...;

reporter.enableLocationTracking();
reporter.setVehicleState(VehicleState.ONLINE);

Kotlin

val reporter = ...

reporter.enableLocationTracking()
reporter.setVehicleState(VehicleState.ONLINE)

Khi bạn bật tính năng cập nhật vị trí, lệnh gọi đến setVehicleState sẽ áp dụng vào lần cập nhật vị trí tiếp theo.

Việc đánh dấu một xe là ONLINE khi tính năng theo dõi vị trí chưa được bật sẽ dẫn đến IllegalStateException. Một chiếc xe có thể được đánh dấu là OFFLINE khi tính năng theo dõi vị trí chưa được bật hoặc đã bị tắt một cách rõ ràng. Thao tác này sẽ dẫn đến việc cập nhật ngay lập tức. Lệnh gọi đến RidesharingVehicleReporter.disableLocationTracking() sẽ đặt trạng thái của xe thành OFFLINE.

Xin lưu ý rằng setVehicleState sẽ trả về ngay lập tức và quá trình cập nhật sẽ được thực hiện trong luồng cập nhật vị trí. Tương tự như việc xử lý lỗi khi cập nhật vị trí, các lỗi cập nhật trạng thái xe sẽ được phổ biến bằng cách sử dụng StatusListener được cung cấp (không bắt buộc) trong DriverContext.