Mehrere APKs erstellen

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

Es ist zwar besser, nach Möglichkeit ein einzelnes APK zu erstellen, das alle Zielgeräte unterstützt. Das kann jedoch zu einem sehr großen APK führen, da Dateien mehrere Bildschirmdichten oder Application Binary Interfaces (ABIs) unterstützen. Eine Möglichkeit, die Größe Ihres APK 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 enthalten, die für jede Dichte oder jedes ABI spezifisch sind. Auf dieser Seite wird beschrieben, wie Sie Ihren Build so konfigurieren, dass mehrere APKs generiert werden. Wenn Sie verschiedene Versionen Ihrer App erstellen möchten, die nicht auf Bildschirmdichte oder ABI basieren, verwenden Sie stattdessen Build-Varianten.

Build für mehrere APKs konfigurieren

Wenn Sie Ihren Build für mehrere APKs konfigurieren möchten, fügen Sie der Datei build.gradle auf Modulebene den Block splits hinzu. Geben Sie innerhalb des splits-Blocks einen density-Block an, in dem angegeben ist, wie Gradle APKs pro Dichte generieren soll, oder einen abi-Block, in dem angegeben ist, wie Gradle APKs pro ABI generieren soll. Sie können sowohl Dichte- als auch ABI-Blöcke angeben. Das Build-System erstellt dann ein APK für jede Kombination aus Dichte und ABI.

Mehrere APKs für Bildschirmdichten konfigurieren

Wenn Sie separate APKs für verschiedene Bildschirmdichten erstellen möchten, fügen Sie einen density-Block in den splits-Block ein. Geben Sie in Ihrem density-Block eine Liste der gewünschten Bildschirmdichten und kompatiblen Bildschirmgrößen an. Verwenden Sie die Liste der kompatiblen Bildschirmgrößen nur, wenn Sie bestimmte <compatible-screens>-Elemente im Manifest jedes APKs benötigen.

Mit den folgenden Gradle-DSL-Optionen können Sie mehrere APKs für Bildschirmdichten konfigurieren:

enable für Groovy-, isEnable für Kotlin-Script
Wenn Sie dieses Element auf true festlegen, generiert Gradle mehrere APKs basierend auf den von Ihnen definierten Bildschirmdichten. Der Standardwert ist false.
exclude
Eine durch Kommas getrennte Liste von Dichten, für die Gradle keine separaten APKs generieren soll. Verwenden Sie exclude, wenn Sie APKs für die meisten Dichten generieren, aber einige Dichten ausschließen möchten, die von Ihrer App nicht unterstützt werden.
reset()

Die Standardliste der Bildschirmdichten wird gelöscht. Verwenden Sie dieses Element nur in Kombination mit dem include-Element, um die Dichten anzugeben, die Sie hinzufügen möchten.

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

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. Verwenden Sie diese Option nur in Kombination mit reset(), 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 passender <compatible-screens>-Knoten in das Manifest eingefügt.

Mit dieser Einstellung können Sie sowohl die Bildschirmdichte als auch die Bildschirmgröße im selben Bereich build.gradle verwalten. Die Verwendung von <compatible-screens> kann jedoch die Gerätetypen einschränken, mit denen Ihre App funktioniert. Alternative Möglichkeiten 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 bestimmten Einschränkungen zu den Bildschirmtypen enthält, die das APK unterstützt, stimmen einige neue Geräte nicht mit Ihren Filtern für mehrere APKs überein – auch wenn Sie mehrere APKs veröffentlichen. Daher generiert Gradle immer ein zusätzliches universelles APK, das Assets für alle Bildschirmdichten enthält und kein <compatible-screens>-Tag enthält. Veröffentlichen Sie dieses universelle APK zusammen mit Ihren APKs für die einzelnen Dichten, um einen Fallback für Geräte bereitzustellen, die nicht mit den APKs mit einem <compatible-screens>-Tag übereinstimmen.

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

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

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

Weitere Informationen zum Anpassen verschiedener Buildvarianten Ihrer App an bestimmte Bildschirmtypen und Geräte finden Sie unter Unterstützung für eingeschränkte Bildschirme angeben.

Mehrere APKs für ABIs konfigurieren

Wenn Sie separate APKs für verschiedene ABIs erstellen möchten, fügen Sie einen abi-Block in den splits-Block ein. Geben Sie in Ihrem abi-Block eine Liste der gewünschten ABIs an.

Mit den folgenden Gradle DSL-Optionen können Sie mehrere APKs pro ABI konfigurieren:

enable für Groovy oder isEnable für Kotlin-Script
Wenn Sie dieses Element auf true festlegen, generiert Gradle mehrere APKs basierend auf den von Ihnen definierten ABIs. Der Standardwert ist false.
exclude
Eine durch Kommas getrennte Liste von ABIs, für die Gradle keine separaten APKs generieren soll. Verwenden Sie exclude, wenn Sie APKs für die meisten ABIs generieren, aber einige ABIs ausschließen möchten, die von Ihrer App nicht unterstützt werden.
reset()

Die Standardliste der ABIs wird gelöscht. Verwenden Sie dieses Element nur in Kombination mit dem include-Element, um die ABIs anzugeben, die Sie hinzufügen möchten.

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

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. Verwenden Sie diese Option nur in Kombination mit reset(), um eine genaue Liste von ABIs anzugeben.
universalApk für Groovy oder isUniversalApk für Kotlin-Script

