Cómo comenzar a usar el SDK del controlador para Android

Requisitos mínimos del sistema

El dispositivo móvil debe ejecutar Android 6.0 (nivel de API 23) o una versión posterior.

Configuración de Maven

Las versiones 4.99 y posteriores del SDK de Driver están disponibles en el repositorio de Maven de Google.

Gradle

Agrega lo siguiente a tu archivo build.gradle:

repositories {
    ...
    google()
}

Maven

Agrega lo siguiente a tu archivo pom.xml:

<project>
  ...
  <repositories>
    <repository>
      <id>google-maven-repository</id>
      <url>https://maven.google.com</url>
    </repository>
  </repositories>
  ...
</project>

Configuración de proyectos

Para usar el SDK de Driver, tu app debe orientarse a minSdkVersion 23 o versiones posteriores. Para obtener más información, consulta las Notas de la versión.

Para ejecutar una app compilada con el SDK de Driver, el dispositivo Android debe tener instalados los Servicios de Google Play.

Configura tu proyecto de desarrollo

Si deseas configurar tu proyecto de desarrollo y obtener una clave de API para el proyecto en la consola de Google Cloud, sigue estos pasos:

  1. Crea un proyecto nuevo de Google Cloud Console o selecciona uno existente para usarlo con el SDK de Driver. Espera unos minutos hasta que el proyecto nuevo sea visible en la consola de Google Cloud.

  2. Para ejecutar la app de demostración, tu proyecto debe tener acceso al SDK de Maps para Android. En la consola de Google Cloud, selecciona APIs y servicios > Biblioteca y, luego, busca y habilita el SDK de Maps para Android.

  3. Para obtener una clave de API para el proyecto, selecciona APIs y servicios > Credenciales > Crear credenciales > Clave de API. Para conocer más detalles sobre cómo obtener una clave de API, consulta Cómo obtener una clave de API.

Agrega el SDK de Driver a tu app

El SDK de Driver está disponible en el repositorio de Maven de Google. El repositorio incluye los archivos del Modelo de objetos del proyecto (.pom) del SDK y Javadocs. Para agregar el SDK de Driver a tu app, haz lo siguiente:

  1. Agrega la siguiente dependencia a tu configuración de Gradle o Maven y reemplaza el marcador de posición VERSION_NUMBER por la versión seleccionada del SDK de Driver.

    Gradle

    Agrega lo siguiente a tu build.gradle:

    dependencies {
      ...
      implementation 'com.google.android.libraries.mapsplatform.transportation:transportation-driver:[VERSION_NUMBER]'
    }
    

    Maven

    Agrega lo siguiente a tu pom.xml:

    <dependencies>
      ...
      <dependency>
        <groupId>com.google.android.libraries.mapsplatform.transportation.driver</groupId>
        <artifactId>transportation-driver</artifactId>
        <version>[VERSION_NUMBER]</version>
      </dependency>
    </dependencies>
    

Agrega la clave de API a tu app

Una vez que hayas agregado el SDK de Driver a tu app, agrega la clave de API a esta. Deberás usar la clave de API del proyecto que obtuviste cuando configuraste tu proyecto de desarrollo.

En esta sección, se describe cómo almacenar tu clave de API para que tu app pueda hacer referencia a ella de manera más segura. No debes verificar la clave de API en tu sistema de control de versión. Debe almacenarse en el archivo local.properties, que se encuentra en el directorio raíz de tu proyecto. Para obtener más información sobre el archivo local.properties, consulta los archivos de propiedades de Gradle.

