Skip to content

Most visited

Recently visited

navigation

Migrate to the New Plugin

If you want to migrate your project to Android plugin 3.0.0-alpha1 or higher, read this page to learn how to apply the plugin and specific version of Gradle, and adapt your project to some breaking changes.

Update Gradle version

The new Android plugin requires Gradle version 4.0-milestone-1 or higher. If you're opening an existing project using Android Studio 3.0 Preview 1 or later, follow the prompts to automatically update an existing project to the compatible version of Gradle.

To update Gradle manually, update the URL in gradle-wrapper.properties as follows:

distributionUrl=\
  https\://services.gradle.org/distributions/gradle-4.0-milestone-1-all.zip

Apply the plugin

If you're opening an existing project using Android Studio 3.0 Preview 1 or later, follow the prompts to automatically update your project to the latest version of the Android plugin. To manually update your project, include the maven repo and change the plugin version in your project-level build.gradle file as follows:

buildscript {
    repositories {
        ...
        // You need to add the following repository to download the
        // new plugin.
        maven {
          url 'https://maven.google.com'
        }
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.0-alpha1'
    }
}

Use Flavor Dimensions for variant-aware dependency management

Plugin 3.0.0 includes a new dependency mechanism that automatically matches variants when consuming a library. This means an app's debug variant automatically consumes a library's debug variant, and so on. It also works when using flavors—an app's redDebug variant will consume a library's redDebug variant. To make this work, the plugin now requires that all flavors belong to a named flavor dimension —even if you intend to use only a single dimension. Otherwise, you will get the following build error:

Error:All flavors must now belong to a named flavor dimension.
The flavor 'flavor_name' is not assigned to a flavor dimension.

To resolve this error, assign each flavor to a named dimension, as shown in the sample below. Because dependency matching is now taken care of by the plugin, you should name your flavor dimensions carefully. For example, if all your app and library modules use the foo dimension, you'll have less control over which flavors are matched by the plugin.

// Specifies a flavor dimension.
flavorDimensions "color"

productFlavors {
     red {
      // Assigns this product flavor to the 'color' flavor dimension.
      // This step is optional if you are using only one dimension.
      dimension "color"
      ...
    }

    blue {
      dimension "color"
      ...
    }
}

Select default flavors for missing dimensions

If a consumer does not have a flavor dimension that the producer does, you need to specify a default flavor (and dimension) for each dimension that the consumer does not have. For example, if library foo has dimensions shape and color, but the app bar only uses the color dimension, you may get the following build error:

Error:Could not resolve all dependencies for configuration ':bar:redDebugCompileClasspath'.
Cannot choose between the following configurations on project :foo:
  - redCircleDebugApiElements
  - redSquareDebugApiElements
  ...

Using the flavorSelection property in the consumer's build.gradle file, you can pick the default flavor of the producer that the plugin should use, as shown below:

android {
  ...
  // The flavorSelection property uses the following format:
  // flavorSelection 'dimension_name', 'flavor_name'

  // Chooses the 'red' flavor from libraries that specify a 'color'
  // dimension.
  flavorSelection 'shape', 'square'
}

Note: There's no issue if a producer does not have a flavor dimension that the consumer does. That's because, by default, an app's redDebug variant consumes a library's debug variant.

While, by default, the plugin expects an exact same name for dependency matching (i.e. red must match red), Gradle has a new DSL to offer some flexibility around attribute matching. You could, for instance, set up some rules saying that if a consumer asks for red, then red or magenta are compatible. However, the usage of this DSL is non-trivial and we are exploring ways to make it easier to use.

Known Issue: You currently can not set this per-variant on the consumer side, though we intend to change this in the future. Additionally, if two libraries each configure a color dimension, you can not specify the red flavor for the first library and the blue flavor for the second library.

Migrate dependency configurations for local modules

If you've properly configured your flavor dimensions to take advantage of variant-aware dependency resolution, you no longer need to use variant-specific configurations, such as redDebugImplementation, for local module dependencies—the plugin takes care of this for you. Using variant-specific configurations is optional and doesn't break your build.

However, targeting a specific variant of a local module dependency (for example, using configuration: 'debug') causes the following build error:

Error:Could not resolve all dependencies for configuration
  ':app:prodDebugCompileClasspath'.
Project :app declares a dependency from configuration 'compile'
  to configuration 'debug' which is not declared in the descriptor
  for project :foo.

You should instead configure your dependencies as follows:

dependencies {
    // This is the old method and no longer works for local
    // library modules:
    // debugCompile project(path: ':foo', configuration: 'debug')
    // releaseCompile project(path: ':foo', configuration: 'release')

    // Instead, simply use the following to take advantage of
    // variant-aware dependency resolution. You can learn more about
    // the 'implementation' configuration in the section about
    // new dependency configurations.
    implementation project(':foo')

    // You can, however, keep using variant-specific configurations when
    // targeting external dependencies. The following line adds 'app-magic'
    // as a dependency to only the 'debug' version of your module.

    debugImplementation 'com.example.android:app-magic:12.3'
}