Wenn true festgelegt ist, generiert Gradle zusätzlich zu den ABI-spezifischen APKs ein universelles APK. 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 Block splits.abi 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 jedes ABI ein separates APK generiert: x86 und x86_64. Dazu verwenden Sie reset(), um mit einer leeren Liste von ABIs zu beginnen, gefolgt von include mit einer Liste von ABIs, die jeweils ein APK erhalten.

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

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 finden Sie unter Unterstützte ABIs.

Projekte ohne nativen/C++-Code

Bei Projekten ohne nativen/C++-Code enthält der Bereich Build-Varianten zwei Spalten: Modul und Aktive Build-Variante, wie in Abbildung 1 dargestellt.

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

Der Wert Active Build Variant (Aktive Build-Variante) für das Modul bestimmt die Build-Variante, die bereitgestellt und im Editor angezeigt wird. Wenn Sie zwischen Varianten wechseln möchten, klicken Sie auf die Zelle Aktive Build-Variante für ein Modul 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-Varianten drei Spalten: Modul, Aktive Build-Variante und Aktives ABI, wie in Abbildung 2 dargestellt.

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

Der Wert Active Build Variant (Aktive Build-Variante) für das Modul bestimmt die Build-Variante, die bereitgestellt und im Editor angezeigt wird. Bei nativen Modulen bestimmt der Wert Active ABI das ABI, das der Editor verwendet. Er hat jedoch keine Auswirkungen auf die Bereitstellung.

So ändern Sie den Buildtyp oder ABI:

  1. Klicken Sie auf die Zelle für die Spalte Active Build Variant (Aktive Build-Variante) oder Active ABI (Aktive 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 ein App- oder Bibliotheksmodul ändern, wird die Änderung auf alle abhängigen Zeilen angewendet.

Versionierung konfigurieren

Wenn Gradle mehrere APKs generiert, haben diese standardmäßig dieselben Versionsinformationen, wie in der build.gradle- oder build.gradle.kts-Datei auf Modulebene angegeben. Da im Google Play Store keine mehrere APKs für dieselbe App mit denselben Versionsinformationen zulässig sind, muss jedes APK vor dem Hochladen in den Play Store eine eindeutige versionCode haben.

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

Im folgenden Beispiel erhält die APK für die x86 ABI die versionCode 2004 und die x86_64 ABI die versionCode 3004.

Wenn Sie Versionscodes in großen Schritten wie 1.000 zuweisen, können Sie später eindeutige Versionscodes zuweisen, wenn Sie Ihre App aktualisieren müssen. Wenn defaultConfig.versionCode beispielsweise bei einem nachfolgenden Update auf 5 iteriert, weist Gradle dem x86 APK den versionCode 2005 und dem x86_64 APK den versionCode 3005 zu.

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

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

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 Versionscode-Schemata finden Sie unter Versionscodes zuweisen.

Mehrere APKs erstellen

Nachdem Sie die build.gradle- oder build.gradle.kts-Datei auf Modulebene für das Erstellen mehrerer APKs konfiguriert haben, klicken Sie auf Build > 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 Verzeichnis build/outputs/apk/ des Projekts.

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

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

Groovy

...
  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 die hdpi-Dichte und das x86-ABI.
  • app-hdpiX86_64-release.apk: Enthält Code und Ressourcen für die hdpi-Dichte und das x86_64-ABI.
  • app-mdpiX86-release.apk: Enthält Code und Ressourcen für die mdpi-Dichte und das x86-ABI.
  • app-mdpiX86_64-release.apk: Enthält Code und Ressourcen für die mdpi-Dichte und das x86_64-ABI.

Wenn Sie mehrere APKs basierend auf der Bildschirmdichte erstellen, generiert Gradle zusätzlich zu den APKs für jede Dichte immer ein universelles APK, das Code und Ressourcen für alle Dichten enthält.

Wenn Sie mehrere APKs basierend auf dem ABI erstellen, generiert Gradle nur ein APK mit Code und Ressourcen für alle ABIs, wenn Sie in der Datei build.gradle (für Groovy) im Block splits.abi die Zeichenfolge universalApk true oder in der Datei build.gradle.kts (für Kotlin-Script) im Block splits.abi die Zeichenfolge isUniversalApk = true 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, gibt dies die Bildschirmdichte für das APK an, z. B. mdpi.
ABI

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

Wenn mehrere APKs sowohl für die Bildschirmdichte als auch für das ABI aktiviert sind, verknüpft Gradle den Namen der Dichte mit dem Namen des ABI, z. B. mdpiX86. Wenn universalApk für ABI-spezifische APKs aktiviert ist, verwendet Gradle universal als ABI-Teil des Dateinamens des universellen APKs.

buildvariant
Gibt die Buildvariante an, die erstellt wird, z. B. debug.

Wenn Sie beispielsweise ein APK mit einer Bildschirmdichte von mdpi für die Debugversion von „myApp“ erstellen, lautet der APK-Dateiname myApp-mdpi-debug.apk. Die Releaseversion von „myApp“, die so konfiguriert ist, dass mehrere APKs sowohl für die Bildschirmdichte mdpi als auch für das ABI x86 erstellt werden, hat die APK-Dateinamen myApp-mdpiX86-release.apk.