開始使用 Android 版 Driver SDK

您可以使用 Driver SDK 提供強化的導航和追蹤功能 。Driver SDK 提供 隨選乘車和配送解決方案機群引擎的車輛位置和工作更新。

驅動程式 SDK 可讓您隨時掌握 Fleet Engine 服務和您的自訂服務 車輛位置和州別的資訊舉例來說,車輛可以是 ONLINEOFFLINE,且車輛位置會隨著行程進展而變更。

基本系統需求

行動裝置必須搭載 Android 6.0。 (API 級別 23) 以上版本。

建構和依附元件設定

您可以從 Google Maven 存放區取得 4.99 以上版本的驅動程式 SDK。

Gradle

請將以下內容新增到 build.gradle 檔案中:

repositories {
    ...
    google()
}

Maven

請將以下內容新增到 pom.xml 檔案中:

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

專案設定

如要使用 Driver SDK,應用程式必須指定 minSdkVersion 23 以上版本。

如要執行使用 Driver SDK 建構的應用程式,Android 裝置必須具備 Google Play 服務 已安裝。

設定開發專案

設定開發專案並取得 API 金鑰 建立專案:

  1. 建立新的 Google Cloud 控制台專案或選取現有專案,以便使用 驅動程式 SDK 版本請稍候片刻,直到 新專案會顯示在 Google Cloud 控制台中

  2. 如要執行試用版應用程式,專案必須具備 Maps SDK 的存取權 。在 Google Cloud 控制台中,選取 API 與服務 >程式庫,然後搜尋並啟用 Maps SDK for Android。

  3. 選取專案的 API 金鑰,取得專案的 API 金鑰 API 與服務 >憑證 >建立憑證 >API 金鑰。 如要進一步瞭解如何取得 API 金鑰,請參閱 取得 API 金鑰

在應用程式中新增驅動程式 SDK

您可以從 Google Maven 存放區取得驅動程式 SDK。 存放區包括 SDK 的專案物件模型 (.pom) 檔案和 Javadocs。在應用程式中新增 Driver SDK:

  1. 將以下依附元件新增至 Gradle 或 Maven 設定,將 所需驅動程式 SDK 版本的 VERSION_NUMBER 預留位置。

    Gradle

    請將以下內容新增到您的 build.gradle 中:

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

    Maven

    請將以下內容新增到您的 pom.xml 中:

    <dependencies>
      ...
      <dependency>
        <groupId>com.google.android.libraries.mapsplatform.transportation</groupId>
        <artifactId>transportation-driver</artifactId>
        <version>VERSION_NUMBER</version>
      </dependency>
    </dependencies>
    
  2. 驅動程式 SDK 依附於 Navigation SDK,此依附元件是由 以便在需要特定版本的 Navigation SDK 時 明確定義,如下所示: 省略上述程式碼區塊後,專案就會一律下載 主要發布版本中最新版 Navigation SDK。 請注意,最新版驅動程式 SDK 和 Navigation SDK 發布前已進行嚴格的測試。

    排列開發和發布版本的依附元件設定 部署應用程式

    Gradle

    請將以下內容新增到您的 build.gradle 中:

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

    Maven

    請將以下內容新增到您的 pom.xml 中:

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

在應用程式中加入 API 金鑰

在應用程式中加入 Driver SDK 後,請將 API 金鑰加進應用程式。個人中心 您必須使用在測試期間取得的專案 API 金鑰 設定開發專案

本節說明如何儲存 API 金鑰,讓金鑰更安全 由您的應用程式參照。請勿檢查 API 金鑰版本 控制系統這個檔案應儲存在 local.properties 檔案中 這個目錄位於專案的根目錄如要進一步瞭解 local.properties 個檔案,請參閱 Gradle 屬性檔案

您可以使用 Secrets Gradle Plugin for Android 來簡化這項工作。

如要安裝這個外掛程式並儲存 API 金鑰,請按照下列步驟操作:

  1. 開啟根層級的 build.gradle 檔案,然後將下列程式碼加進 buildscript 底下的 dependencies 元素。

    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. 開啟應用程式層級的 build.gradle 檔案,然後將下列程式碼加進 plugins 元素。

    Groovy

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

    Kotlin

    id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin")
    
  3. 如果您使用的是 Android Studio 使用 Gradle 同步處理專案

  4. 在專案層級目錄中開啟 local.properties 並新增 下方的程式碼。然後將 YOUR_API_KEY 替換成您的 API 金鑰。

    MAPS_API_KEY=YOUR_API_KEY
    
  5. 透過 AndroidManifest.xml 檔案前往 com.google.android.geo.API_KEY 然後更新 android:value 屬性,如下所示:

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

以下範例顯示範例應用程式的完整資訊清單:

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

在應用程式中加入必要的作者資訊

如果您在應用程式中使用 Driver SDK,則必須納入 將作者資訊文字和開放原始碼授權納入應用程式的法律聲明中 專區。最好的方法是將出處資訊列為獨立的選單項目,或者 「關於」選單項目的一部分

您可以在「third_party_licenses.txt」中找到授權資訊該檔案位於 已取消封存的 AAR 檔案

請參閱 https://developers.google.com/android/guides/opensource ,瞭解如何納入開放原始碼通知。

依附元件

如果您使用 ProGuard 您可能需要將下列幾行程式碼加入 ProGuard 中,將建構作業最佳化 設定檔:

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

支援的最低 API 級別為 23。

初始化 SDK

