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 UNAVAILABLE サービス利用不可。通常、サーバーがダウンしています。
504 DEADLINE_EXCEEDED リクエスト期限を超えました。このエラーは、呼び出し元が、メソッドのデフォルト期限よりも短い期限を設定し(つまり、要求された期限はサーバーがリクエストを処理するのに十分ではない)、リクエストがその期限内に完了しなかった場合にのみ発生します。

Consumer SDK のエラーを処理する

Consumer SDK は、コールバック メカニズムを使用して、乗車情報の更新エラーをユーザーアプリに送信します。コールバック パラメータは、プラットフォーム固有の戻り値の型(Android では TripUpdateError、iOS では NSError)です。

ステータス コードを抽出する

コールバックに渡されるエラーは通常 gRPC エラーです。ステータス コードの形式で追加情報を抽出することもできます。ステータス コードの完全なリストについては、ステータス コードと gRPC での使用方法をご覧ください。

Java

onTripUpdateError() から返された TripUpdateError から、エラーの詳細を提供する gRPC ステータス コードを抽出できます。

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

Kotlin

onTripUpdateError() から返された TripUpdateError から、エラーの詳細を提供する gRPC ステータス コードを抽出できます。

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

ステータス コードを解釈する

ステータス コードは、サーバーとネットワーク関連のエラー、クライアントサイド エラーの 2 種類のエラーを対象としています。

サーバーとネットワークのエラー

次のステータス コードはネットワーク エラーまたはサーバーエラーを示しており、解決するために対応する必要はありません。Consumer SDK は自動的に復元します。

ステータス コード説明
ABORTED サーバーがレスポンスの送信を停止しました。通常、これはサーバーの問題が原因です。
CANCELLED サーバーが送信レスポンスを終了しました。通常、この状態は、
アプリがバックグラウンドに移行したとき、または
ユーザーアプリの状態が変化したときに発生します。
INTERRUPTED
DEADLINE_EXCEEDED サーバーの応答に時間がかかりすぎました。
UNAVAILABLE サーバーが利用できませんでした。通常、これはネットワークの問題が原因で発生します。

クライアントエラー

次のステータス コードはクライアント エラーを示しており、解決するには対応が必要です。Consumer SDK は、乗車状況の共有を終了するまで乗車状況の更新を再試行し続けますが、ユーザーが操作するまで復元されません。

ステータス コード説明
INVALID_ARGUMENT ユーザーアプリで無効な乗車名を指定しました。乗車名は providers/{provider_id}/trips/{trip_id} 形式に従う必要があります。
NOT_FOUND ルートは作成されませんでした。
PERMISSION_DENIED ユーザーアプリに十分な権限がありません。このエラーは、次の場合に発生します。
  • ユーザーアプリに権限がない
  • Google Cloud コンソールのプロジェクトで Consumer SDK が有効になっていない。
  • JWT トークンがないか、無効です。
  • JWT トークンが、リクエストされた乗車と一致しない乗車 ID で署名されている。
RESOURCE_EXHAUSTED リソース割り当てがゼロであるか、トラフィック フローのレートが制限速度を超えています。
UNAUTHENTICATED JWT トークンが無効なため、リクエストの認証に失敗しました。このエラーは、JWT トークンが乗車 ID なしで署名された場合、または JWT トークンの有効期限が切れた場合に発生します。