Skip to content

Most visited

Recently visited


Migrate to Android Plugin for Gradle 3.0.0

Known issue: If you have an existing Android Studio project that's using an alpha version of Android plugin 3.0.0 (such as 3.0.0-alpha9), you may get the following error when you migrate to Android plugin 3.0.0-beta4 and sync your project: Gradle project refresh failed.

Resolve this issue by selecting Build > Clean Project from the menu bar—you need to perform this action only once for each project. You can then sync your project files with Gradle by clicking Sync Project from the menu bar.

If you want to migrate your project to Android plugin 3.0.0-beta4 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.1-rc-1 or higher. If you're opening an existing project using Android Studio 3.0 Beta 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 as follows:


Apply the plugin

If you're opening an existing project using Android Studio 3.0 Beta 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.

    dependencies {
        classpath ''

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"

Resolve build errors related to dependency matching

The Android plugin tries to match each variant of your app with the same one from the library. So, when you build a "freeDebug" version of your app, the plugin tries to match it with "freeDebug" versions of its local library dependencies.

However, consider if your app configures a build type called "staging", but one of its library dependencies does not. When the plugin tries to build the "staging" version of your app, it won't know which version of the library to use, and you'll see an error message similar to the following:

Error:Failed to resolve: Could not resolve project :mylibrary.
Required by:
    project :app

Android plugin 3.0.0-beta4 and higher include DSL elements to help control how the plugin should resolve situations in which a direct variant match between an app and a dependency is not possible. The table below helps you determine which DSL property you should use to resolve certain build errors related to variant-aware dependency matching.

Cause of build errorResolution

Your app includes a build type that a library dependency does not.

For example, your app includes a "staging" build type, but a dependency includes only a "debug" and "release" build type.

Note that there is no issue when a library dependency includes a build type that your app does not. That's because the plugin simply never requests that build type from the dependency.

Use matchingFallbacks to specify alternative matches for a given build type, as shown below:
// In the app's build.gradle file.
android {
    buildTypes {
        debug {}
        release {}
        staging {
            // Specifies a sorted list of fallback build types that the
            // plugin should try to use when a dependency does not include a
            // "staging" build type. You may specify as many fallbacks as you
            // like, and the plugin selects the first build type that's
            // available in the dependency.
            matchingFallbacks = ['debug', 'qa', 'release']

For a given flavor dimension that exists in both the app and its library dependency, your app includes flavors that the library does not.

For example, both your app and its library dependencies include a "tier" flavor dimension. However, the "tier" dimension in the app includes "free" and "paid" flavors, but a dependency includes only "demo" and "paid" flavors for the same dimension.

Note that, for a given flavor dimension that exists in both the app and its library dependencies, there is no issue when a library includes a product flavor that your app does not. That's because the plugin simply never requests that flavor from the dependency.

Use matchingFallbacks to specify alternative matches for the app's "free" product flavor, as shown below:
// In the app's build.gradle file.
android {
    // Do not configure matchingFallbacks in the defaultConfig block.
    // Instead, you must specify fallbacks for a given product flavor in the
    // productFlavors block, as shown below.
    flavorDimensions 'tier'
    productFlavors {
        paid {
            dimension 'tier'
            // Because the dependency already includes a "paid" flavor in its
            // "tier" dimension, you don't need to provide a list of fallbacks
            // for the "paid" flavor.
        free {
            dimension 'tier'
            // Specifies a sorted list of fallback flavors that the plugin
            // should try to use when a dependency's matching dimension does
            // not include a "free" flavor. You may specify as many
            // fallbacks as you like, and the plugin selects the first flavor
            // that's available in the dependency's "tier" dimension.
            matchingFallbacks = ['demo', 'trial']

A library dependency includes a flavor dimension that your app does not.

For example, a library dependency includes flavors for a "minApi" dimension, but your app includes flavors for only the "tier" dimension. So, when you want to build the "freeDebug" version of your app, the plugin doesn't know whether to use the "minApi23Debug" or "minApi18Debug" version of the dependency.

Note that there is no issue when your app includes a flavor dimension that a library dependency does not. That's because the plugin matches flavors of only the dimensions that exist in the dependency. For example, if a dependency did not include a dimension for ABIs, the "freeX86Debug" version of your app would simply use the "freeDebug" version of the dependency.

Use missingDimensionStrategy in the defaultConfig block to specify the default flavor the plugin should select from each missing dimension, as shown in the sample below. You can also override your selections in the productFlavors block, so each flavor can specify a different matching strategy for a missing dimension.
// In the app's build.gradle file.
android {
    // Specifies a sorted list of flavors that the plugin should try to use from
    // a given dimension. The following tells the plugin that, when encountering
    // a dependency that includes a "minApi" dimension, it should select the
    // "minApi18" flavor. You can include additional flavor names to provide a
    // sorted list of fallbacks for the dimension.
    missingDimensionStrategy 'minApi', 'minApi18', 'minApi23'
    // You should specify a missingDimensionStrategy property for each
    // dimension that exists in a local dependency but not in your app.
    missingDimensionStrategy 'abi', 'x86', 'arm64'
    flavorDimensions 'tier'
    productFlavors {
        free {
            dimension 'tier'
            // You can override the default selection at the product flavor
            // level by configuring another missingDimensionStrategy property
            // for the "minApi" dimension.
            missingDimensionStrategy 'minApi', 'minApi23', 'minApi18'
        paid {}

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

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 '<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 ('debug') {

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 changes

Android plugin 3.0.0 introduces API changes that removes certain functionalities and may break your existing builds. Later versions of the plugin may introduce new public APIs that replace broken functionalities.

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


The processManifest.manifestOutputFile() method is no longer available, and you get the following error when you try to call it:

A problem occurred configuring project ':myapp'.
   Could not get unknown property 'manifestOutputFile' for task ':myapp:processDebugManifest'
   of type

Instead of calling manifestOutputFile() to get the manifest file for each variant, you can call processManifest.manifestOutputDirectory() to return the path of the directory that contains all generated manifests. You can then locate a manifest and apply your logic to it. The sample below dynamically changes the version code in the manifest:

android.applicationVariants.all { variant ->
    variant.outputs.all { output ->
        output.processManifest.doLast {
            // Stores the path to the maifest.
            String manifestPath = "$manifestOutputDirectory/AndroidManifest.xml"
            // Stores the contents of the manifest.
            def manifestContent = file(manifestPath).getText()
            // Changes the version code in the stored text.
            manifestContent = manifestContent.replace('android:versionCode="1"',
                    String.format('android:versionCode="%s"', generatedCode))
            // Overwrites the manifest with the new text.
This site uses cookies to store your preferences for site-specific language and display options.

Get the latest Android developer news and tips that will help you find success on Google Play.

* Required Fields


Browse this site in ?

You requested a page in , but your language preference for this site is .

Would you like to change your language preference and browse this site in ? If you want to change your language preference later, use the language menu at the bottom of each page.

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 short survey?
Help us improve the Android developer experience.
(Sep 2017 survey)