Para optimizar esta tarea, usa el complemento Secrets Gradle para Android. Sigue este procedimiento para instalar el complemento Secrets Gradle y almacenar tu clave de API de forma segura.

  1. Abre el archivo build.gradle en el nivel raíz y agrega el siguiente código al elemento dependencies en buildscript.

    Groovy

    buildscript {
        dependencies {
            // ...
            classpath "com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.0"
        }
    }
    

    Kotlin

    buildscript {
        dependencies {
            // ...
            classpath("com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.0")
        }
    }
    
  2. Abre el archivo build.gradle a nivel de la app y agrega el siguiente código al elemento plugins.

    Groovy

    id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin'
    

    Kotlin

    id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin")
    
  3. Sincroniza tu proyecto con Gradle.

  4. Abre local.properties en el directorio de nivel de proyecto y, luego, agrega el siguiente código. Asegúrate de reemplazar YOUR_API_KEY por tu clave de API.

    MAPS_API_KEY=YOUR_API_KEY
    
  5. En tu archivo AndroidManifest.xml, ve a com.google.android.geo.API_KEY y actualiza el atributo android:value de la siguiente manera:

    <meta-data
        android:name="com.google.android.geo.API_KEY"
        android:value="${MAPS_API_KEY}" />
    

En el siguiente ejemplo, se muestra un manifiesto completo para una app de ejemplo:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.driverapidemo" >
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/_AppTheme" >

        <meta-data
            android:name="com.google.android.geo.API_KEY"
            android:value="${MAPS_API_KEY}" />

        <activity android:name=".MainActivity" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

Incluye las atribuciones requeridas en tu aplicación

Si usas el SDK de Driver en tu app, debes incluir texto de atribución y licencias de código abierto como parte de la sección de avisos legales de tu app. Es mejor incluir las atribuciones como un elemento de menú independiente o como parte de un elemento de menú Acerca de.

La información de las licencias se puede encontrar en el archivo “third_party_licenses.txt” del archivo AAR desarchivado.

Para obtener información sobre cómo incluir avisos de código abierto, consulta https://developers.google.com/android/guides/opensource.

Dependencias

El SDK de Driver usa gRPC para comunicarse con el servidor de Fleet Engine. Si aún no usas gRPC, es posible que debas declarar las siguientes dependencias:

dependencies {
    implementation 'io.grpc:grpc-android:1.12.0'
    implementation 'io.grpc:grpc-okhttp:1.12.0'
}

Sin estas dependencias, es posible que el SDK de Driver experimente errores en el entorno de ejecución mientras intente comunicarse con el servidor de Fleet Engine.

Si usas ProGuard para optimizar las compilaciones, es posible que debas agregar las siguientes líneas al archivo de configuración de ProGuard:

-dontwarn com.google.**
-dontwarn io.grpc.**
-dontwarn okio.**

El nivel de API mínimo admitido es 23.

Inicializa el SDK

Se requiere un ID de proveedor (por lo general, el ID del proyecto de Google Cloud) para inicializar el objeto DriverContext. Para obtener más detalles sobre cómo configurar el proyecto de Google Cloud, consulta Autenticación y autorización.

Antes de usar el SDK de Driver, primero debes inicializar el SDK de Navigation. Cómo inicializar el SDK:

  1. Obtén un objeto Navigator de NavigationApi.

    NavigationApi.getNavigator(
        this, // Activity
        new NavigationApi.NavigatorListener() {
          @Override
          public void onNavigatorReady(Navigator navigator) {
            // Keep a reference to the Navigator (used to configure and start nav)
            this.navigator = navigator;
          }
        }
    );
    
  2. Crea un objeto DriverContext y propaga los campos obligatorios.

    DriverContext driverContext = DriverContext.builder(application)
        .setProviderId(providerId)
        .setVehicleId(vehicleId)
        .setAuthTokenFactory(authTokenFactory)
        .setNavigator(navigator)
        .setRoadSnappedLocationProvider(
            NavigationApi.getRoadSnappedLocationProvider(application))
        .build();
    
  3. Usa el objeto DriverContext para inicializar *DriverApi.

    DeliveryDriverApi driverApi = DeliveryDriverApi.createInstance(driverContext);
    
  4. Obtén el DeliveryVehicleReporter del objeto de la API. (DeliveryVehicleReporter extiende NavigationVehicleReporter).

    DeliveryVehicleReporter vehicleReporter = driverApi.getDeliveryVehicleReporter();
    

