Last Mile Fleet Solution is currently available only to select customers. Contact sales to learn more.

Getting started with the Driver SDK for Android

Stay organized with collections Save and categorize content based on your preferences.

Minimum system requirements

The mobile device must be running Android 5.0 (API level 21) or later.

Prerequisites

This guide assumes your app already implements the Navigation SDK and that the Fleet Engine backend is set up and available.

The Driver SDK for Android is published to an Artifact Registry Maven repository. The repository includes the SDK's Project Object Model (.pom) files and offline Javadocs.

Get access

If you are a Google Workspace customer, create a Workspace Group such as google-maps-platform-sdk-users@workspacedomain.com during onboarding and provide the name to Google. This is the recommended approach. Your Workspace Group will then be added to an allowlist that grants access to the Maven repository gmp-artifacts/transportation. Confirm that the user emails and service account emails that need access are included in this list.

If your organization cannot create Workspace Groups, send to Google a list of user and service account emails that need access to these artifacts.

Local development

For local development, it is sufficient to log in with the Cloud SDK.

gcloud

gcloud auth login

The email used to log in must be a member of the Workspace Group.

Automation (build systems or continuous integration)

Set up your automation hosts according to best practices:

  • If your process runs inside a Google Cloud environment, use automatic credential detection.

  • Otherwise, store the service account key file in a secure location on the host's file-system and set the GOOGLE_APPLICATION_CREDENTIALS environment variable appropriately.

The service account email associated with the credentials must be a member of the Workspace Goup.

Configuration

Configure Maven or Gradle to detect user or service credentials automatically.

Gradle

Add the following to your app module's build.gradle file, not the project root module build.gradle file:

  plugins {
    id "com.google.cloud.artifactregistry.gradle-plugin" version "2.1.5"
  }
  repositories {
    maven {
      url "artifactregistry://us-west2-maven.pkg.dev/gmp-artifacts/transportation"
    }
  }

Maven

Add the following to your pom.xml:

  <repositories>
    <repository>
      <id>gmp-artifacts</id>
      <url>artifactregistry://us-west2-maven.pkg.dev/gmp-artifacts/transportation</url>
      <releases>
        <enabled>true</enabled>
      </releases>
    </repository>
  </repositories>
  <build>
    <extensions>
      <extension>
        <groupId>com.google.cloud.artifactregistry</groupId>
        <artifactId>artifactregistry-maven-wagon</artifactId>
        <version>2.1.0</version>
      </extension>
    </extensions>
  </build>

For information on verifying access, see Managing Java packages.

Project configuration

To use the Driver SDK, your app must target minSdkVersion 21 or higher. For more information, see Release Notes.

To run an app built with the Driver SDK, the Android device must have Google Play services installed.

Set up your development project

To set up your development project and get an API key for the project on the Google Cloud Console:

  1. Create a new Google Cloud Console project, or select an existing project, for use with the Driver SDK. Wait a few minutes until the new project is visible on the Google Cloud Console.

  2. In order to run the demo app, your project must have access to the Maps SDK for Android. In the Google Cloud Console, select APIs & Services > Library, then search for and enable the Maps SDK for Android.

  3. Get an API key for the project by selecting APIs & Services > Credentials > Create credentials > API key. For more information about getting an API key, see Get an API key.

Add the Driver SDK to your app

The Driver SDK is available via a private Maven repository. The repository includes the SDK's Project Object Model (.pom) files and Javadocs. To add the Driver SDK to your app:

  1. Set up your environment to access the host Maven repository as described in the Configuration section.

  2. Add the following dependency to your Gradle or Maven configuration, substituting the VERSION_NUMBER placeholder for the desired version of the Driver SDK.

    Gradle

    Add the following to your build.gradle:

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

    Maven

    Add the following to your pom.xml:

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

Update your app's manifest

Once you have added the Driver SDK to your app, you can update your app's manifest by editing its AndroidManifest.xml file.

