Android Driver SDK 5.0 Migration Guide

This guide describes the changes necessary to migrate to version 5.0.

Gradle and Android Gradle Plugin updates

Upgrade Gradle and Android Gradle Plugin versions

First, upgrade your Gradle and Android Gradle Plugin versions. This upgrade includes better compatibility with certain SDK dependencies (including Kotlin 1.9), as well as some critical bug fixes.

This SDK major release requires the following version dependencies for your Android application project:

  • a Gradle version at least v7.5.0 but no higher than v7.6.0.
  • an Android Gradle Plugin (AGP) version in the range of v7.4.x.

You can target a higher version of the plugins; however, you might run into deprecation warnings, or some new features might not work.

To modify the Gradle version, modify the line in your project's /gradle/wrapper/gradle-wrapper.properties file

distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip

To modify the Android Gradle Plugin version, modify the build.gradle file that contains the buildscript block. For example:

buildscript {
    repositories {
        google()
        mavenCentral()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:7.4.1'
    }
}

Java 7 to Java 8 library support migration

Step 1 - Enable Java 8 library support

Source

Since the SDK min API level is 23 and the required AGP version is 7.4+, the configuration is slightly different from the mentioned source documentation.

buildscript {

    repositories {
        google()
        mavenCentral()
        jcenter()
        maven {
            url = uri("https://storage.googleapis.com/r8-releases/raw")
        }
    }
    dependencies {
        classpath 'com.android.tools:r8:8.0.46'
        classpath 'com.android.tools.build:gradle:7.4.1'
    }
}

android {
    compileOptions {
        // Flag to enable support for the new language APIs
        coreLibraryDesugaringEnabled true
        // Sets Java compatibility to Java 8
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs_nio:2.0.3'
}

Step 2 - Migrate from Proguard or Dexguard to R8

R8, source

AGP v7.4+ uses R8 as the default shrinking, obfuscation, and optimization tool for the binary, so no special action is needed at this point.

If the project is migrated from AGP 4.0+, AGP may issue a the following warnings about file removals:

  • useProguard true usage in build.gradle file
  • android.enableR8=false usage in gradle.properties file

Removing these lines usually resolves those issues.

Kotlin 1.6 to 1.9 migration

Step 1 - Migrate to Kotlin Gradle Plugin 1.9.0

Source

Update the Kotlin Gradle Plugin version in your application top level module build.gradle file. Make sure to add org.jetbrains.kotlin:kotlin-gradle-plugin in the dependencies from the buildscript block in case it's missing.

buildscript {
  dependencies {
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.0"
  }
}

You must migrate your application from Kotlin-synthetics in case you're coming from Kotlin Gradle Plugin 1.6.X or 1.7.X. Refer to the official migration guide for more information.

Step 2 - Upgrade kotlin-stdlib to 1.9.0

Source

Upgrade kotlin-stblib to 1.9.0 in your application build.gradle file.

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib:1.9.0"
}

Make sure to remove any references to kotlin-stdlib-jdk7 or kotlin-stdlib-jdk8. Both dependencies have been consolidated into kotlin-stdlib starting in Kotlin 1.8.0.

StatusListener deprecation

The StatusListener interface is now deprecated (to be removed in v6), in favor of DriverStatusListener.

There are mainly 3 changes:

  1. Change the implements interface from StatusListener to DriverStatusListener.
  2. Add a Nullable cause parameter to updateStatus.
  3. Call the DriverContextBuilder.setDriverStatusListener instead of the setStatusListener.

DriverStatusListener shares the same structure as StatusListener. The main difference between them is that DriverStatusListener.updateStatus() takes an extra parameter named cause. This provides users insights on the cause of an update with error status level.

Typically, you would use cause to retrieve the error code returned by Fleet Engine for failed location updates.

The following sample illustrates how to implement StatusListener:

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) {
    // Implementation
  }
}

// Inject StatusListener into DriverContext.
DriverContextBuilder.setStatusListener(new MyStatusListener());

The following shows a sample DriverStatusListener implementation:

class MyStatusListener implements DriverStatusListener {
  /** Called when background status is updated during actions such as location reporting. */
  @Override
  public void updateStatus(
      StatusLevel statusLevel, StatusCode statusCode, String statusMsg, @Nullable Throwable cause) {
    // Existing implementation

    if (cause != null && cause instanceof StatusRuntimeException) {
      if (Status.NOT_FOUND.getCode().equals(cause.getStatus().getCode())) {
        // NOT_FOUND gRPC exception thrown by Fleet Engine.
      }
    }
  }
}

DriverContextBuilder.setStatusListener(new MyStatusListener());

Implement DriverStatusListener as a functional interface

DriverStatusListener supports Java functional interfaces just like its predecessor. Here is an example of it:

DriverContextBuilder.setDriverStatusListener((statusLevel, statusCode, statusMsg, cause) -> {
  if (cause != null && cause instanceof StatusRuntimeException) {
    if (Status.NOT_FOUND.getCode().equals(cause.getStatus().getCode())) {
      // NOT_FOUND gRPC exception thrown by Fleet Engine.
    }
  }
});