**Caution:** Since August 2021, all new
apps must be published as App Bundles. If you publish your app to Google Play,
build and upload an [Android App Bundle](https://developer.android.com/guide/app-bundle). When
you do so, Google Play automatically generates and serves optimized APKs for
each user's device configuration, so they download only the code and resources
they need to run your app. Publishing multiple APKs is useful if you are
publishing to a store that doesn't support the AAB format. In that case, you
must build, sign, and manage each APK yourself.

Although it is better to build a single APK to support all your target devices
whenever possible, that might result in a very large APK due to files
supporting multiple [screen densities](https://developer.android.com/training/multiscreen/screendensities) or [Application Binary
Interfaces](https://developer.android.com/ndk/guides/abis) (ABIs). One way to reduce the size of your APK is to create
[multiple APKs](https://developer.android.com/google/play/publishing/multiple-apks) that
contain files for specific screen densities or ABIs.


Gradle can create separate APKs that contain only code and resources specific
to each density or ABI. This page describes how to configure your build to
generate multiple APKs. If you need to create different versions of your app
that are not based on screen density or ABI, use [build variants](https://developer.android.com/studio/build/build-variants) instead.

## Configure your build for multiple APKs

To configure your build for multiple APKs, add a
[`splits`](https://developer.android.com/reference/tools/gradle-api/7.2/com/android/build/api/dsl/Splits) block to your module-level
`build.gradle` file. Within the
`splits` block, provide
a `density` block that specifies how you want Gradle to generate
per-density APKs or an `abi` block that specifies how you want Gradle
to generate per-ABI APKs. You can provide both density and ABI blocks, and
the build system creates an APK for each density and ABI combination.
| **Note:** Generating per-language APKs is supported only for Android Instant App projects.

### Configure multiple APKs for screen densities

To create separate APKs for different screen densities, add a
`density` block inside your
`splits` block. In your `density` block, provide a
list of desired screen densities and compatible screen sizes. Only use the list of
compatible screen sizes if you need specific
[`<compatible-screens>`](https://developer.android.com/guide/topics/manifest/compatible-screens-element) elements in each APK's manifest.


The following Gradle DSL options are used to configure multiple APKs for
screen densities:


`enable` for Groovy, `isEnable` for Kotlin script
:
    If you set this element to `true`, Gradle generates multiple APKs
    based on the screen densities you define. The default value is
    `false`.


`exclude`
:
    Specifies a comma-separated list of densities that you don't want Gradle
    to generate separate APKs for. Use `exclude` if you
    want to generate APKs for most densities but need to exclude a few
    densities that your app doesn't support.


`reset()`

:   Clears the default list of screen densities. Only use when combined with the
    `include` element to specify the densities you want to
    add.

    The following snippet sets the list of densities to just
    `ldpi` and `xxhdpi` by calling `reset()`
    to clear the list, and then using `include`:  

    ```
    reset()                  // Clears the default list from all densities
                             // to no densities.
    include "ldpi", "xxhdpi" // Specifies the two densities to generate APKs
                             // for.
    ```


`include`
:
    Specifies a comma-separated list of densities that you want Gradle to generate
    APKs for. Only use in combination with `reset()` to specify an
    exact list of densities.


`compatibleScreens`

:   Specifies a comma-separated list of compatible screen sizes. This injects
    a matching [`<compatible-screens>`](https://developer.android.com/guide/topics/manifest/compatible-screens-element) node in the manifest for
    each APK.

    This setting provides a convenient way to manage both screen
    densities and screen sizes in the same `build.gradle` section.
    However, using
    `<compatible-screens>` can limit the types of device
    your app works with. For alternative ways to support different
    screen sizes, see the
    [screen compatibility overview](https://developer.android.com/guide/practices/screens_support).

Because each APK that's based on screen density includes a
`<compatible-screens>` tag with specific restrictions
about which screen types the APK supports---even if you publish several
APKs---some new devices don't match your multiple APK filters. As such,
Gradle always generates an additional universal APK that contains assets
for all screen densities and doesn't include a
`<compatible-screens>` tag. Publish this
universal APK along with your per-density APKs to provide a fallback for
devices that don't match the APKs with a
`<compatible-screens>` tag.

The following example generates a separate APK for each
[screen
density](https://developer.android.com/training/multiscreen/screendensities#TaskProvideAltBmp") except `ldpi`, `xxhdpi`, and
`xxxhdpi`. This is done by using `exclude` to remove
those three densities from the default list of all densities.  

### Groovy

```groovy
android {
  ...
  splits {

    // Configures multiple APKs based on screen density.
    density {

      // Configures multiple APKs based on screen density.
      enable true

      // Specifies a list of screen densities you don't want Gradle to create multiple APKs for.
      exclude "ldpi", "xxhdpi", "xxxhdpi"

      // Specifies a list of compatible screen size settings for the manifest.
      compatibleScreens 'small', 'normal', 'large', 'xlarge'
    }
  }
}
```

### Kotlin

```kotlin
android {
    ...
    splits {

        // Configures multiple APKs based on screen density.
        density {

            // Configures multiple APKs based on screen density.
            isEnable = true

            // Specifies a list of screen densities you don't want Gradle to create multiple APKs for.
            exclude("ldpi", "xxhdpi", "xxxhdpi")

            // Specifies a list of compatible screen size settings for the manifest.
            compatibleScreens("small", "normal", "large", "xlarge")
        }
    }
}
```

For more details on customizing different build
variants of your app to specific screen types and devices, see
[Declare restricted
screen support](https://developer.android.com/guide/practices/screens-distribution).

### Configure multiple APKs for ABIs

To create separate APKs for different ABIs, add an `abi` block
inside your
`splits` block. In your `abi` block, provide a list of
desired ABIs.

The following Gradle DSL options are used to configure multiple APKs per
ABI:


`enable` for Groovy, or `isEnable` for Kotlin script
:   If you set this element to `true`, Gradle generates multiple
    APKs based on the ABIs you define. The default value is `false`.


`exclude`
:
    Specifies a comma-separated list of ABIs that you don't want Gradle to
    generate separate APKs for. Use `exclude` if you want to generate
    APKs for most ABIs but need to exclude a few ABIs that your app doesn't
    support.


`reset()`

:   Clears the default list of ABIs. Only use when combined with the
    `include` element to specify the ABIs you want to add.

    The following snippet sets the list of ABIs to just `x86` and
    `x86_64` by calling `reset()` to clear the list, and
    then using `include`:  

    ```
    reset()                 // Clears the default list from all ABIs to no ABIs.
    include "x86", "x86_64" // Specifies the two ABIs we want to generate APKs for.
    ```


`include`
:
    Specifies a comma-separated list of ABIs that you want Gradle to generate APKs
    for. Only use in combination with `reset()` to specify an exact
    list of ABIs.


`universalApk` for Groovy, or `isUniversalApk` for
Kotlin script

:   If `true`, Gradle generates a universal APK in addition to
    per-ABI APKs. A universal APK contains code and resources for all ABIs in a
    single APK. The default value is `false`.

    Note that this option is only
    available in the `splits.abi` block. When building multiple APKs
    based on screen density, Gradle always generates a universal APK that
    contains code and resources for all screen densities.

The following example generates a separate APK for each ABI: `x86`
and `x86_64`. This is done by using `reset()`
to start with an empty list of ABIs, followed by `include` with a
list of ABIs that each get an APK.  

### Groovy

```groovy
android {
  ...
  splits {

    // Configures multiple APKs based on ABI.
    abi {

      // Enables building multiple APKs per ABI.
      enable true

      // By default all ABIs are included, so use reset() and include to specify that you only
      // want APKs for x86 and x86_64.

      // Resets the list of ABIs for Gradle to create APKs for to none.
      reset()

      // Specifies a list of ABIs for Gradle to create APKs for.
      include "x86", "x86_64"

      // Specifies that you don't want to also generate a universal APK that includes all ABIs.
      universalApk false
    }
  }
}
```

### Kotlin

```kotlin
android {
  ...
  splits {

    // Configures multiple APKs based on ABI.
    abi {

      // Enables building multiple APKs per ABI.
      isEnable = true

      // By default all ABIs are included, so use reset() and include to specify that you only
      // want APKs for x86 and x86_64.

      // Resets the list of ABIs for Gradle to create APKs for to none.
      reset()

      // Specifies a list of ABIs for Gradle to create APKs for.
      include("x86", "x86_64")

      // Specifies that you don't want to also generate a universal APK that includes all ABIs.
      isUniversalApk = false
    }
  }
}
```

For a list of supported ABIs, see
[Supported
ABIs](https://developer.android.com/ndk/guides/abis.html#sa).

#### Projects without native/C++ code

For projects without native/C++ code, the **Build Variants** panel has two
columns: **Module** and **Active Build
Variant**, as shown in figure 1.

![The Build variants panel](https://developer.android.com/static/studio/images/build/build-variants.png)  

**Figure 1.** The **Build Variants** panel has two columns for projects without
native/C++ code.

The **Active Build Variant** value for the
module determines the build variant that is deployed and visible in the editor.
To switch between variants, click the **Active Build Variant** cell for a module
and choose the desired variant from the list field.

#### Projects with native/C++ code

For projects with native/C++ code, the **Build Variants** panel has three
columns: **Module** , **Active Build
Variant** , and **Active ABI**, as shown in figure 2.

![](https://developer.android.com/static/studio/images/build/build-variants-ndk.png)
**Figure 2.** The **Build Variants** panel adds the **Active ABI** column for
projects with native/C++ code.

The **Active Build Variant** value for the module
determines the build variant that is deployed and is visible in the editor.
For native modules, the **Active ABI** value determines the ABI that the editor
uses, but doesn't impact what is deployed.

To change the build type or ABI:

1. Click the cell for the **Active Build Variant** or **Active ABI** column.
2. Choose the desired variant or ABI from the list field. A new sync automatically runs.

Changing either column for an app or library module applies the change to all
dependent rows.

### Configure versioning


By default, when Gradle generates multiple APKs, each APK has the same
version information, as specified in the module-level
`build.gradle` or `build.gradle.kts` file. Because the
Google Play Store doesn't allow multiple APKs for the same app that all have
the same version information, you need to ensure that each APK has a unique
[`versionCode`](https://developer.android.com/studio/publish/versioning#versioningsettings) before you upload to the Play Store.


You can configure your module-level `build.gradle` file to
override the `versionCode` for each APK. By creating a mapping
that assigns a unique numeric value for each ABI and density that you configure
multiple APKs for, you can override the output version code with a value that
combines the version code defined within the `defaultConfig` or
`productFlavors` block with the numeric value assigned to the
density or ABI.


In the following example, the APK for the `x86` ABI
gets a `versionCode` of 2004 and the `x86_64` ABI
gets a `versionCode` of 3004.

<br />

Assigning version codes in large increments, such as 1000, allows
you to later assign unique version codes if you need to update your app. For
example, if `defaultConfig.versionCode` iterates to 5 in a
subsequent update, Gradle assigns a `versionCode` of 2005 to
the `x86` APK and 3005 to the `x86_64` APK.

<br />


**Tip:** If your build includes a universal APK, assign it a
`versionCode` that's lower than that of any of your other APKs.
Because Google Play Store installs the version of your app that is both
compatible with the target device and has the highest
`versionCode`, assigning a lower `versionCode` to the
universal APK ensures that Google Play Store tries to install one of your
APKs before falling back to the universal APK. The following sample code
handles this by not overriding a universal APK's
default `versionCode`.  

### Groovy

```groovy
android {
  ...
  defaultConfig {
    ...
    versionCode 4
  }
  splits {
    ...
  }
}

// Map for the version code that gives each ABI a value.
ext.abiCodes = ['armeabi-v7a':1, x86:2, x86_64:3]

// For per-density APKs, create a similar map:
// ext.densityCodes = ['mdpi': 1, 'hdpi': 2, 'xhdpi': 3]

import com.android.build.OutputFile

// For each APK output variant, override versionCode with a combination of
// ext.abiCodes * 1000 + variant.versionCode. In this example, variant.versionCode
// is equal to defaultConfig.versionCode. If you configure product flavors that
// define their own versionCode, variant.versionCode uses that value instead.
android.applicationVariants.all { variant ->

  // Assigns a different version code for each output APK
  // other than the universal APK.
  variant.outputs.each { output ->

    // Stores the value of ext.abiCodes that is associated with the ABI for this variant.
    def baseAbiVersionCode =
            // Determines the ABI for this variant and returns the mapped value.
            project.ext.abiCodes.get(output.getFilter(OutputFile.ABI))

    // Because abiCodes.get() returns null for ABIs that are not mapped by ext.abiCodes,
    // the following code doesn't override the version code for universal APKs.
    // However, because you want universal APKs to have the lowest version code,
    // this outcome is desirable.
    if (baseAbiVersionCode != null) {

      // Assigns the new version code to versionCodeOverride, which changes the
      // version code for only the output APK, not for the variant itself. Skipping
      // this step causes Gradle to use the value of variant.versionCode for the APK.
      output.versionCodeOverride =
              baseAbiVersionCode * 1000 + variant.versionCode
    }
  }
}
```

### Kotlin

```kotlin
android {
  ...
  defaultConfig {
    ...
    versionCode = 4
  }
  splits {
    ...
  }
}

// Map for the version code that gives each ABI a value.
val abiCodes = mapOf("armeabi-v7a" to 1, "x86" to 2, "x86_64" to 3)

// For per-density APKs, create a similar map:
// val densityCodes = mapOf("mdpi" to 1, "hdpi" to 2, "xhdpi" to 3)

import com.android.build.api.variant.FilterConfiguration.FilterType.*

// For each APK output variant, override versionCode with a combination of
// abiCodes * 1000 + variant.versionCode. In this example, variant.versionCode
// is equal to defaultConfig.versionCode. If you configure product flavors that
// define their own versionCode, variant.versionCode uses that value instead.
androidComponents {
    onVariants { variant ->

        // Assigns a different version code for each output APK
        // other than the universal APK.
        variant.outputs.forEach { output ->
            val name = output.filters.find { it.filterType == ABI }?.identifier

            // Stores the value of abiCodes that is associated with the ABI for this variant.
            val baseAbiCode = abiCodes[name]
            // Because abiCodes.get() returns null for ABIs that are not mapped by ext.abiCodes,
            // the following code doesn't override the version code for universal APKs.
            // However, because you want universal APKs to have the lowest version code,
            // this outcome is desirable.
            if (baseAbiCode != null) {
                // Assigns the new version code to output.versionCode, which changes the version code
                // for only the output APK, not for the variant itself.
                output.versionCode.set(baseAbiCode * 1000 + (output.versionCode.get() ?: 0))
            }
        }
    }
}
```

For more examples of alternate version code schemes, see
[Assigning version codes](https://developer.android.com/google/play/publishing/multiple-apks#VersionCodes).

## Build multiple APKs

Once you configure your module-level `build.gradle` or
`build.gradle.kts` file to build multiple APKs, click
**Build \> Build APK** to build all APKs for the currently
selected module in the **Project** pane. Gradle creates the APKs
for each density or ABI in the project's `build/outputs/apk/`
directory.

Gradle builds an APK for each density or ABI you configure multiple APKs for.
If you enable multiple APKs for both densities and ABIs, Gradle creates an APK
for each density and ABI combination.

<br />

For example, the following
`build.gradle` snippet enables building multiple APKs for `mdpi` and
`hdpi` densities, and also `x86` and `x86_64` ABIs:

<br />

### Groovy

```groovy
...
  splits {
    density {
      enable true
      reset()
      include "mdpi", "hdpi"
    }
    abi {
      enable true
      reset()
      include "x86", "x86_64"
    }
  }
```

### Kotlin

```kotlin
...
  splits {
    density {
      isEnable = true
      reset()
      include("mdpi", "hdpi")
    }
    abi {
      isEnable = true
      reset()
      include("x86", "x86_64")
    }
  }
```

The output from the example configuration includes the following 4 APKs:

- `app-hdpiX86-release.apk`: Contains code and resources for `hdpi` density and `x86` ABI.
- `app-hdpiX86_64-release.apk`: Contains code and resources for `hdpi` density and `x86_64` ABI.
- `app-mdpiX86-release.apk`: Contains code and resources for `mdpi` density and `x86` ABI.
- `app-mdpiX86_64-release.apk`: Contains code and resources for `mdpi` density and `x86_64` ABI.


When building multiple APKs based on screen density, Gradle always
generates a universal APK that includes code and resources for all densities,
in addition to the per-density APKs.

<br />

When building multiple APKs based on
ABI, Gradle only generates an APK that includes code and resources for all
ABIs if you specify `universalApk true` in the
`splits.abi` block in your `build.gradle` file
(for Groovy) or `isUniversalApk = true` in the
`splits.abi` block in your `build.gradle.kts` file
(for Kotlin script).

<br />

### APK file name format

When building multiple APKs, Gradle generates APK filenames using the following
scheme:


<var translate="no">modulename</var>`-`<var translate="no">screendensity</var><var translate="no">ABI</var>`-`<var translate="no">buildvariant</var>`.apk`

The scheme components are:


`modulename`
:
    Specifies the module name being built.


`screendensity`
:
    If multiple APKs for screen density are enabled, specifies the screen
    density for the APK, such as `mdpi`.


`ABI`

:   If multiple APKs for ABI are enabled, specifies the ABI for the APK, such
    as `x86`.

    If multiple APKs for both screen density and ABI are enabled,
    Gradle concatenates the density name with the ABI name, for example
    `mdpiX86`. If `universalApk` is enabled for per-ABI
    APKs, Gradle uses `universal` as the ABI portion of the universal APK
    filename.


`buildvariant`
:
    Specifies the build variant being built, such as `debug`.


For example, when building `mdpi` screen density APK for the
debug version of myApp, the APK filename is
`myApp-mdpi-debug.apk`. The release
version of myApp that is configured to build multiple APKs for both the
`mdpi` screen density and the `x86` ABI has an APK filename of
`myApp-mdpiX86-release.apk`.