Add your API key within the <application> element. You must use the project API key you obtained when you set up your development project.

For example, replace PASTE_YOUR_API_KEY_HERE with your API key in the following application meta-data:

<meta-data
    android:name="com.google.android.geo.API_KEY"
    android:value="PASTE_YOUR_API_KEY_HERE"/>

The following example shows a complete manifest for a sample app:

<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="PASTE_YOUR_API_KEY_HERE"/>

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

Include the required attributions in your app

If you use the Driver SDK in your app, you must include attribution text and open source licenses as part of your app's legal notices section. It's best to include the attributions as an independent menu item or as part of an About menu item.

You can find the required attribution text and open source licenses in the Driver SDK zip file:

  • NOTICE.txt
  • LICENSES.txt

Dependencies

The Driver SDK uses gRPC to communicate to the Fleet Engine server. If you don't already bring in gRPC, you may need to declare the following dependencies:

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

Without these dependencies, the Driver SDK will experience errors at runtime while trying to communicate with the Fleet Engine server.

If you use ProGuard to optimize your builds, you may need to add the following lines to your ProGuard configuration file:

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

The minimum API level supported is 21.

Initializing the SDK

A provider ID (usually the Google Cloud Project ID) is required in order to initialize the FleetEngine object. For more detail about setting up the Google Cloud Project, see Authentication and Authorization.

Before using the Driver SDK, you must first initialize the Navigation SDK. To initialize the SDK:

  1. Obtain a Navigator object from the 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. Create a DriverContext object, populating the required fields.

    DriverContext driverContext = DriverContext.builder(application)
                 .setProviderId(providerId)
                 .setVehicleId(vehicleId)
                 .setAuthTokenFactory(authTokenFactory)
                 .setNavigator(navigator)
                 .setRoadSnappedLocationProvider(
                     NavigationApi.getRoadSnappedLocationProvider(application))
                 .build()
    
  3. Use the DriverContext object to initialize the *DriverApi.

    DeliveryDriverApi driverApi = DeliveryDriverApi.createInstance(driverContext);
    
  4. Obtain the DeliveryVehicleReporter from the API object. (DeliveryVehicleReporter extends NavigationVehicleReporter.)

    DeliveryVehicleReporter vehicleReporter = driverApi.getDeliveryVehicleReporter();
    

Authenticating with AuthTokenFactory

When the Driver SDK generates location updates, it must send these updates to the Google Fleet Engine server. In order to authenticate these requests, the Driver SDK will call out to a caller-provided instance of AuthTokenFactory. The factory is responsible for generating authentication tokens at location update time.

How exactly tokens are generated will be specific to each developer's situation. However, the implementation will probably need to:

  • fetch an authentication token, possibly in JSON format, from an HTTPS server
  • parse and cache the token
  • refresh the token when it expires

For details of the tokens expected by the Fleet Engine server, see Creating a JSON Web Token (JWT) for authorization.

Here is a skeleton implementation of an AuthTokenFactory:

class JsonAuthTokenFactory implements AuthTokenFactory {
  String vehicleServiceToken;  // initially null
  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 URL(url).openStream()) {
      com.google.gson.JsonObject obj
          = new com.google.gson.JsonParser().parse(r);
      vehicleServiceToken = obj.get("VehicleServiceToken").getAsString();
      expiryTimeMs = obj.getAsLong("TokenExpiryMs");

      // 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 FleetEngine class will be notified and pass along the failed
      // update warning.
      throw new RuntimeException("Could not get auth token", e);
    }
  }
}

This particular implementation uses the built-in Java HTTP client to fetch a token in JSON format from the developer's authentication server. The token is saved for reuse. The token is re-fetched if the old token is within 10 minutes of its expiry time.

Your implementation may do things differently, such as using a background thread to refresh tokens.

Exceptions in AuthTokenFactory will be treated as transient unless they happen repeatedly. After a number of attempts, the Driver SDK will assume that the error is permanent and will stop trying to send updates.

