開始使用 Android 版 Driver SDK

基本系統需求

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

Maven 設定

Google Maven 存放區提供驅動程式 SDK 4.99 以上版本。

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

設定開發專案

如要在 Google Cloud 控制台中設定開發專案並取得專案的 API 金鑰,請按照下列步驟操作:

  1. 建立新的 Google Cloud 控制台專案,或選取現有專案,以便與 Driver SDK 搭配使用。等待幾分鐘,新的專案在 Google Cloud 控制台中顯示。

  2. 如要執行試用版應用程式,您的專案必須能存取 Maps SDK for Android。在 Google Cloud 控制台中,依序選取「APIs & Services」(API 和服務) >「Library」(程式庫),然後搜尋並啟用 Maps SDK for Android。

  3. 依序選取「APIs & Services」(API 和服務) >「Credentials」(憑證) >「Create credentials」(建立憑證) >「API key」(API 金鑰),以取得專案的 API 金鑰。如要進一步瞭解如何取得 API 金鑰,請參閱「取得 API 金鑰」一文。

在應用程式中新增 Driver 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.driver</groupId>
        <artifactId>transportation-driver</artifactId>
        <version>[VERSION_NUMBER]</version>
      </dependency>
    </dependencies>
    

在應用程式中加入 API 金鑰

將驅動程式 SDK 加入應用程式後,請將 API 金鑰新增至應用程式。您必須使用在設定開發專案時取得的專案 API 金鑰。

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

請使用 Secrets Gradle Plugin for Android 來簡化這項工作。請按照這個程序安裝 Secrets Gradle 外掛程式,並安全地儲存 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. 將專案與 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>

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

如果您在應用程式中使用驅動程式 SDK,就必須在應用程式的法律聲明部分中納入作者資訊文字和開放原始碼授權。建議將作者資訊新增為獨立的選單項目,或是做為「About」選單項目的一部分。

您可以在 Driver SDK ZIP 檔案中找到所需的作者資訊文字和開放原始碼授權:

  • NOTICE.txt
  • LICENSES.txt

依附元件

Driver SDK 會使用 gRPC 與 Fleet Engine 伺服器進行通訊。如果您尚未匯入 gRPC,可能需要宣告下列依附元件:

dependencies {
    implementation 'io.grpc:grpc-android:1.12.0'
    implementation 'io.grpc:grpc-okhttp:1.12.0'
}

如果沒有這些依附元件,驅動程式 SDK 在嘗試與 Fleet Engine 伺服器通訊時,可能會在執行階段發生錯誤。

如果您使用 ProGuard 最佳化建構作業,可能需要在 ProGuard 設定檔中加入以下幾行內容:

-dontwarn com.google.**
-dontwarn io.grpc.**
-dontwarn okio.**

支援的最低 API 級別為 23。

初始化 SDK

初始化 DriverContext 物件需要提供者 ID (通常為 Google Cloud 專案 ID)。如要進一步瞭解如何設定 Google Cloud 專案,請參閱「驗證及授權」。

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

  1. NavigationApi 取得 Navigator 物件。

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

    DriverContext driverContext = DriverContext.builder(application)
        .setProviderId(providerId)
        .setVehicleId(vehicleId)
        .setAuthTokenFactory(authTokenFactory)
        .setNavigator(navigator)
        .setRoadSnappedLocationProvider(
            NavigationApi.getRoadSnappedLocationProvider(application))
        .build();
    
  3. 使用 DriverContext 物件初始化 *DriverApi

    DeliveryDriverApi driverApi = DeliveryDriverApi.createInstance(driverContext);
    
  4. 從 API 物件取得 DeliveryVehicleReporter。(DeliveryVehicleReporter 擴充 NavigationVehicleReporter)。

    DeliveryVehicleReporter vehicleReporter = driverApi.getDeliveryVehicleReporter();
    

透過 AuthTokenFactory 進行驗證

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

權杖的產生方式會因開發人員的情況而有所不同。不過,實作可能需要:

  • 從 HTTPS 伺服器擷取驗證權杖 (可能為 JSON 格式)
  • 剖析及快取權杖
  • 權杖過期時

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

以下是 AuthTokenFactory 的架構實作:

