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

停止关注行程

请确保您的应用在不再需要跟踪行程时停止跟踪,例如当司机在后端将行程标记为“已完成”时。停止行程共享可避免向车队引擎发出不必要的网络请求,并防止内存泄露。

使用 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 超出请求时限。仅当调用方设置的时限比方法的默认时限短(即请求的时限不足以让服务器处理请求)并且请求未在时限范围内完成时,才会发生此错误。

处理使用方 SDK 错误

使用方 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()
}

解读状态代码

状态代码涵盖两种错误:服务器和网络相关错误,以及客户端错误。

服务器和网络错误

以下状态代码表示网络或服务器错误,您无需执行任何操作即可解决这些错误。使用方 SDK 会自动从中恢复。

状态代码说明
ABORTED 服务器停止发送响应。这通常是由服务器问题导致的。
已取消 服务器终止了外发响应。通常,当应用被发送到后台或

使用方应用发生状态变化时,就会发生这种情况。
INTERRUPTED
DEADLINE_EXCEEDED 服务器的响应时间过长。
UNAVAILABLE 服务器不可用。这通常是由网络问题导致的。

客户端错误

以下状态代码针对的是客户端错误,您必须采取措施来解决这些问题。消费者 SDK 会继续重新尝试刷新行程,直到您结束行程分享,但只有在您采取行动后才会恢复。

状态代码说明
INVALID_ARGUMENT 消费者应用指定的行程名称无效;行程名称必须遵循格式 providers/{provider_id}/trips/{trip_id}
NOT_FOUND 行程从未创建。
PERMISSION_DENIED 消费者应用权限不足。在以下情况下,会发生此错误:
  • 消费者应用没有权限
  • Google Cloud 控制台中的项目未启用使用方 SDK。
  • JWT 令牌缺失或无效。
  • JWT 令牌的签名行程 ID 与所请求的行程不匹配。
RESOURCE_EXHAUSTED 资源配额为零,或者流量速率超过速度限制。
UNAUTHENTICATED 由于 JWT 令牌无效,请求未通过身份验证。如果 JWT 令牌在签名时未提供行程 ID,或者 JWT 令牌已过期,就会发生此错误。