Cómo seguir un viaje en Android

Selecciona la plataforma: Android iOS JavaScript

Cuando sigues un viaje, tu app para consumidores muestra al consumidor la ubicación del vehículo correspondiente. Para ello, tu app debe comenzar a seguir un viaje, actualizar su progreso y dejar de seguirlo cuando se complete.

En este documento, se explica cómo funciona ese proceso.

Antes de comenzar

Asegúrate de haber configurado lo siguiente:

  • Los servicios de backend de tu app para consumidores están implementados, y los servicios de coincidencia de consumidores con vehículos están operativos.

  • Configuraste un mapa para tu app.

Cómo comenzar a seguir un viaje

Cuando el servidor de backend coincida con un consumidor y un vehículo, usa JourneySharingSession para comenzar a seguir el viaje.

En el siguiente código de muestra, se muestra cómo comenzar a seguir un viaje después de que se carga la vista.

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()
  }
}

Actualizar el progreso del viaje

Para actualizar los detalles del progreso del viaje, como la distancia que el vehículo debe recorrer antes de la llegada y la hora estimada de llegada, tu app debe registrar y configurar un objeto de escucha como se muestra en los siguientes ejemplos.

  1. Registra un objeto de escucha en un objeto 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. Configura el objeto de escucha del viaje con 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)
    

Cómo dejar de seguir un viaje

Asegúrate de que tu app se detenga después de un viaje cuando ya no sea necesaria, por ejemplo, cuando el conductor marque el viaje como COMPLETO en el backend. Detener el uso compartido de viajes evita solicitudes de red innecesarias al motor de flotas y evita fugas de memoria.

Usa JourneySharingSession para dejar de seguir el viaje, como se indica en el siguiente código de muestra.

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()
  }
}

Cómo controlar los errores de viaje

El método onTripRefreshError muestra los errores que se producen durante la supervisión de viajes. Los mensajes de error siguen el estándar de Google Cloud Error. Para obtener definiciones detalladas de los mensajes de error y todos los códigos de error, consulta la documentación de errores de Google Cloud.

Estos son algunos errores comunes que pueden ocurrir durante la supervisión de viajes:

HTTP RPC Descripción
400 INVALID_ARGUMENT El cliente especificó un nombre de viaje no válido. El nombre del viaje debe seguir el formato providers/{provider_id}/trips/{trip_id}. provider_id debe ser el ID del proyecto de Cloud que pertenece al proveedor de servicios.
401 UNAUTHENTICATED Recibes este error si no hay credenciales de autenticación válidas. Por ejemplo, si el token JWT se firma sin un ID de viaje o el token JWT venció.
403 PERMISSION_DENIED Recibirás este error si el cliente no tiene permisos suficientes (por ejemplo, un usuario con el rol de consumidor intenta llamar a updateTrip) si el token JWT no es válido o si la API no está habilitada para el proyecto del cliente. Es posible que falte el token JWT o que el token esté firmado con un ID de viaje que no coincide con el ID de viaje solicitado.
429 RESOURCE_EXHAUSTED La cuota de recursos es de cero o la frecuencia de tráfico excede el límite.
503 NO DISPONIBLE Servicio no disponible. Por lo general, el servidor no está en funcionamiento.
504 DEADLINE_EXCEEDED Se excedió el plazo de la solicitud. Este error solo ocurre si el emisor establece una fecha límite más corta que la fecha límite predeterminada del método (es decir, la fecha límite solicitada no es suficiente para que el servidor procese la solicitud) y la solicitud no finalizó dentro de la fecha límite.

Cómo controlar errores del SDK de consumidor

El SDK para consumidores envía errores de actualización de viajes a la app para consumidores mediante un mecanismo de devolución de llamada. El parámetro de devolución de llamada es un tipo de datos que se muestra específico de la plataforma (TripUpdateError en Android y NSError en iOS).

Extrae códigos de estado

Por lo general, los errores que se pasan a la devolución de llamada son errores de gRPC, y también puedes extraer información adicional de ellos en forma de un código de estado. Para obtener la lista completa de códigos de estado, consulta Códigos de estado y su uso en gRPC.

Java

Puedes extraer un código de estado de gRPC que proporcione detalles sobre el error de la TripUpdateError que se muestra desde onTripUpdateError().

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

Kotlin

Puedes extraer un código de estado de gRPC que proporcione detalles sobre el error de la TripUpdateError que se muestra desde onTripUpdateError().

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

Cómo interpretar los códigos de estado

Los códigos de estado abarcan dos tipos de errores: errores relacionados con el servidor y la red, y errores del cliente.

Errores de servidor y red

Los siguientes códigos de estado son para errores de red o servidor, y no es necesario que realices ninguna acción para resolverlos. El SDK del consumidor se recupera automáticamente de ellos.

Código de estadoDescripción
ABORTED El servidor dejó de enviar la respuesta. Por lo general, esto se debe a un problema del servidor.
CANCELADO El servidor finalizó la respuesta saliente. Esto suele ocurrir cuando la app se envía a segundo plano o cuando hay un cambio de estado en la app de consumidor de
.
/, interrumpido
DEADLINE_EXCEEDED El servidor tardó demasiado en responder.
NO DISPONIBLE El servidor no estaba disponible. Por lo general, esto se debe a un problema de red.

Errores de cliente

Los siguientes códigos de estado son para errores del cliente y debes tomar medidas para resolverlos. El SDK del consumidor continúa reintentando actualizar el viaje hasta que dejes de compartirlo, pero no se recuperará hasta que tomes medidas al respecto.

Código de estadoDescripción
INVALID_ARGUMENT La app para consumidores especificó un nombre de viaje no válido, que debe seguir el formato providers/{provider_id}/trips/{trip_id}.
NOT_FOUND El viaje nunca se creó.
PERMISSION_DENIED La app para consumidores no tiene permisos suficientes. Este error ocurre en las siguientes situaciones:
  • La app para consumidores no tiene permisos
  • El SDK del consumidor no está habilitado para el proyecto en la consola de Google Cloud.
  • Falta el token JWT o no es válido.
  • El token JWT está firmado con un ID de viaje que no coincide con el viaje solicitado.
RESOURCE_EXHAUSTED La cuota de recursos está en cero o la frecuencia del flujo de tráfico excede el límite de velocidad.
UNAUTHENTICATED La solicitud no pudo autenticarse debido a que el token JWT no es válido. Este error ocurre cuando el token de JWT se firma sin un ID de viaje o cuando el token de JWT venció.