class JsonAuthTokenFactory implements AuthTokenFactory {
  private String vehicleServiceToken;  // 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(vehicleId);
    }
    if (ServiceType.VEHICLE.equals(authTokenContext.getServiceType)) {
      return vehicleServiceToken;
    } else {
      throw new RuntimeException("Unsupported ServiceType: " + authTokenContext.getServiceType());
    }
  }

  private void fetchNewToken(String vehicleId) {
    String url = "https://yourauthserver.example/token/" + vehicleId;

    try (Reader r = new InputStreamReader(new URL(url).openStream())) {
      com.google.gson.JsonObject obj
          = com.google.gson.JsonParser.parseReader(r).getAsJsonObject();
      vehicleServiceToken = obj.get("VehicleServiceToken").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);
    }
  }
}

這個特定實作使用內建的 Java HTTP 用戶端,從開發人員的驗證伺服器擷取 JSON 格式的權杖。系統會儲存權杖以供重複使用。如果舊權杖在過期後的 10 分鐘內,系統就會重新擷取權杖。

您的實作方式可能會以不同方式執行,例如使用背景執行緒重新整理權杖。

AuthTokenFactory 中的例外狀況會被視為暫時性的,除非重複發生。經過多次嘗試後,驅動程式 SDK 會假設錯誤永久有效,並停止嘗試傳送更新。

StatusListener」的狀態和 Error Reporting

由於驅動程式 SDK 會在背景執行動作,因此使用 StatusListener 即可在特定事件發生 (例如錯誤、警告或偵錯訊息) 時觸發通知。錯誤可能是暫時性的 (例如 BACKEND_CONNECTIVITY_ERROR),也可能導致位置更新遭到永久停止 (例如 VEHICLE_NOT_FOUND,表示設定錯誤)。

您可以提供選用的 StatusListener 實作方式,如下所示:

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

SSL/TLS 注意事項

驅動程式 SDK 實作會在內部使用 SSL/TLS,與 Fleet Engine 伺服器安全地進行通訊。舊版 Android (API 23 以下版本) 可能需要 SecurityProvider 修補程式,才能與伺服器通訊。如要進一步瞭解如何在 Android 中使用 SSL,請參閱「安全性 GMS 供應商」。 本文也包含用於修補安全性供應商的程式碼範例。

啟用位置更新通知

建立 *VehicleReporter 執行個體後,啟用位置更新便十分簡單:

DeliveryVehicleReporter reporter = ...;

reporter.enableLocationTracking();

如果可以,系統將定期傳送位置更新資訊。每次位置更新也都會表示車輛已連線。

報表間隔預設為 10 秒。您可以使用 reporter.setLocationReportingInterval(long, TimeUnit) 變更報表間隔。支援的更新間隔下限為 5 秒。頻繁更新可能會導致要求和錯誤變慢。

停用位置更新功能

駕駛人輪班後,呼叫 DeliveryVehicleReporter.disableLocationTracking 即可停止位置更新通知。

可靠的模型用途

本節說明如何在使用信任的模型時,透過驅動程式 SDK 實作常見用途。

建立車輛

您可以透過 Driver SDK 建立車輛。

建立車輛之前,請務必初始化 Delivery Driver API。建立車輛 ID 時,請務必使用駕駛 SDK 初始化期間使用的車輛和供應商 ID。然後建立車輛,如以下範例所示:

DeliveryDriverApi api = DeliveryDriverApi.getInstance();
DeliveryVehicleManager vehicleManager = api.getDeliveryVehicleManager();
try {
  DeliveryVehicle vehicle = vehicleManager.createVehicle().get();
  // Handle CreateVehicleRequest DeliveryVehicle response.
} catch (Exception e) {
  // Handle CreateVehicleRequest error.
}

建立出貨取貨工作

您可以透過 Driver SDK 建立出貨取貨工作。

建立工作之前,請務必初始化 Delivery Driver API。工作必須使用在驅動程式 SDK 初始化期間指定的供應商 ID 建立。接著建立出貨取貨工作,如以下範例所示。如需工作 ID 的相關資訊,請參閱「工作 ID 範例」。

static final String TASK_ID = "task-8241890"; // Avoid auto-incrementing IDs.

DeliveryDriverApi api = DeliveryDriverApi.getInstance();
DeliveryTaskManager taskManager = api.getDeliveryTaskManager();
CreateDeliveryTaskRequest request = CreateDeliveryTaskRequest.builder(TASK_ID)
   .setPlannedWaypoint(Waypoint.builder().setLatLng(-6.195139, 106.820826).build())
   .setTaskDurationSeconds(2 * 60)
   .setParentId("my-tracking-id")
   .setTaskType(TaskType.DELIVERY_PICKUP)
   .build();

try {
   DeliveryTask task = taskManager.createTask(request).get();
   // Handle CreateTaskRequest DeliveryTask response.
} catch (Exception e)  {
   // Handle CreateTaskRequest error.
}

