跟踪行程时,您的消费者应用会向消费者显示相应车辆的位置。为此,您的应用需要开始跟踪行程、更新行程进度,并在行程结束时停止跟踪行程。
本文档介绍了该流程的工作原理。
准备工作
请确保您已设置以下内容:
您已为用户应用构建好后端服务,并且用于将用户与车辆匹配的服务已投入使用。
您已为应用设置地图。
开始跟踪行程
当您的后端服务器将使用方与车辆匹配后,请使用 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()
}
}
更新行程进度
如需更新行程进度详情(例如车辆在到达前所需的行驶距离和预计到达时间),您的应用需要注册并配置监听器,如以下示例所示。
在
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?, ) { // ... } // ... })
使用
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 | 消费者应用权限不足。在以下情况下,会发生此错误:
|
RESOURCE_EXHAUSTED | 资源配额为零,或者流量速率超过速度限制。 |
UNAUTHENTICATED | 由于 JWT 令牌无效,请求未通过身份验证。如果 JWT 令牌在签名时未提供行程 ID,或者 JWT 令牌已过期,就会发生此错误。 |