Status and Error Reporting with StatusListener

Since the Driver SDK performs actions in the background, use the StatusListener to trigger notifications when certain events occur, such as errors, warnings, or debug messages. Errors may be transient in nature (such as BACKEND_CONNECTIVITY_ERROR), or they may cause location updates to be stopped permanently (such as VEHICLE_NOT_FOUND, indicating a configuration error).

You provide an optional StatusListener implementation like the following:

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.
  }
}

Notes on SSL/TLS

Internally, the Driver SDK implementation uses SSL/TLS to communicate securely with the Fleet Engine server. Older versions of Android (API versions 21 or lower) may require a SecurityProvider patch to be able to communicate with the server. You should see this article for more information about working with SSL in Android. The article also contains code samples for patching the security provider.

Enabling location updates

Once you have a *VehicleReporter instance, enabling location updates is straightforward:

DeliveryVehicleReporter reporter = ...;

reporter.enableLocationTracking();

Location updates will be sent at a regular interval, if possible. Each location update will also indicate that the vehicle is online.

By default, the reporting interval is 10 seconds, but the reporting interval can be changed with FleetEngine.setLocationReportingInterval(long, TimeUnit). The minimum supported update interval is 5 seconds. More frequent updates may result in slower requests and errors.

Disabling location updates

When the driver's shift is finished, location updates can be stopped by calling DeliveryVehicleReporter.disableLocationTracking.

Trusted model use cases

This section describes how to use the Driver SDK to implement common use cases when using the trusted model.

Create a vehicle

You can create a vehicle from the Driver SDK.

Before creating a vehicle, make sure to initialize the Delivery Driver API. The vehicle ID must be created with the vehicle and provider IDs used during Driver SDK initialization. Then create the vehicle as shown in the following example:

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

Create a shipment pickup task

You can create a shipment pickup task from the Driver SDK.

Before creating a task, make sure to initialize the Delivery Driver API. The task must be created using the provider ID specified during Driver SDK initialization. Then create the shipment pickup task as shown in the following example. For information about task IDs, see Task ID examples.

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.
}

Create a shipment delivery task

You can create a shipment delivery task from the Driver SDK.

Before creating a task, make sure to initialize the Delivery Driver API. Then create the shipment delivery task as shown in the following example. For information about task IDs, see Task ID examples.

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.
}

Scheduled unavailability

You can create a task indicating unavailability (for example, for driver breaks or vehicle refueling) from the Driver SDK. A scheduled unavailability task must not include a tracking ID. You may optionally provide a location.

Before creating a task, make sure to initialize the Delivery Driver API. Then create the unavailability task as shown in the following example. For information about task IDs, see Task ID examples.

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.
}

Scheduled stops

You can create a scheduled stop task from the Driver SDK. A scheduled stop task cannot include a tracking ID.

Before creating a task, make sure to initialize the Delivery Driver API. Then create the scheduled stop task as shown in the following example. For information about task IDs, see Task ID examples.

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.
}

Update task ordering

You can update the order of execution of tasks assigned to a vehicle from the Driver SDK.

Updating the task ordering also assigns tasks to a vehicle if they weren't previously assigned to a vehicle. It also closes tasks that were previously assigned to a vehicle and were left out of the updated ordering. Assigning a task to a different vehicle if it had previously been assigned to another vehicle generates an error. Before assigning a task to the new vehicle, close the existing task and then create a new task.

You can update task ordering at any time.

Before updating the task ordering for a vehicle, make sure that the vehicle and tasks have already been created in Fleet Engine. Then update the task ordering for the vehicle as shown in the following example.

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.
}

An exception might occur that could prevent an update to the Driver SDK's internal state. If this happens, resolve the issue and then call setVehicleStops again until the call is successful.