建立出貨工作

您可以透過 Driver SDK 建立運送交付工作。

建立工作之前,請務必初始化 Delivery Driver API。然後建立運送交付工作,如以下範例所示。如需工作 ID 的相關資訊,請參閱「工作 ID 範例」。

static final String TASK_ID = "task-8241890"; // Avoid auto-incrementing IDs.

DeliveryDriverApi api = DeliveryDriverApi.getInstance();
DeliveryTaskManager taskManager = api.getDeliveryTaskManager();
CreateDeliveryTaskRequest request = CreateDeliveryTaskRequest.builder(TASK_ID)
   .setPlannedWaypoint(Waypoint.builder().setLatLng(-6.195139, 106.820826).build())
   .setTaskDurationSeconds(2 * 60)
   .setParentId("my-tracking-id")
   .setTaskType(TaskType.DELIVERY_DELIVERY)
   .build();
try {
   DeliveryTask task = taskManager.createTask(request).get();
   // Handle CreateTaskRequest DeliveryTask response.
} catch (Exception e)  {
   // Handle CreateTaskRequest error.
}

預定無法使用

您可以建立一個工作,指出驅動程式 SDK 無法使用 (例如駕駛中斷或車輛拒絕)。排定的無法使用工作不得包含追蹤 ID。您也可以選擇提供位置。

建立工作之前,請務必初始化 Delivery Driver API。接著建立無法使用的工作,如以下範例所示。如需工作 ID 的相關資訊,請參閱「工作 ID 範例」。

static final String TASK_ID = "task-8241890"; // Avoid auto-incrementing IDs.

DeliveryDriverApi api = DeliveryDriverApi.getInstance();
DeliveryTaskManager taskManager = api.getDeliveryTaskManager();
CreateDeliveryTaskRequest request = CreateDeliveryTaskRequest.builder(TASK_ID)
   .setTaskDurationSeconds(2 * 60) // Duration or location (or both) must be provided for a BREAK task.
   .setTaskType(TaskType.UNAVAILABLE)
   .build();
try {
   DeliveryTask task = taskManager.createTask(request).get();
   // Handle CreateTaskRequest DeliveryTask response.
} catch (Exception e)  {
   // Handle CreateTaskRequest error.
}

排定的停靠站

您可以透過 Driver SDK 建立排定的停止工作。排定的停止工作可能不包含追蹤 ID。

建立工作之前,請務必初始化 Delivery Driver API。接著建立排定的停止工作,如以下範例所示。如需工作 ID 的相關資訊,請參閱「工作 ID 範例」。

    static final String TASK_ID = "task-8241890"; //  Avoid auto-incrementing IDs.

    DeliveryDriverApi api = DeliveryDriverApi.getInstance();
    DeliveryTaskManager taskManager = api.getDeliveryTaskManager();
    CreateDeliveryTaskRequest request = CreateDeliveryTaskRequest.builder(TASK_ID)
       .setPlannedWaypoint(Waypoint.builder().setLatLng(-6.195139, 106.820826).build())
       .setTaskDurationSeconds(2 * 60)
       .setTaskType(TaskType.DELIVERY_SCHEDULED_STOP)
       .build();
    try {
       DeliveryTask task = taskManager.createTask(request).get();
       // Handle CreateTaskRequest DeliveryTask response.
    } catch (Exception e)  {
       // Handle CreateTaskRequest error.
    }

更新工作排序方式

您可以透過驅動程式 SDK 更新指派給車輛的工作執行順序。

更新工作順序後,如果之前從未指派給車輛,這些工作也會指派到車輛。這樣做也會關閉先前指派給車輛且未更新順序的工作。如果先前已指派給其他車輛,則將某項任務指派給其他車輛會產生錯誤。將任務指派給新車輛前,請先關閉現有工作,然後建立新工作。

你隨時可以更新工作排序方式。

