Mehrere APKs erstellen

Achtung:Seit August 2021 müssen alle neuen Anwendungen als App Bundles veröffentlicht werden. Wenn Sie Ihre App bei Google Play veröffentlichen, erstellen Sie ein Android App Bundle und laden Sie es hoch. In diesem Fall generiert Google Play automatisch optimierte APKs für die Gerätekonfiguration jedes Nutzers und stellt sie bereit, sodass nur der Code und die Ressourcen heruntergeladen werden, die sie zum Ausführen deiner App benötigen. Die Veröffentlichung mehrerer APKs ist nützlich, wenn du in einem Store veröffentlichst, der das AAB-Format nicht unterstützt. In diesem Fall musst du jedes APK selbst erstellen, signieren und verwalten.

Es ist zwar besser, ein einzelnes APK für die Unterstützung aller Zielgeräte zu erstellen, wann immer dies möglich ist. Aufgrund der Dateien, die mehrere Bildschirmdichten oder Binärprogramme (Application Binary Interfaces, ABI) unterstützen, kann dies aber zu einem sehr großen APK führen. Eine Möglichkeit, die Größe deines APKs zu reduzieren, besteht darin, mehrere APKs zu erstellen, die Dateien für bestimmte Bildschirmdichten oder ABIs enthalten.

Gradle kann separate APKs erstellen, die nur Code und Ressourcen für die jeweilige Dichte oder ABI enthalten. Auf dieser Seite wird beschrieben, wie du deinen Build so konfigurierst, dass mehrere APKs generiert werden. Wenn du verschiedene Versionen deiner App erstellen musst, die nicht auf Bildschirmdichte oder ABI basieren, solltest du stattdessen Varianten erstellen verwenden.

Build für mehrere APKs konfigurieren

Wenn du deinen Build für mehrere APKs konfigurieren möchtest, füge der build.gradle-Datei auf Modulebene einen splits-Block hinzu. Geben Sie innerhalb des splits-Blocks einen density-Block an, der angibt, wie Gradle APKs mit der Dichte generieren soll, oder einen abi-Block, der angibt, wie Gradle APK-pro-ABI-APKs generieren soll. Du kannst sowohl Dichte- als auch ABI-Blöcke angeben. Das Build-System erstellt dann für jede Kombination aus Dichte und ABI ein APK.

Mehrere APKs für Bildschirmdichten konfigurieren

Wenn du separate APKs für verschiedene Bildschirmdichten erstellen möchtest, füge innerhalb deines splits-Blocks einen density-Block hinzu. Gib im density-Block eine Liste der gewünschten Bildschirmdichten und kompatiblen Bildschirmgrößen an. Verwende die Liste der kompatiblen Bildschirmgrößen nur, wenn du im Manifest der einzelnen APKs bestimmte <compatible-screens>-Elemente benötigst.

Mit den folgenden Gradle-DSL-Optionen werden mehrere APKs für die Bildschirmdichten konfiguriert:

enable für Groovy, isEnable für Kotlin-Script
Wenn du dieses Element auf true setzt, generiert Gradle mehrere APKs für die von dir definierten Bildschirmdichten. Der Standardwert ist false.
exclude
Gibt eine durch Kommas getrennte Liste von Dichten an, für die Gradle keine separaten APKs generieren soll. Verwende exclude, wenn du APKs für die meisten Dichten generieren möchtest, aber einige nicht unterstützte Dichten ausschließen möchtest.
reset()

Löscht die Standardliste für Bildschirmdichten. Nur in Kombination mit dem Element include verwenden, um die Dichten anzugeben, die hinzugefügt werden sollen.

Mit dem folgenden Snippet wird die Liste der Dichten nur auf ldpi und xxhdpi festgelegt. Dazu wird reset() aufgerufen, um die Liste zu löschen, und dann include verwenden:

reset()                  // Clears the default list from all densities
                         // to no densities.
include "ldpi", "xxhdpi" // Specifies the two densities to generate APKs
                         // for.
include
Gibt eine durch Kommas getrennte Liste von Dichten an, für die Gradle APKs generieren soll. Wird nur in Kombination mit reset() verwendet, um eine genaue Liste der Dichten anzugeben.
compatibleScreens