Autenticando con AuthTokenFactory

Cuando el SDK de Driver genera actualizaciones de ubicación, debe enviarlas al servidor de Fleet Engine. Para autenticar estas solicitudes, el SDK del controlador llama a una instancia de AuthTokenFactory proporcionada por el llamador. La fábrica es responsable de generar tokens de autenticación en el momento de la actualización de la ubicación.

La forma exacta en que se generan los tokens es específica de la situación de cada desarrollador. Sin embargo, es probable que la implementación deba hacer lo siguiente:

  • Recuperar un token de autenticación, posiblemente en formato JSON, de un servidor HTTPS
  • analizar y almacenar en caché el token
  • actualiza el token cuando venza

Para obtener detalles de los tokens que espera el servidor de Fleet Engine, consulta Crea un token web JSON (JWT) para la autorización.

A continuación, se muestra una implementación básica de AuthTokenFactory:

class JsonAuthTokenFactory implements AuthTokenFactory {
  private String vehicleServiceToken;  // initially null
  private long expiryTimeMs = 0;

  // This method is called on a thread whose only responsibility is to send
  // location updates. Blocking is OK, but just know that no location updates
  // can occur until this method returns.
  @Override
  public String getToken(AuthTokenContext authTokenContext) {
    if (System.currentTimeMillis() > expiryTimeMs) {
      // The token has expired, go get a new one.
      fetchNewToken(vehicleId);
    }
    if (ServiceType.VEHICLE.equals(authTokenContext.getServiceType)) {
      return vehicleServiceToken;
    } else {
      throw new RuntimeException("Unsupported ServiceType: " + authTokenContext.getServiceType());
    }
  }

  private void fetchNewToken(String vehicleId) {
    String url = "https://yourauthserver.example/token/" + vehicleId;

    try (Reader r = new InputStreamReader(new URL(url).openStream())) {
      com.google.gson.JsonObject obj
          = com.google.gson.JsonParser.parseReader(r).getAsJsonObject();
      vehicleServiceToken = obj.get("VehicleServiceToken").getAsString();
      expiryTimeMs = obj.get("TokenExpiryMs").getAsLong();

      // The expiry time could be an hour from now, but just to try and avoid
      // passing expired tokens, we subtract 10 minutes from that time.
      expiryTimeMs -= 10 * 60 * 1000;
    } catch (IOException e) {
      // It's OK to throw exceptions here. The StatusListener you passed to
      // create the DriverContext class will be notified and passed along the failed
      // update warning.
      throw new RuntimeException("Could not get auth token", e);
    }
  }
}

Esta implementación en particular utiliza el cliente HTTP de Java integrado para recuperar un token en formato JSON desde el servidor de autenticación del desarrollador. El token se guarda para su reutilización. El token se vuelve a recuperar si el anterior está dentro de los 10 minutos de su hora de vencimiento.

Tu implementación puede realizar acciones de manera diferente, como usar un subproceso en segundo plano para actualizar los tokens.

Las excepciones en AuthTokenFactory se tratan como transitorias, a menos que ocurran de forma repetida. Después de varios intentos, el SDK de Driver da por sentado que el error es permanente y deja de intentar enviar actualizaciones.

Status y Error Reporting con StatusListener

Dado que el SDK de Driver realiza acciones en segundo plano, usa StatusListener para activar notificaciones cuando se produzcan ciertos eventos, como errores, advertencias o mensajes de depuración. Los errores pueden ser de naturaleza transitoria (como BACKEND_CONNECTIVITY_ERROR) o pueden hacer que las actualizaciones de ubicación se detengan de forma permanente (por ejemplo, VEHICLE_NOT_FOUND, que indica un error de configuración).

Proporcionas una implementación opcional de StatusListener como la siguiente:

class MyStatusListener implements StatusListener {
  /** Called when background status is updated, during actions such as location reporting. */
  @Override
  public void updateStatus(
      StatusLevel statusLevel, StatusCode statusCode, String statusMsg) {
    // Status handling stuff goes here.
    // StatusLevel may be DEBUG, INFO, WARNING, or ERROR.
    // StatusCode may be DEFAULT, UNKNOWN_ERROR, VEHICLE_NOT_FOUND,
    // BACKEND_CONNECTIVITY_ERROR, or PERMISSION_DENIED.
  }
}

Notas sobre SSL/TLS

De forma interna, la implementación del SDK de Driver usa SSL/TLS para comunicarse de forma segura con el servidor de Fleet Engine. Es posible que las versiones anteriores de Android (niveles de API 23 o anteriores) requieran un parche SecurityProvider para comunicarse con el servidor. Para obtener más información sobre cómo trabajar con SSL en Android, consulta Proveedor de GMS de seguridad. El artículo también contiene muestras de código para aplicar parches al proveedor de seguridad.

Cómo habilitar las actualizaciones de ubicación

Una vez que tengas una instancia de *VehicleReporter, es sencillo habilitar las actualizaciones de la ubicación:

DeliveryVehicleReporter reporter = ...;

reporter.enableLocationTracking();

Si es posible, las actualizaciones de ubicación se envían en intervalos regulares. Cada actualización de ubicación también indica que el vehículo está en línea.

De forma predeterminada, el intervalo de informes es de 10 segundos. Puedes cambiar el intervalo de informes con reporter.setLocationReportingInterval(long, TimeUnit). El intervalo de actualización mínimo admitido es de 5 segundos. Las actualizaciones más frecuentes pueden generar solicitudes y errores más lentos.

Inhabilitar las actualizaciones de ubicación

Cuando termine el turno del conductor, podrás detener las actualizaciones de ubicación llamando a DeliveryVehicleReporter.disableLocationTracking.

Casos de uso de modelos confiables

En esta sección, se describe cómo usar el SDK de Driver para implementar casos de uso comunes cuando se usa el modelo de confianza.

Crea un vehículo

Puedes crear un vehículo desde el SDK de Driver.

Antes de crear un vehículo, asegúrate de inicializar la API de Delivery Driver. El ID de vehículo se debe crear con el ID de vehículo y proveedor que se usó durante la inicialización del SDK de Driver. Luego, crea el vehículo como se muestra en el siguiente ejemplo:

DeliveryDriverApi api = DeliveryDriverApi.getInstance();
DeliveryVehicleManager vehicleManager = api.getDeliveryVehicleManager();
try {
  DeliveryVehicle vehicle = vehicleManager.createVehicle().get();
  // Handle CreateVehicleRequest DeliveryVehicle response.
} catch (Exception e) {
  // Handle CreateVehicleRequest error.
}

Cómo crear una tarea de retiro de envío

Puedes crear una tarea de retiro de envío desde el SDK de Driver.

Antes de crear una tarea, asegúrate de inicializar la API de Delivery Driver. La tarea debe crearse con el ID de proveedor especificado durante la inicialización del SDK de Driver. Luego, crea la tarea de retiro de envío como se muestra en el siguiente ejemplo. Para obtener información sobre los IDs de tarea, consulta Ejemplos de IDs de tareas.

static final String TASK_ID = "task-8241890"; // Avoid auto-incrementing IDs.

DeliveryDriverApi api = DeliveryDriverApi.getInstance();
DeliveryTaskManager taskManager = api.getDeliveryTaskManager();
CreateDeliveryTaskRequest request = CreateDeliveryTaskRequest.builder(TASK_ID)
   .setPlannedWaypoint(Waypoint.builder().setLatLng(-6.195139, 106.820826).build())
   .setTaskDurationSeconds(2 * 60)
   .setParentId("my-tracking-id")
   .setTaskType(TaskType.DELIVERY_PICKUP)
   .build();