更新車輛的工作順序之前,請確認車輛和工作已在 Fleet Engine 中建立。然後更新車輛的工作順序,如以下範例所示。

    DeliveryDriverApi api = DeliveryDriverApi.getInstance();
    DeliveryVehicleReporter reporter = api.getDeliveryVehicleReporter();
    try {
       List<VehicleStop> stops = reporter.setVehicleStops(
         ImmutableList.of(
             VehicleStop.builder()
                 .setVehicleStopState(VehicleStopState.ARRIVED)
                 .setWaypoint(Waypoint.builder().setLatLng(37.1749, 122.412).build())
                 .setTasks(ImmutableList.of(task1)) // Previously created DeliveryTask in Fleet Engine.
                 .build(),
             VehicleStop.builder()
                 .setVehicleStopState(VehicleStopState.NEW) // The current vehicle stop.
                 .setWaypoint(Waypoint.builder().setLatLng(37.7749, 122.4194).build())
                 .setTasks(ImmutableList.of(task2)) // Previously created DeliveryTask in Fleet Engine.
                 .build(),
             VehicleStop.builder()
                 .setVehicleStopState(VehicleStopState.NEW)
                 .setWaypoint(Waypoint.builder().setLatLng(37.3382, 121.8863).build())
                 .setTasks(ImmutableList.of(task3, task4)) // Previously created DeliveryTasks in Fleet Engine.
                 .build())).get();
       // Successfully updated vehicle stops in Fleet Engine. Returns the successfully set VehicleStops.
    } catch (Exception e)  {
       // Failed to update vehicle stops in Fleet Engine. Setting VehicleStops must be attempted again after resolving
       // errors.
    }

例外狀況可能會導致驅動程式 SDK 的內部狀態更新。如果發生這種情況,請解決問題,然後再次呼叫 setVehicleStops,直到呼叫成功為止。

可能的問題包括:

  • 指定的 VehicleStops 不符合有效的模式。只有第一個 VehicleStops 可以位於任何 VehicleStopStates:NEW、ENROUTE 或 ARRIVED。目前停靠站之後的 VehicleStops 必須位於新 VehicleStopState。

  • 工作不存在,或是工作屬於其他車輛。

  • 這輛車不存在。

車輛正在前往下一個停靠站

在車輛從停靠站出發及開始導航時,Fleet Engine 必須發出通知。您可以從 Driver SDK 通知 Fleet Engine,

通知 Fleet Engine 車輛已從停靠站出發之前,請確認車輛已建立並設定停靠站。接著通知 Fleet Engine 車輛的出發時間,如以下範例所示。

    DeliveryDriverApi api = DeliveryDriverApi.getInstance();
    DeliveryVehicleReporter reporter = api.getDeliveryVehicleReporter();
    reporter.enableLocationTracking(); // Location tracking must be enabled.

    // Create Vehicle, VehicleStops, and DeliveryTasks.
    // Set VehicleStops on Vehicle.

    navigator.setDestination(vehicleStop.getWaypoint());
    try {
       List<VehicleStop> updatedStops = reporter.enrouteToNextStop().get();
       // Successfully updated vehicle stops in Fleet Engine. Returns the set VehicleStops, with the first
       // VehicleStop updated to ENROUTE state.
    } catch (Exception e)  {
       // Failed to update vehicle stops in Fleet Engine. Updating VehicleStops must be attempted again
       // after resolving errors.
    }

例外狀況可能會導致驅動程式 SDK 的內部狀態更新。如果發生這種情況,請解決問題,然後再次呼叫 enrouteToNextStop,直到成功為止。

可能的問題包括:

  • Driver SDK 中沒有剩餘的 VehicleStops

車輛抵達停靠站

Fleet Engine 必須在車輛抵達停靠站時收到通知。您可以從驅動程式 SDK 通知 Fleet Engine。

通知 Fleet Engine 有車輛已抵達停靠站之前,請確認車輛已停靠。接著,如以下範例所示,通知 Fleet Engine 車輛已抵達停靠站。

DeliveryDriverApi api = DeliveryDriverApi.getInstance();
DeliveryVehicleReporter reporter = api.getDeliveryVehicleReporter();
reporter.enableLocationTracking(); // Location tracking must be enabled.

// Create Vehicle, VehicleStops, and DeliveryTasks.
// Set VehicleStops on Vehicle.
// Mark ENROUTE to VehicleStop and start guidance using Navigator.

try {
   List<VehicleStop> updatedStopsArrived = reporter.arrivedAtStop().get();
   // Successfully updated vehicle stops in Fleet Engine. Returns the set VehicleStops, with the first
   // VehicleStop updated to ARRIVED state.
   navigator.clearDestinations();
} catch (Exception e)  {
   // Failed to update vehicle stops in Fleet Engine. Updating VehicleStops must be attempted again
   // after resolving errors.
}

但可能會發生例外狀況,導致驅動程式 SDK 的內部狀態無法更新。如果發生這種情況,請解決問題,然後再次呼叫 arrivedAtStop,直到成功為止。

可能的問題包括:

  • Driver SDK 中沒有剩餘的 VehicleStops

車輛完成停靠站