Potential issues can include:

  • The specified VehicleStops don't follow a valid pattern. Only the first VehicleStop can be in any of the VehicleStopStates: NEW, ENROUTE, or ARRIVED. VehicleStops after the current stop must be in the NEW VehicleStopState.

  • Tasks either don't exist, or they belong to a different vehicle.

  • The vehicle doesn't exist.

Vehicle is enroute to the next stop

Fleet Engine must be notified when a vehicle departs from a stop, and when it begins navigation. You can notify Fleet Engine from the Driver SDK.

Before notifying Fleet Engine that a vehicle departed from a stop, ensure that the vehicle stops have been created and set. Then notify Fleet Engine of the vehicle's departure as shown in the following example.

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.
}

An exception might occur that could prevent an update to the Driver SDK's internal state. If this happens, resolve the issue and then call enrouteToNextStop again until it is successful.

Potential issues can include:

  • No remaining VehicleStops set in the Driver SDK.

Vehicle arrives at a stop

Fleet Engine must be notified when a vehicle arrives at a stop. You can notify Fleet Engine from the Driver SDK.

Before notifying Fleet Engine that a vehicle arrived at a stop, ensure that the vehicle stops have been set. Then notify Fleet Engine of the vehicle's arrival at the stop as shown in the following example.

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.
}

An exception can occur that could prevent an update to the Driver SDK's internal state. If this happens, resolve the issue and then call arrivedAtStop again until it is successful.

Potential issues might include:

  • No remaining VehicleStops set in the Driver SDK.

Vehicle completes a stop

Fleet Engine must be notified when a vehicle completes a stop. This causes all tasks associated with the stop to be set to a CLOSED state. You can notify Fleet Engine from the Driver SDK.

Notify Fleet Engine that the vehicle has completed its VehicleStop as shown in the following example.

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.
}

An exception can occur that could prevent an update to the Driver SDK's internal state. If this happens, resolve the issue and then call completedStop again until it is successful.

Potential issues can include:

  • No remaining VehicleStops set in the Driver SDK.

Close a task

To close a task that has been assigned to a vehicle, either notify Fleet Engine that the vehicle has completed the stop where the task takes place, or remove it from the list of vehicle stops. To do so, you can set the list of the remaining vehicle stops just as when updating the task ordering for a vehicle.

If a task was not yet assigned a vehicle, and it needs to be closed, update the task to a CLOSED state. However, you can not reopen a CLOSED task.

Closing a task does not indicate success or failure. It indicates that the task is no longer considered in progress. For shipment tracking, it is important to indicate the actual outcome of a task so a delivery outcome can be shown.

A task must be assigned to a vehicle in order to be able to use the Driver SDK to close the task. To close a task that has been assigned to a vehicle, notify Fleet Engine that the vehicle has completed the stop where the task takes place.

Alternatively, update the task ordering of the vehicle that the task is assigned to, and then remove the desired task from the list of stops.

Setting the task outcome and outcome location

Closing a task doesn't indicate success or failure. It indicates that the task is no longer considered in progress. For shipment tracking, it's important to indicate the actual outcome of a task so a delivery outcome can be shown, and so that there's proper billing for the services. Once set, you cannot change the task outcome. But you can modify task outcome time and task outcome location after you have set them.

Tasks that are in the CLOSED state can have their outcome set to either SUCCEEDED or FAILED. Only pickup and delivery tasks that have a state of SUCCEEDED are billed.

When marking the outcome of a task, Fleet Engine automatically fills-in the task outcome location with the last known vehicle location. You can override this behavior by calling Fleet Engine. Note that you cannot set task outcome location using the Driver SDK.

The following code example demonstrates how to use the Driver SDK to set a task outcome and timestamp.

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.
}

Look up a vehicle

You can look up a vehicle from the Driver SDK. Before looking up a vehicle, ensure that you initialize the Delivery Driver API. You can then lookup the vehicle as shown in the following example.

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

The DeliveryVehicleManager can only look up the DeliveryVehicle for the vehicle ID that was provided during Delivery Driver API initialization.