在 Android 中追蹤行程

選取平台: Android iOS JavaScript

當您追蹤行程時,消費者應用程式會向消費者顯示適當車輛的位置。為此,應用程式需要開始追蹤行程、更新行程進度,並在行程完成時停止追蹤。

本文件將說明這項程序的運作方式。

事前準備

請確認已完成下列設定:

  • 消費者應用程式的後端服務已就位,且用於將消費者與車輛配對的服務已可運作。

  • 您已為應用程式設定地圖

開始追蹤行程

當後端伺服器將使用者與車輛配對時,請使用 JourneySharingSession 開始追蹤行程。

下列程式碼範例示範如何在檢視畫面載入後開始追蹤行程。

Java

public class MainActivity extends AppCompatActivity
    implements ConsumerViewModel.JourneySharingListener  {

  // Class implementation

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Create a TripModel instance to listen for updates to the trip specified by this trip name.
    String tripName = ...;
    TripModelManager tripModelManager = consumerApi.getTripModelManager();
    TripModel tripModel = tripModelManager.getTripModel(tripName);

    // Create a JourneySharingSession instance based on the TripModel.
    JourneySharingSession session = JourneySharingSession.createInstance(tripModel);

    // Add the JourneySharingSession instance on the map for updating the UI.
    consumerController.showSession(session);

    // Register for trip update events.
    tripModel.registerTripCallback(new TripModelCallback() {
      @Override
      public void onTripETAToNextWaypointUpdated(
          TripInfo tripInfo, @Nullable Long timestampMillis) {
        // ...
      }

      @Override
      public void onTripActiveRouteRemainingDistanceUpdated(
          TripInfo tripInfo, @Nullable Integer distanceMeters) {
        // ...
      }

      // ...
    });
  }

  @Override
  protected void onDestroy() {
    super.onDestroy();

    if (journeySharingSession != null) {
      journeySharingSession.stop();
    }
  }
}

Kotlin

class SampleAppActivity : AppCompatActivity(), ConsumerViewModel.JourneySharingListener {

  // Class implementation

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    // Create a TripModel instance to listen for updates to the trip specified by this trip name.
    val tripName = "tripName"
    val tripModelManager = consumerApi.getTripModelManager()
    val tripModel = tripModelManager.getTripModel(tripName)

    // Create a JourneySharingSession instance based on the TripModel.
    val session = JourneySharingSession.createInstance(tripModel)

    // Add the JourneySharingSession instance on the map for updating the UI.
    consumerController.showSession(session)

    // Register for trip update events.
    tripModel.registerTripCallback(
      object : TripModelCallback() {
        override fun onTripETAToNextWaypointUpdated(
          tripInfo: TripInfo,
          timestampMillis: Long?,
        ) {
          // ...
        }

        override fun onTripActiveRouteRemainingDistanceUpdated(
          tripInfo: TripInfo,
          distanceMeters: Int?,
        ) {
          // ...
        }

      // ...
    })
  }

  override fun onDestroy() {
    super.onDestroy()

    journeySharingSession?.stop()
  }
}

更新行程進度

如要更新行程進度詳細資料,例如車輛抵達前需要行駛的距離和預估抵達時間,應用程式需要註冊並設定事件監聽器,如以下範例所示。

  1. TripModel 物件上註冊監聽器。

    Java

    // Create a TripModel instance for listening to updates to the trip specified by this trip name.
    String tripName = ...;
    TripModelManager tripModelManager = consumerApi.getTripModelManager();
    TripModel tripModel = tripModelManager.getTripModel(tripName);
    
    // Create a JourneySharingSession instance based on the TripModel.
    JourneySharingSession session = JourneySharingSession.createInstance(tripModel);
    
    // Add the JourneySharingSession instance on the map for updating the UI.
    consumerController.showSession(session);
    
    // Register for trip update events.
    tripModel.registerTripCallback(new TripModelCallback() {
    @Override
    public void onTripETAToNextWaypointUpdated(
            TripInfo tripInfo, @Nullable Long timestampMillis) {
          // ...
    }
    
    @Override
    public void onTripActiveRouteRemainingDistanceUpdated(
            TripInfo tripInfo, @Nullable Integer distanceMeters) {
          // ...
    }
    
    // ...
    });
    

    Kotlin

    // Create a TripModel instance for listening to updates to the trip specified by this trip name.
    val tripName = "tripName"
    val tripModelManager = consumerApi.getTripModelManager()
    val tripModel = tripModelManager.getTripModel(tripName)
    
    // Create a JourneySharingSession instance based on the TripModel.
    val session = JourneySharingSession.createInstance(tripModel)
    
    // Add the JourneySharingSession instance on the map for updating the UI.
    consumerController.showSession(session)
    
    // Register for trip update events.
    tripModel.registerTripCallback(
      object : TripModelCallback() {
        override fun onTripETAToNextWaypointUpdated(
          tripInfo: TripInfo,
          timestampMillis: Long?,
        ) {
          // ...
        }
    
        override fun onTripActiveRouteRemainingDistanceUpdated(
          tripInfo: TripInfo,
          distanceMeters: Int?,
        ) {
          // ...
        }
    
      // ...
    })
    
  2. 使用 TripModelOptions 為行程設定事件監聽器。

    Java

    // Set refresh interval to 2 seconds.
    TripModelOptions tripOptions =
          TripModelOptions.builder().setRefreshIntervalMillis(2000).build();
    tripModel.setTripModelOptions(tripOptions);
    

    Kotlin

    // Set refresh interval to 2 seconds.
    val tripOptions = TripModelOptions.builder().setRefreshIntervalMillis(2000).build()
    tripModel.setTripModelOptions(tripOptions)
    