try {
   DeliveryTask task = taskManager.createTask(request).get();
   // Handle CreateTaskRequest DeliveryTask response.
} catch (Exception e)  {
   // Handle CreateTaskRequest error.
}

Cómo crear una tarea de entrega de envíos

Puedes crear una tarea de entrega de envíos desde el SDK de Driver.

Antes de crear una tarea, asegúrate de inicializar la API de Delivery Driver. Luego, crea la tarea de entrega de envíos como se muestra en el siguiente ejemplo. Para obtener información sobre los IDs de tarea, consulta Ejemplos de IDs de tareas.

static final String TASK_ID = "task-8241890"; // Avoid auto-incrementing IDs.

DeliveryDriverApi api = DeliveryDriverApi.getInstance();
DeliveryTaskManager taskManager = api.getDeliveryTaskManager();
CreateDeliveryTaskRequest request = CreateDeliveryTaskRequest.builder(TASK_ID)
   .setPlannedWaypoint(Waypoint.builder().setLatLng(-6.195139, 106.820826).build())
   .setTaskDurationSeconds(2 * 60)
   .setParentId("my-tracking-id")
   .setTaskType(TaskType.DELIVERY_DELIVERY)
   .build();
try {
   DeliveryTask task = taskManager.createTask(request).get();
   // Handle CreateTaskRequest DeliveryTask response.
} catch (Exception e)  {
   // Handle CreateTaskRequest error.
}

Falta de disponibilidad programada

Puedes crear una tarea que indique la no disponibilidad (por ejemplo, para descansos de conductores o recargas de combustible de vehículos) en el SDK de Driver. Una tarea de no disponibilidad programada no debe incluir un ID de seguimiento. De manera opcional, puedes proporcionar una ubicación.

Antes de crear una tarea, asegúrate de inicializar la API de Delivery Driver. Luego, crea la tarea de no disponibilidad como se muestra en el siguiente ejemplo. Para obtener información sobre los IDs de tarea, consulta Ejemplos de IDs de tareas.

static final String TASK_ID = "task-8241890"; // Avoid auto-incrementing IDs.

DeliveryDriverApi api = DeliveryDriverApi.getInstance();
DeliveryTaskManager taskManager = api.getDeliveryTaskManager();
CreateDeliveryTaskRequest request = CreateDeliveryTaskRequest.builder(TASK_ID)
   .setTaskDurationSeconds(2 * 60) // Duration or location (or both) must be provided for a BREAK task.
   .setTaskType(TaskType.UNAVAILABLE)
   .build();
try {
   DeliveryTask task = taskManager.createTask(request).get();
   // Handle CreateTaskRequest DeliveryTask response.
} catch (Exception e)  {
   // Handle CreateTaskRequest error.
}

Paradas programadas

Puedes crear una tarea de detención programada desde el SDK de Driver. Es posible que una tarea de detención programada no incluya un ID de seguimiento.

Antes de crear una tarea, asegúrate de inicializar la API de Delivery Driver. Luego, crea la tarea de detención programada como se muestra en el siguiente ejemplo. Para obtener información sobre los IDs de tarea, consulta Ejemplos de IDs de tareas.

    static final String TASK_ID = "task-8241890"; //  Avoid auto-incrementing IDs.

    DeliveryDriverApi api = DeliveryDriverApi.getInstance();
    DeliveryTaskManager taskManager = api.getDeliveryTaskManager();
    CreateDeliveryTaskRequest request = CreateDeliveryTaskRequest.builder(TASK_ID)
       .setPlannedWaypoint(Waypoint.builder().setLatLng(-6.195139, 106.820826).build())
       .setTaskDurationSeconds(2 * 60)
       .setTaskType(TaskType.DELIVERY_SCHEDULED_STOP)
       .build();
    try {
       DeliveryTask task = taskManager.createTask(request).get();
       // Handle CreateTaskRequest DeliveryTask response.
    } catch (Exception e)  {
       // Handle CreateTaskRequest error.
    }