您必須提供供應商 ID (通常為 Google Cloud 專案 ID),才能 初始化 DriverContext 物件。如要進一步瞭解如何設定 Google Cloud 專案,請參閱 驗證與授權

使用 Driver SDK 前,必須先初始化 Navigation SDK。如要初始化 SDK:

  1. NavigationApi 取得 Navigator 物件。

    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. 建立 DriverContext 物件,並填入必填欄位。

    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. 使用 DriverContext 物件初始化 *DriverApi

    Java

    RidesharingDriverApi ridesharingDriverApi = RidesharingDriverApi.createInstance(driverContext);
    

    Kotlin

    val ridesharingDriverApi = RidesharingDriverApi.createInstance(driverContext)
    
  4. 從 API 物件取得 RidesharingVehicleReporter。 (*VehicleReporter 擴充 NavigationVehicleReporter)。

    Java

    RidesharingVehicleReporter vehicleReporter = ridesharingDriverApi.getRidesharingVehicleReporter();
    

    Kotlin

    val vehicleReporter = ridesharingDriverApi.getRidesharingVehicleReporter()
    

使用 AuthTokenFactory 進行驗證

當驅動程式 SDK 產生位置更新時, 必須將這些更新傳送至 Fleet Engine 伺服器為了驗證這些要求, 驅動程式 SDK 會呼叫呼叫端提供的 AuthTokenFactory 的執行個體。 工廠負責產生所在位置的驗證權杖 更新時間。

每個開發人員的情況各有不同的符記產生方式。 不過,實作可能需要:

  • 從 HTTPS 伺服器擷取驗證權杖 (可能採用 JSON 格式)
  • 剖析及快取權杖
  • 重新整理權杖

如要進一步瞭解 Fleet Engine 伺服器預期的權杖,請參閱 建立用於授權的 JSON Web Token (JWT)

以下是 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)
    }
  }
}

這個特定實作會使用內建的 Java HTTP 用戶端,擷取 產生 JSON 格式的權杖權杖是 儲存以供重複使用如果舊的權杖在 10 分鐘內,系統會重新擷取權杖 才會達到使用門檻

實作項目可能會有不同,例如使用背景執行緒 重新整理符記

除非 AuthTokenFactory 發生例外狀況,否則系統會將例外狀況視為暫時處理 重複執行。嘗試多次嘗試後,驅動程式 SDK 會假設 錯誤永久有效,且會停止嘗試傳送更新。

StatusListener」的狀態和 Error Reporting

由於驅動程式 SDK 會在 背景,使用 StatusListener,以便在特定情況下觸發通知 事件,例如錯誤、警告或偵錯訊息錯誤可能是 短暫出現 (例如 BACKEND_CONNECTIVITY_ERROR),否則可能會 這會永久停止位置更新 (例如 VEHICLE_NOT_FOUND、 表示設定錯誤)。

您可以自行提供選用的 StatusListener 實作項目,如下所示:

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

SSL/TLS 注意事項

在內部,驅動程式 SDK 實作會使用 採用 SSL/TLS 進行安全通訊 與 Fleet Engine 伺服器連線舊版 Android (API 19 或 較低) 可能需要 SecurityProvider 修補程式,才能與 伺服器您應該會看到 文章 。這篇文章 包含修補安全性提供者的程式碼範例。

啟用位置更新功能

建立 *VehicleReporter 執行個體後,啟用位置更新功能 直截了當:

Java

RidesharingVehicleReporter reporter = ...;

reporter.enableLocationTracking();

Kotlin

val reporter = ...

reporter.enableLocationTracking()

當車輛狀態處於以下狀態時,系統會定期傳送位置更新資訊 ONLINE。請注意,呼叫 reporter.enableLocationTracking() 不會 自動將車輛狀態設為 ONLINE。您必須 明確設定車輛狀態

報表間隔預設為 10 秒,報表間隔 變更為 reporter.setLocationReportingInterval(long, TimeUnit)。 支援的更新時間間隔下限為 5 秒。如要提高更新頻率 會導致要求變慢並發生錯誤。

停用位置更新通知

司機的班次完成後,即可停止位置更新, 撥打電話,將車輛標示為離線 DeliveryVehicleReporter.disableLocationTrackingRidesharingVehicleReporter.disableLocationTracking

這次呼叫會安排立即傳送一次最終更新。 代表車輛離線。這次更新將不包含使用者的 或 HTTP/HTTPS 位置

設定車輛狀態

啟用位置更新功能後,將車輛狀態設為 ONLINE 會 開放車輛進行 SearchVehicles 查詢。所以在 交通工具 OFFLINE 會將這輛車標示為無法預訂。

你可以選擇在伺服器端設定車輛狀態 (請參閱「更新 汽車), 或在 Driver SDK 中直接使用:

Java

RidesharingVehicleReporter reporter = ...;

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

Kotlin

val reporter = ...

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

啟用位置更新功能後,對 setVehicleState 的呼叫會傳播於 下一點的位置更新。

如未啟用位置追蹤功能,將車輛標示為「ONLINE」將會 在 IllegalStateException 中。車輛可在出現以下情況時標示為 OFFLINE 未啟用或明確停用位置追蹤功能。這會產生 就能取得所需支援對 RidesharingVehicleReporter.disableLocationTracking()會 將車輛狀態設為 OFFLINE

請注意,setVehicleState 會立即傳回,且更新作業會在 位置資訊更新會話串。與位置更新錯誤處理方式類似 更新車輛狀態,可視需求提供的 已在 DriverContext 中設定 StatusListener