Gibt eine durch Kommas getrennte Liste kompatibler Bildschirmgrößen an. Dadurch wird für jedes APK ein übereinstimmender <compatible-screens>-Knoten in das Manifest eingefügt.

Mit dieser Einstellung lassen sich die Bildschirmdichten und die Bildschirmgrößen bequem im selben build.gradle-Bereich verwalten. Durch die Verwendung von <compatible-screens> können jedoch die Gerätetypen eingeschränkt werden, mit denen deine App kompatibel ist. Alternativen zur Unterstützung verschiedener Bildschirmgrößen finden Sie in der Übersicht zur Bildschirmkompatibilität.

Da jedes APK, das auf der Bildschirmdichte basiert, ein <compatible-screens>-Tag mit spezifischen Einschränkungen dazu enthält, welche Bildschirmtypen das APK unterstützt, entsprechen einige neue Geräte nicht den Filtern für mehrere APKs. Das gilt auch dann, wenn du mehrere APKs veröffentlichst. Gradle generiert daher immer ein zusätzliches universelles APK, das Assets für alle Bildschirmdichten und kein <compatible-screens>-Tag enthält. Veröffentlichen Sie dieses universelle APK zusammen mit Ihren APKs pro Dichte, um als Fallback für Geräte zu dienen, die nicht den APKs mit einem <compatible-screens>-Tag entsprechen.

Im folgenden Beispiel wird für jede Bildschirmdichte mit Ausnahme von ldpi, xxhdpi und xxxhdpi ein separates APK generiert. Dazu wird exclude verwendet, um diese drei Dichten aus der Standardliste aller Dichten zu entfernen.

Groovig

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

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")
        }
    }
}

Eine Liste der Namen der Dichte und der Bildschirmgröße finden Sie unter Unterstützung verschiedener Bildschirmgrößen. Weitere Informationen zum Anpassen verschiedener Build-Varianten deiner App für bestimmte Bildschirmtypen und Geräte findest du unter Eingeschränkte Bildschirmunterstützung deklarieren.

Mehrere APKs für ABIs konfigurieren

Wenn du separate APKs für verschiedene ABIs erstellen möchtest, füge einen abi-Block innerhalb deines splits-Blocks hinzu. Geben Sie in Ihrem abi-Block eine Liste der gewünschten ABIs an.

Mit den folgenden Gradle-DSL-Optionen werden mehrere APKs pro ABI konfiguriert:

enable für Groovy oder isEnable für Kotlin-Script
Wenn du dieses Element auf true setzt, generiert Gradle mehrere APKs anhand der von dir definierten ABIs. Der Standardwert ist false.
exclude
Gibt eine durch Kommas getrennte Liste von ABIs an, für die Gradle keine separaten APKs generieren soll. Verwende exclude, wenn du APKs für die meisten ABIs generieren möchtest, aber einige ABIs ausschließen möchtest, die deine App nicht unterstützt.
reset()

Löscht die Standardliste der ABIs. Nur in Kombination mit dem Element include verwenden, um die ABIs anzugeben, die du hinzufügen möchtest.

Mit dem folgenden Snippet wird die Liste der ABIs nur auf x86 und x86_64 festgelegt. Dazu wird reset() aufgerufen, um die Liste zu löschen, und dann include verwenden:

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
Gibt eine durch Kommas getrennte Liste von ABIs an, für die Gradle APKs generieren soll. Wird nur in Kombination mit reset() verwendet, um eine genaue Liste von ABIs anzugeben.
universalApk für Groovy oder isUniversalApk für Kotlin-Script

Wenn true, generiert Gradle ein universelles APK zusätzlich zu den APKs pro ABI. Ein universelles APK enthält Code und Ressourcen für alle ABIs in einem einzigen APK. Der Standardwert ist false.

Diese Option ist nur im splits.abi-Block verfügbar. Wenn Sie mehrere APKs basierend auf der Bildschirmdichte erstellen, generiert Gradle immer ein universelles APK, das Code und Ressourcen für alle Bildschirmdichten enthält.