Note: You cannot easily use the old mechanism for manual variant dependency anymore, even though the Gradle API for it is still present. The configuration provided to the project() DSL now needs to match the consumer in build type and flavors (and other attributes). For instance, it is not possible to make a 'debug' variant consume a 'release' variant through this mechanism because the producer and consumer would not match. (In this case, the name 'debug' refers to the published configuration object mentioned above in the Publishing Dependencies section.) Now that we publish two configurations, one for compiling and one for runtime, this old way of selecting one configuration really doesn't work anymore.

Configure Wear App dependencies

To support variant-aware dependency resolution for embedded wear apps, plugin 3.0.0 now combines all the graphs together before resolving them, similarly to how other dependencies are handled. In previous versions of the plugin, <component>WearApp dependency graphs were resolved separately. So, for example, you could do something like the following, and the blue variant(s) would use :wear2 and all other variants would use :wear1:

dependencies {
    // This is the old way of configuring Wear App dependencies.
    wearApp project(':wear1')
    blueWearApp project(':wear2')
}

The configuration above no longer works with the new plugin. However, if your wearable module configures the same flavors as your main app, you don't need to use the <flavor>WearApp configuration. Simply specify the wearApp configuration and each variant of the main app will consume the matching variant from wearable:

dependencies {
    // If the main app and wearable modules have the same flavors,
    // the following configuration uses automatic dependency matching.
    wearApp  project(':wearable')
}