停止追蹤行程

請確認應用程式在不再需要時停止追蹤行程,例如當駕駛員在後端將行程標示為「完成」時。停止行程分享可避免向 Fleet Engine 提出不必要的網路要求,並防止記憶體外洩。

使用 JourneySharingSession 停止追蹤行程,如以下程式碼範例所示。

Java

public class MainActivity extends AppCompatActivity
    implements ConsumerViewModel.JourneySharingListener  {

  // Class implementation

  @Override
  protected void onDestroy() {
    super.onDestroy();

    if (journeySharingSession != null) {
      journeySharingSession.stop();
    }
  }
}

Kotlin

class SampleAppActivity : AppCompatActivity(), ConsumerViewModel.JourneySharingListener {

  // Class implementation

  override fun onDestroy() {
    super.onDestroy()

    journeySharingSession?.stop()
  }
}

處理行程錯誤

onTripRefreshError 方法會顯示行程監控期間發生的錯誤。錯誤訊息遵循 Google Cloud 錯誤標準。如需錯誤訊息定義和所有錯誤代碼的詳細資訊,請參閱 Google Cloud 錯誤說明文件

以下是行程監控期間可能發生的常見錯誤:

HTTP RPC 說明
400 INVALID_ARGUMENT 用戶端指定的旅遊名稱無效。行程名稱必須採用 providers/{provider_id}/trips/{trip_id} 格式。provider_id 必須是服務供應商擁有的 Cloud 專案 ID。
401 UNAUTHENTICATED 如果沒有有效的驗證憑證,就會收到這項錯誤訊息。例如,如果 JWT 憑證未經簽署就附上行程 ID,或是 JWT 憑證已過期。
403 PERMISSION_DENIED 如果用戶端沒有足夠的權限 (例如,具有消費者角色的使用者嘗試呼叫 updateTrip)、JWT 權杖無效,或是用戶端專案未啟用 API,就會收到這則錯誤訊息。JWT 權杖可能遺失,或是權杖使用與要求行程 ID 不符的行程 ID 進行簽署。
429 RESOURCE_EXHAUSTED 資源配額為零,或流量頻率超出限制。
503 無法使用 服務無法使用,通常是因伺服器停止運作所致。
504 DEADLINE_EXCEEDED 已超出要求期限。只有在呼叫者設定的期限短於方法的預設期限 (即要求的期限不夠讓伺服器處理要求),且要求未在期限內完成時,才會發生這項錯誤。

處理 Consumer SDK 錯誤

Consumer SDK 會使用回呼機制,將行程更新錯誤傳送至消費者應用程式。回呼參數是特定平台的傳回類型 (Android 上的 TripUpdateError,iOS 上的 NSError)。

擷取狀態碼

傳遞至回呼的錯誤通常是 gRPC 錯誤,您也可以從中擷取狀態碼形式的其他資訊。如需完整的狀態碼清單,請參閱「狀態碼及其在 gRPC 中的用法」。

Java

您可以擷取 gRPC 狀態碼,從 onTripUpdateError() 傳回的 TripUpdateError 中取得錯誤詳細資料。

// Called when there is a trip update error.
@Override
public void onTripUpdateError(TripInfo tripInfo, TripUpdateError error) {
  Status.Code code = error.getStatusCode();
}

Kotlin

您可以擷取 gRPC 狀態碼,從 onTripUpdateError() 傳回的 TripUpdateError 中取得錯誤詳細資料。

// Called when there is a trip update error.
override fun onTripUpdateError(tripInfo: TripInfo, error: TripUpdateError) {
  val code = error.getStatusCode()
}

解讀狀態碼

狀態碼涵蓋兩種錯誤:伺服器和網路相關錯誤,以及用戶端錯誤。

伺服器和網路錯誤

以下狀態碼代表網路或伺服器錯誤,您不需要採取任何行動即可解決。Consumer SDK 會自動復原這些錯誤。

狀態碼說明
ABORTED 伺服器停止傳送回應。這通常是伺服器問題所致。
已取消 伺服器終止了傳出回應。這通常會發生在
應用程式傳送至背景時,或是
消費者應用程式發生狀態變更時。
INTERRUPTED
DEADLINE_EXCEEDED 伺服器的回應時間過長。
無法使用 伺服器無法使用。這通常是因為網路問題。

用戶端錯誤

下列狀態碼是用於用戶端錯誤,您必須採取行動來解決這些錯誤。在您結束行程分享之前,Consumer SDK 會持續重試重新整理行程,但必須等到您採取行動,系統才會恢復。

狀態碼說明
INVALID_ARGUMENT 消費者應用程式指定的旅程名稱無效。旅程名稱必須採用 providers/{provider_id}/trips/{trip_id} 格式。
NOT_FOUND 系統從未建立行程。
PERMISSION_DENIED Consumer 應用程式的權限不足。發生以下狀況時會出現這個錯誤:
  • 消費者應用程式沒有權限
  • Google Cloud 控制台中的專案未啟用 Consumer SDK。
  • JWT 權杖遺失或無效。
  • JWT 權杖已使用不符於要求行程的行程 ID 簽署。
RESOURCE_EXHAUSTED 資源配額為零,或流量速率超出速度限制。
UNAUTHENTICATED 由於 JWT 權杖無效,因此要求驗證失敗。當 JWT 權杖未加上旅程 ID 就簽署,或是 JWT 權杖已過期時,就會發生這個錯誤。