Im folgenden Beispiel wird für jede ABI ein separates APK generiert: x86 und x86_64. Dazu wird reset() verwendet, um mit einer leeren Liste von ABIs zu beginnen, gefolgt von include mit einer Liste von ABIs, die jeweils ein APK erhalten.

Groovig

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

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

Eine Liste der unterstützten ABIs findest du unter Unterstützte ABIs.

Projekte ohne nativen/C++-Code

Bei Projekten ohne nativen/C++-Code enthält der Bereich Build-Varianten zwei Spalten: Module und Aktive Build-Variante (siehe Abbildung 1).

Bereich „Varianten erstellen“
Abbildung 1: Der Bereich Build Variants (Varianten erstellen) enthält zwei Spalten für Projekte ohne nativen/C++-Code.

Der Wert Aktive Build-Variante für das Modul bestimmt die Build-Variante, die bereitgestellt wird und im Editor sichtbar ist. Wenn Sie zwischen Varianten wechseln möchten, klicken Sie für ein Modul auf die Zelle Aktive Build-Variante und wählen Sie die gewünschte Variante aus dem Listenfeld aus.

Projekte mit nativem/C++-Code

Bei Projekten mit nativem/C++-Code enthält der Bereich Build Variants (Varianten erstellen) drei Spalten: Module, Active Build Variant (Aktive Build-Variante) und Active ABI (Aktive ABI), wie in Abbildung 2 dargestellt.

Abbildung 2: Im Bereich Varianten erstellen wird für Projekte mit nativem/C++-Code die Spalte Aktive ABI hinzugefügt.

Der Wert Aktive Build-Variante für das Modul bestimmt die bereitgestellte Build-Variante und wird im Editor angezeigt. Bei nativen Modulen bestimmt der Wert Active ABI (Aktives ABI), das der Editor verwendet, hat aber keinen Einfluss darauf, was bereitgestellt wird.

So ändern Sie den Build-Typ oder ABI:

  1. Klicken Sie auf die Zelle für die Spalte Aktive Build-Variante oder Aktives ABI.
  2. Wählen Sie die gewünschte Variante oder ABI aus dem Listenfeld aus. Es wird automatisch eine neue Synchronisierung ausgeführt.

Wenn Sie eine der Spalten für eine Anwendung oder ein Bibliotheksmodul ändern, wird die Änderung auf alle abhängigen Zeilen angewendet.

Versionsverwaltung konfigurieren

Wenn Gradle mehrere APKs generiert, hat jedes APK standardmäßig die gleichen Versionsinformationen, wie in der Datei build.gradle oder build.gradle.kts auf Modulebene angegeben. Da im Google Play Store nicht mehrere APKs für dieselbe App zulässig sind, die alle dieselben Versionsinformationen haben, muss jedes APK vor dem Upload in den Play Store einen eindeutigen versionCode haben.

Du kannst die Datei build.gradle auf Modulebene so konfigurieren, dass versionCode für jedes APK überschrieben wird. Wenn du eine Zuordnung erstellst, die jeder ABI und jeder Dichte, für die du mehrere APKs konfigurierst, einen eindeutigen numerischen Wert zuweist, kannst du den Ausgabeversionscode mit einem Wert überschreiben, der den im defaultConfig- oder productFlavors-Block definierten Versionscode mit dem numerischen Wert kombiniert, der der Dichte oder dem ABI zugewiesen ist.

Im folgenden Beispiel erhält das APK für das x86 ABI einen versionCode von 2004 und das x86_64 ABI einen Wert für versionCode von 3.004.

Wenn du Versionscodes in großen Schritten (z. B. 1.000) zuweist, kannst du später eindeutige Versionscodes zuweisen, wenn du deine App aktualisieren musst. Wenn defaultConfig.versionCode bei einem nachfolgenden Update beispielsweise zu 5 wird, weist Gradle dem APK x86 den Wert 2005 und dem APK x86_64 den Wert 3005 zu.versionCode