If you want to specify a different Wear App module per app flavor, you can still use the <flavor>WearApp configuration as follows (however you can't combine it with the wearApp configuration):

dependencies {
    redWearApp project(':wear1')
    greenWearApp project(':wear1')
    blueWearApp project(':wear2')
}

Use the new dependency configurations

Gradle 3.4 introduced new Java Library plugin configurations that allow control over publication to compile and runtime classpaths (for inter-module dependencies). Android plugin 3.0.0 is moving to these new dependency configurations. To migrate your project, simply update your dependencies to use the new configurations instead of the deprecated ones, as outlined in the table below.

New configuration Deprecated configuration Behavior
implementation compile The dependency is available to the module at compile time, and it's available to the consumer of the module only at runtime. For large multi-project builds, using implementation instead of api/compile can result in significant build time improvements because it reduces the amount of projects that the build system needs to recompile. Most app and test modules should use this configuration.
api compile The dependency is available to the module at compile time, and it's also available to the consumer of the module at compile time and runtime. This configuration behaves just like compile (which is now deprecated), and you should typically use this only in library modules. App modules should use implementation, unless you want to expose its API to a separate test module.
compileOnly provided The dependency is available to the module only at compile time, and not available to its consumers at compilation or runtime. This configuration behaves just like provided (which is now deprecated).
runtimeOnly apk The dependency is available to the module and its consumers only at runtime. This configuration behaves just like apk (which is now deprecated).

Just like the current stable versions of the Android plugin, the above configurations are available for flavor- or build-type-specific dependencies. For example, you can use api to make the dependency available to all variants, or you can use redApi to make it available to only the red variant(s) of the module.

Note: compile, provided, and apk are currently still available. However, they will disappear in the next major release of the Android plugin.

Publish dependencies

The following configurations hold the transitive dependencies of a library for consumption by its consumers:

There used to be a single configuration per variant called: <variant>. Since a library can now control what consumers see for compilation, using the implementation and api configurations described in a previous section, there are now two configurations, one for compilation of the consumer(s), and one for runtime.

To learn more about the relationships between the different configurations, go to The Java Library plugin configurations.

Migrate custom dependency resolution strategies

The plugin uses the following configurations to resolve all the dependencies of a variant:

If you're still using the old configurations, you'll get a build error similar to the following:

Error:Configuration with old name _debugCompile found.
Use new name debugCompileClasspath instead.

Plugins or build files that set a resolution strategy on the resolved configuration will need to adapt to the new name. Because of delayed dependency resolution, it is now possible to set the resolution strategy while using the variant API, as shown in the example below. (The Android plugin now includes getters to access the configuration objects of a variant.)

// Previously, you had to apply a custom resolution strategy during the
// configuration phase, rather than in the execution phase. That's
// because, by the time the variant was created and the Variant API was
// called, the dependencies were already resolved. This no longer works, and
// you should use this method only while using an older version of the plugin.
// configurations {
//     _debugCompile
//     _debugApk
// }
// ...
//
// configurations._debugCompile.resolutionStrategy {
//     ...
// }
//
// configurations.all {
//     resolutionStrategy {
//     ...
//     }
// }

// Because the new build model delays dependency resolution, you should
// query and modify the resolution strategy using the Variant API.
android {
    applicationVariants.all { variant ->
        variant.getCompileConfiguration().resolutionStrategy {
            ...
        }
        variant.runtimeConfiguration.resolutionStrategy {
            ...
        }
        variant.getAnnotationProcessorConfiguration().resolutionStrategy {
            ...
        }
    }
}

Note: The new plugin currently looks for configurations using the old name and will fail if it finds them. Otherwise it would silently ignore the custom resolution strategy. We may change this based on feedback, but we would like to find a way to ease migration.

Use the annotation processor dependency configuration

In previous versions of the Android plugin for Gradle, dependencies on the compile classpath were automatically added to the processor classpath. That is, you could add an annotation processor to the compile classpath and it would work as expected. However, this causes a significant impact to performance by adding a large number of unnecessary dependencies to the processor.

When using the new plugin, annotation processors must be added to the processor classpath using the annotationProcessor dependency configuration, as shown below:

dependencies {
    ...
    annotationProcessor 'com.google.dagger:dagger-compiler:<version-number>'
}

The plugin assumes a dependency is an annotation processor if its JAR file contains the following file: META- INF/services/javax.annotation.processing.Processor. If the plugin detects annotation processors on the compile classpath, your build fails and you get an error message that lists each annotation processor on the compile classpath. To fix the error, simply change the configuration of those dependencies to use annotationProcessor. If a dependency includes components that also need to be on the compile classpath, declare that dependency a second time and use the compile dependency configuration.

android-apt plugin users: This behavior change currently does not affect the android-apt plugin. However, the plugin will not be compatible with future versions of the Android plugin for Gradle.

Disable the error check

If you have dependencies on the compile classpath that include annotation processors you don't need, you can disable the error check by adding the following to your build.gradle file. Keep in mind, the annotation processors you add to the compile classpath are still not added to the processor classpath.

android {
    ...
    defaultConfig {
        ...
        javaCompileOptions {
            annotationProcessorOptions {
                includeCompileClasspath false
            }
        }
    }
}

If you are experiencing issues migrating to the new dependency resolution strategy, you can restore behavior to that of Android plugin 2.3 by setting includeCompileClasspath true. However, restoring behavior to version 2.3 is not recommended, and the option to do so will be removed in a future update. To help us improve compatibility with the dependencies you're using, please file a bug.

Using separate test modules

Separate test modules are now variant-aware (see the section above) when using plugin 3.0.0. This means that specifying targetVariant is no longer necessary.

Each variant in the test module will attempt to test a matching variant in the target project. By default, test modules contain only a debug variant, but you can create new build types and new flavors to create new variants to match the tested app project. A connectedCheck task is created for each variant.

To make the Test project test a different build type only, and not the debug one, use VariantFilter to disable the debug variant in the test project, as shown below:

android {
    variantFilter { variant ->
        if (variant.buildType.name.equals('debug') {
            variant.setIgnore(true);
        }
    }
}

If you want a test module to target only certain flavored variants of an app, you can use flavorSelection properties to target the flavors you want to test. This also prevents the test module from having to configure those flavors for itself.

Local Jars In Libraries

Previously, library modules would handle dependencies on local JARs in a non- standard way and would package them inside their AAR. Even in a multi-project build, consumers of the AAR would see these JAR files through the packaged version.

Android plugin 3.0.0 and higher use new Gradle APIs to allow consuming projects to see the local JARs as regular transitive dependencies, similar to maven coordinate based dependencies. To adapt to the new Gradle APIs, the plugin had to change a few aspects of how it handles local JAR files.

Inter-project publishing

Publishing to Maven repo

API change in variant output

Using the Variant API to manipulate variant outputs is broken with the new plugin. It still works for simple tasks, such as changing the APK name during build time, as shown below:

// If you use each() to iterate through the variant objects,
// you need to start using all(). That's because each() iterates
// through only the objects that already exist during configuration time—
// but those object don't exist at configuration time with the new model.
// However, all() adapts to the new model by picking up object as they are
// added during execution.
android.applicationVariants.all { variant ->
    variant.outputs.all {
        outputFileName = "${variant.name}-${variant.versionName}.apk"
    }
}

However, more complicated tasks that involve accessing outputFile objects no longer work. That's because variant-specific tasks are no longer created during the configuration stage. This results in the plugin not knowing all of its outputs up front, but it also means faster configuration times. As an alternative, we will introduce new APIs to provide similar functionality.

This site uses cookies to store your preferences for site-specific language and display options.

Hooray!

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a one-minute survey?
Help us improve Android tools and documentation.