在車輛完成停靠站時,您必須通知 Fleet Engine。這項通知會讓所有與停靠站相關聯的工作都設為「關閉」狀態。您可以從驅動程式 SDK 通知 Fleet Engine。

通知 Fleet Engine 車輛已完成 VehicleStop,如以下範例所示。

    DeliveryDriverApi api = DeliveryDriverApi.getInstance();
    DeliveryVehicleReporter reporter = api.getDeliveryVehicleReporter();
    reporter.enableLocationTracking(); // Location tracking must be enabled.

    // After completing the tasks at the VehicleStop, remove it from the
    // the current list of VehicleStops.

    try {
       List<VehicleStop> updatedStopsCompleted = reporter.completedStop().get();
       // Successfully updated vehicle stops in Fleet Engine. All tasks on the completed stop are set to CLOSED.
       // Returns the set VehicleStops, with the completed VehicleStop removed from the remaining list.
    } catch (Exception e)  {
       // Failed to update vehicle stops in Fleet Engine. Updating VehicleStops must be attempted again
       // after resolving errors.
    }

但可能會發生例外狀況,導致驅動程式 SDK 的內部狀態無法更新。如果發生這種情況,請解決問題,然後再次呼叫 completedStop,直到成功為止。

可能的問題包括:

  • Driver SDK 中沒有剩餘的 VehicleStops

關閉工作

如要關閉已指派給車輛的工作,請通知 Fleet Engine 表示車輛已完成工作發生的停靠站,或將該工作從車輛停靠站清單中移除。如要這麼做,可以設定其餘車輛停靠站清單,就像為車輛更新工作順序一樣。

如果任務尚未指派給具有需要關閉的車輛,請將任務更新為「已關閉」狀態。不過,「已關閉」的工作不能重新開啟,

關閉工作並不表示成功或失敗,表示不再考慮工作為追蹤運送狀態,請務必指出工作的實際結果,以便顯示交付結果。

您必須將任務指派給車輛,才能使用驅動程式 SDK 關閉任務。如要關閉已指派給車輛的工作,請通知 Fleet Engine 表示車輛已完成工作執行停靠站。

或者,您也可以針對指派給任務的車輛更新工作順序,然後再將任務從停靠站清單中移除。

設定工作結果和結果位置

關閉工作並不表示成功或失敗,表示不再考慮工作就運送追蹤而言,請務必指定任務的實際結果,以便顯示運送結果,以利系統依據適當的服務收費。設定後,就無法變更工作結果。但您可以在設定工作結果時間和工作結果位置之後,修改這些結果。

狀態為「已關閉」的工作可將結果設為「SUCCEEDED」(已完成) 或「FAILED」(失敗)。Fleet Engine 只會針對狀態為「成功」的交付工作收取費用。

標示任務的結果時,Fleet Engine 會自動將工作結果位置填入最後已知的車輛位置。您可以覆寫這個行為。

以下範例說明如何使用驅動程式 SDK 設定工作結果和時間戳記。您無法使用驅動程式 SDK 設定工作結果位置。

    static final String TASK_ID = "task-8241890";

    DeliveryDriverApi api = DeliveryDriverApi.getInstance();
    DeliveryTaskManager taskManager = api.getDeliveryTaskManager();

    // Updating an existing DeliveryTask which is already CLOSED. Manually
    // setting TaskOutcomeLocation with Driver SDK is not supported at this time.
    UpdateDeliveryTaskRequest req = UpdateDeliveryTaskRequest.builder(TASK_ID)
        .setTaskOutcome(TaskOutcome.SUCCEEDED)
        .setTaskOutcomeTimestamp(now()) // Timestamp in milliseconds.
        .build();

    try {
       DeliveryTask updatedTask = taskManager.updateTask(req);
       // Handle UpdateTaskRequest DeliveryTask response.
    } catch (Exception e)  {
       // Handle UpdateTaskRequest error.
    }

查詢車輛

您可以透過驅動程式 SDK 查詢車輛。查詢車輛前,請務必先初始化 Delivery Driver API。接著,您就可以查詢這輛車,如以下範例所示。

    DeliveryDriverApi api = DeliveryDriverApi.getInstance();
    DeliveryVehicleManager vehicleManager = api.getDeliveryVehicleManager();
    try {
       DeliveryVehicle vehicle = vehicleManager.getVehicle().get();
       // Handle GetVehicleRequest DeliveryVehicle response.
    } catch (Exception e)  {
       // Handle GetVehicleRequest error.
    }

DeliveryVehicleManager 只能查詢 DeliveryVehicle,以取得在 Delivery Driver API 初始化期間提供的車輛 ID。