Tipp:Wenn dein Build ein universelles APK enthält, weise ihm eine versionCode zu, die niedriger ist als die deiner anderen APKs. Da der Google Play Store die Version deiner App installiert, die sowohl mit dem Zielgerät kompatibel ist als auch die höchste versionCode hat, wird durch die Zuweisung einer niedrigeren versionCode zum universellen APK sichergestellt, dass der Google Play Store versucht, eines deiner APKs zu installieren, bevor auf das universelle APK zurückgreift. Im folgenden Beispielcode wird die Standard-versionCode eines universellen APK nicht überschrieben.

Groovig

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

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

Weitere Beispiele für alternative Versionscodeschemas finden Sie unter Versionscodes zuweisen.

Mehrere APKs erstellen

Nachdem Sie die Datei build.gradle oder build.gradle.kts auf Modulebene so konfiguriert haben, dass mehrere APKs erstellt werden, klicken Sie auf Erstellen > APK erstellen, um alle APKs für das aktuell ausgewählte Modul im Bereich Projekt zu erstellen. Gradle erstellt die APKs für jede Dichte oder jedes ABI im build/outputs/apk/-Verzeichnis des Projekts.

Gradle erstellt ein APK für jede Dichte oder ABI, für die Sie mehrere APKs konfigurieren. Wenn Sie mehrere APKs für sowohl Dichten als auch ABIs aktivieren, erstellt Gradle ein APK für jede Kombination aus Dichte und ABI.

Mit dem folgenden build.gradle-Snippet können beispielsweise mehrere APKs für die Dichten mdpi und hdpi sowie auch die ABIs x86 und x86_64 erstellt werden:

Groovig

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

Kotlin

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

Die Ausgabe der Beispielkonfiguration enthält die folgenden vier APKs:

  • app-hdpiX86-release.apk: Enthält Code und Ressourcen für hdpi-Dichte und x86-ABI.
  • app-hdpiX86_64-release.apk: Enthält Code und Ressourcen für hdpi-Dichte und x86_64-ABI.
  • app-mdpiX86-release.apk: Enthält Code und Ressourcen für mdpi-Dichte und x86-ABI.
  • app-mdpiX86_64-release.apk: Enthält Code und Ressourcen für mdpi-Dichte und x86_64-ABI.

Wenn Sie mehrere APKs basierend auf der Bildschirmdichte erstellen, generiert Gradle immer ein universelles APK, das neben den APKs pro Punktdichte Code und Ressourcen für alle Dichten enthält.

Wenn Sie mehrere APKs auf Basis von ABI erstellen, generiert Gradle nur dann ein APK, das Code und Ressourcen für alle ABIs enthält, wenn Sie universalApk true im splits.abi-Block in Ihrer build.gradle-Datei (für Groovy) oder isUniversalApk = true im splits.abi-Block in Ihrer build.gradle.kts-Datei (für Kotlin-Script) angeben.

Format des APK-Dateinamens

Wenn Sie mehrere APKs erstellen, generiert Gradle APK-Dateinamen nach dem folgenden Schema:

modulename-screendensityABI-buildvariant.apk

Die Schemakomponenten sind:

modulename
Gibt den Namen des zu erstellenden Moduls an.
screendensity
Wenn mehrere APKs für die Bildschirmdichte aktiviert sind, wird die Bildschirmdichte für das APK angegeben, z. B. mdpi.
ABI

Wenn mehrere APKs für ABI aktiviert sind, gib die ABI für das APK an, z. B. x86.

Wenn mehrere APKs sowohl für die Bildschirmdichte als auch für ABI aktiviert sind, verkettet Gradle den Dichtenamen mit dem ABI-Namen, z. B. mdpiX86. Wenn universalApk für APKs auf ABI-Basis aktiviert ist, verwendet Gradle universal als ABI-Teil des universellen APK-Dateinamens.

buildvariant
Gibt die zu erstellende Build-Variante an, z. B. debug.

Wenn du beispielsweise das APK-APK mdpi für die Debug-Version von „myApp“ erstellst, lautet der APK-Dateiname myApp-mdpi-debug.apk. Die Release-Version von myApp, die so konfiguriert ist, dass mehrere APKs für die Bildschirmdichte mdpi und das ABI x86 erstellt werden, hat den APK-Dateinamen myApp-mdpiX86-release.apk.