Actualizar el orden de las tareas

Puedes actualizar el orden de ejecución de las tareas asignadas a un vehículo desde el SDK de Driver.

La actualización del orden de las tareas también asigna tareas a un vehículo si no estaban asignadas previamente a un vehículo. También cierra las tareas que se asignaron anteriormente a un vehículo y que no se incluyeron en el pedido actualizado. Si asignas una tarea a un vehículo diferente si ya se había asignado a otro vehículo, se genera un error. Antes de asignar una tarea al vehículo nuevo, cierra la tarea existente y crea una nueva.

Puedes actualizar el orden de las tareas en cualquier momento.

Antes de actualizar el orden de tareas de un vehículo, asegúrate de que el vehículo y las tareas ya se hayan creado en Fleet Engine. Luego, actualiza el orden de la tarea para el vehículo como se muestra en el siguiente ejemplo.

    DeliveryDriverApi api = DeliveryDriverApi.getInstance();
    DeliveryVehicleReporter reporter = api.getDeliveryVehicleReporter();
    try {
       List<VehicleStop> stops = reporter.setVehicleStops(
         ImmutableList.of(
             VehicleStop.builder()
                 .setVehicleStopState(VehicleStopState.ARRIVED)
                 .setWaypoint(Waypoint.builder().setLatLng(37.1749, 122.412).build())
                 .setTasks(ImmutableList.of(task1)) // Previously created DeliveryTask in Fleet Engine.
                 .build(),
             VehicleStop.builder()
                 .setVehicleStopState(VehicleStopState.NEW) // The current vehicle stop.
                 .setWaypoint(Waypoint.builder().setLatLng(37.7749, 122.4194).build())
                 .setTasks(ImmutableList.of(task2)) // Previously created DeliveryTask in Fleet Engine.
                 .build(),
             VehicleStop.builder()
                 .setVehicleStopState(VehicleStopState.NEW)
                 .setWaypoint(Waypoint.builder().setLatLng(37.3382, 121.8863).build())
                 .setTasks(ImmutableList.of(task3, task4)) // Previously created DeliveryTasks in Fleet Engine.
                 .build())).get();
       // Successfully updated vehicle stops in Fleet Engine. Returns the successfully set VehicleStops.
    } catch (Exception e)  {
       // Failed to update vehicle stops in Fleet Engine. Setting VehicleStops must be attempted again after resolving
       // errors.
    }

Es posible que se produzca una excepción que podría impedir una actualización del estado interno del SDK de Driver. Si esto sucede, resuelve el problema y, luego, vuelve a llamar a setVehicleStops hasta que la llamada se realice de forma correcta.

Estos son algunos de los problemas potenciales:

  • Las paradas de vehículos especificadas no siguen un patrón válido. Solo la primera VehicleStop puede estar en cualquiera de los VehicleStopStates: NEW, ENROUTE o ARRIVED. Las paradas de vehículos después de la parada actual deben tener el estado NUEVO VehicleStopState.

  • Las tareas no existen o pertenecen a otro vehículo.

  • El vehículo no existe.

El vehículo está en camino a la siguiente parada

Se debe notificar a Fleet Engine cuando un vehículo sale de una parada y cuando comienza la navegación. Puedes notificar a Fleet Engine desde el SDK de Driver.

Antes de notificar a Fleet Engine que un vehículo salió de una parada, asegúrate de que se hayan creado y configurado las paradas del vehículo. Luego, notifica a Fleet Engine la salida del vehículo, como se muestra en el siguiente ejemplo.

    DeliveryDriverApi api = DeliveryDriverApi.getInstance();
    DeliveryVehicleReporter reporter = api.getDeliveryVehicleReporter();
    reporter.enableLocationTracking(); // Location tracking must be enabled.

    // Create Vehicle, VehicleStops, and DeliveryTasks.
    // Set VehicleStops on Vehicle.

    navigator.setDestination(vehicleStop.getWaypoint());
    try {
       List<VehicleStop> updatedStops = reporter.enrouteToNextStop().get();
       // Successfully updated vehicle stops in Fleet Engine. Returns the set VehicleStops, with the first
       // VehicleStop updated to ENROUTE state.
    } catch (Exception e)  {
       // Failed to update vehicle stops in Fleet Engine. Updating VehicleStops must be attempted again
       // after resolving errors.
    }

Es posible que se produzca una excepción que podría impedir una actualización del estado interno del SDK de Driver. Si esto sucede, resuelve el problema y, luego, vuelve a llamar a enrouteToNextStop hasta que funcione.

Estos son algunos de los problemas potenciales:

  • No hay VehicleStops restantes configurados en el SDK de Driver.

El vehículo llega a una parada

Se debe notificar a Fleet Engine cuando un vehículo llega a una parada. Puedes notificar a Fleet Engine desde el SDK de Driver.

Antes de notificar a Fleet Engine que un vehículo llegó a una parada, asegúrate de que se hayan detenido. Luego, notifica a Fleet Engine la llegada del vehículo a la parada, como se muestra en el siguiente ejemplo.

DeliveryDriverApi api = DeliveryDriverApi.getInstance();
DeliveryVehicleReporter reporter = api.getDeliveryVehicleReporter();
reporter.enableLocationTracking(); // Location tracking must be enabled.

// Create Vehicle, VehicleStops, and DeliveryTasks.
// Set VehicleStops on Vehicle.
// Mark ENROUTE to VehicleStop and start guidance using Navigator.

try {
   List<VehicleStop> updatedStopsArrived = reporter.arrivedAtStop().get();
   // Successfully updated vehicle stops in Fleet Engine. Returns the set VehicleStops, with the first
   // VehicleStop updated to ARRIVED state.
   navigator.clearDestinations();
} catch (Exception e)  {
   // Failed to update vehicle stops in Fleet Engine. Updating VehicleStops must be attempted again
   // after resolving errors.
}

Es posible que se produzca una excepción que podría impedir una actualización del estado interno del SDK de Driver. Si esto sucede, resuelve el problema y, luego, vuelve a llamar a arrivedAtStop hasta que funcione.

Estos son algunos de los problemas potenciales:

  • No hay VehicleStops restantes configurados en el SDK de Driver.

El vehículo completa una parada

Debes notificar a Fleet Engine cuando un vehículo complete una parada. Esta notificación hace que todas las tareas asociadas con la parada se establezcan en el estado CLOSED. Puedes notificar a Fleet Engine desde el SDK de Driver.

Notifica a Fleet Engine que el vehículo completó su VehicleStop, como se muestra en el siguiente ejemplo.

    DeliveryDriverApi api = DeliveryDriverApi.getInstance();
    DeliveryVehicleReporter reporter = api.getDeliveryVehicleReporter();
    reporter.enableLocationTracking(); // Location tracking must be enabled.

    // After completing the tasks at the VehicleStop, remove it from the
    // the current list of VehicleStops.

    try {
       List<VehicleStop> updatedStopsCompleted = reporter.completedStop().get();
       // Successfully updated vehicle stops in Fleet Engine. All tasks on the completed stop are set to CLOSED.
       // Returns the set VehicleStops, with the completed VehicleStop removed from the remaining list.
    } catch (Exception e)  {
       // Failed to update vehicle stops in Fleet Engine. Updating VehicleStops must be attempted again
       // after resolving errors.
    }

Es posible que se produzca una excepción que podría impedir una actualización del estado interno del SDK de Driver. Si esto sucede, resuelve el problema y, luego, vuelve a llamar a completedStop hasta que funcione.

Estos son algunos de los problemas potenciales:

  • No hay VehicleStops restantes configurados en el SDK de Driver.

Cómo cerrar una tarea

Para cerrar una tarea asignada a un vehículo, notifica a Fleet Engine que el vehículo completó la parada en la que se realiza la tarea o quítalo de la lista de paradas de vehículos. Para ello, puedes configurar la lista de las paradas restantes del vehículo como cuando actualizas el orden de la tarea para un vehículo.

Si a una tarea aún no se le asignó un vehículo y debe cerrarse, actualízala a un estado CERRADO. Sin embargo, no puedes volver a abrir una tarea CERRADA.

Cerrar una tarea no indica éxito o fracaso. Indica que la tarea ya no se considera en curso. Para el seguimiento del envío, es importante indicar el resultado real de una tarea para que se pueda mostrar el resultado de la entrega.

Se debe asignar una tarea a un vehículo para poder usar el SDK de Driver para cerrarla. Para cerrar una tarea asignada a un vehículo, notifica a Fleet Engine que el vehículo completó la parada donde se realiza la tarea.

Como alternativa, actualiza el orden de la tarea del vehículo al que está asignada la tarea y, luego, quítala de la lista de paradas.

Establecer el resultado de la tarea y la ubicación del resultado

Cerrar una tarea no indica éxito o fracaso. Indica que la tarea ya no se considera en curso. En el seguimiento del envío, es importante indicar el resultado real de una tarea para que se pueda mostrar el resultado de la entrega y la facturación adecuada de los servicios. Una vez establecida, no puedes cambiar el resultado de la tarea. Sin embargo, puedes modificar el tiempo del resultado de la tarea y la ubicación del resultado de la tarea una vez que las hayas configurado.

El resultado de las tareas que están en estado CLOSED puede ser SUCCEEDED o FAILED. Fleet Engine solo cobra las tareas de entrega con el estado SUCCEEDED.

Cuando marcas el resultado de una tarea, Fleet Engine completa automáticamente la ubicación del resultado de la tarea con la ubicación conocida del vehículo más reciente. Puedes anular este comportamiento.

En el siguiente ejemplo, se muestra cómo usar el SDK de Driver para establecer un resultado de tarea y una marca de tiempo. No puedes establecer la ubicación de resultados de las tareas con el SDK de Driver.

    static final String TASK_ID = "task-8241890";

    DeliveryDriverApi api = DeliveryDriverApi.getInstance();
    DeliveryTaskManager taskManager = api.getDeliveryTaskManager();

    // Updating an existing DeliveryTask which is already CLOSED. Manually
    // setting TaskOutcomeLocation with Driver SDK is not supported at this time.
    UpdateDeliveryTaskRequest req = UpdateDeliveryTaskRequest.builder(TASK_ID)
        .setTaskOutcome(TaskOutcome.SUCCEEDED)
        .setTaskOutcomeTimestamp(now()) // Timestamp in milliseconds.
        .build();

    try {
       DeliveryTask updatedTask = taskManager.updateTask(req);
       // Handle UpdateTaskRequest DeliveryTask response.
    } catch (Exception e)  {
       // Handle UpdateTaskRequest error.
    }

Buscar un vehículo

Puedes buscar un vehículo desde el SDK de Driver. Antes de buscar un vehículo, asegúrate de inicializar la API de Delivery Driver. Luego, puedes buscar el vehículo como se muestra en el siguiente ejemplo.

    DeliveryDriverApi api = DeliveryDriverApi.getInstance();
    DeliveryVehicleManager vehicleManager = api.getDeliveryVehicleManager();
    try {
       DeliveryVehicle vehicle = vehicleManager.getVehicle().get();
       // Handle GetVehicleRequest DeliveryVehicle response.
    } catch (Exception e)  {
       // Handle GetVehicleRequest error.
    }

DeliveryVehicleManager solo puede buscar el DeliveryVehicle para el ID del vehículo que se proporcionó durante la inicialización de la API de Delivery Driver.