Birden fazla APK oluşturma

Mümkün olduğunda tüm hedef cihazlarınızı desteklemek için tek bir APK oluşturmak daha iyi olsa da birden fazla Uygulama İkili Arabirimi'ni (ABI) destekleyen dosyalar nedeniyle çok büyük bir APK elde edebilirsiniz. APK'nızın boyutunu küçültmenin bir yolu, belirli ABI'ler için dosyalar içeren birden fazla APK oluşturmaktır.

Gradle, yalnızca her ABI'ye özel kod ve kaynaklar içeren ayrı APK'lar oluşturabilir. Bu sayfada, derlemenizi birden fazla APK oluşturacak şekilde nasıl yapılandıracağınız açıklanmaktadır. Uygulamanızın ABI'ye dayalı olmayan farklı sürümlerini oluşturmanız gerekiyorsa bunun yerine derleme değişkenlerini kullanın.

Derlemenizi birden fazla APK için yapılandırma

Derlemenizi birden fazla APK için yapılandırmak üzere modül düzeyindeki build.gradle dosyanıza bir splits bloğu ekleyin. splits bloğunda, Gradle'ın ABI başına APK'ları nasıl oluşturmasını istediğinizi belirten bir abi bloğu sağlayın.

ABI'ler için birden fazla APK yapılandırma

Farklı ABI'ler için ayrı APK'lar oluşturmak istiyorsanız splits bloğunuzun içine bir abi bloğu ekleyin. abi bloğunuzda, seçtiğiniz ABI'lerin listesini sağlayın.

Aşağıdaki Gradle DSL seçenekleri, ABI başına birden fazla APK yapılandırmak için kullanılır:

Groovy için enable veya Kotlin komut dosyası için isEnable
Bu öğeyi true olarak ayarlarsanız Gradle, tanımladığınız ABI'lere göre birden fazla APK oluşturur. Varsayılan değer: false.
exclude
Gradle'ın ayrı APK'lar oluşturmasını istemediğiniz ABI'lerin virgülle ayrılmış listesini belirtir. Çoğu ABI için APK oluşturmak istiyor ancak uygulamanızın desteklemediği birkaç ABI'yi hariç tutmanız gerekiyorsa exclude kullanın.
reset()

Varsayılan ABI listesini temizler. Yalnızca eklemek istediğiniz ABI'leri belirtmek için include öğesiyle birlikte kullanın.

Aşağıdaki snippet, listeyi temizlemek için reset() yöntemini çağırıp ardından include yöntemini kullanarak ABI listesini yalnızca x86 ve x86_64 olarak ayarlar:

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

Gradle'ın APK oluşturmasını istediğiniz ABI'lerin virgülle ayrılmış listesini belirtir. Yalnızca tam bir ABI listesi belirtmek için reset() ile birlikte kullanın.

Groovy için universalApk veya Kotlin komut dosyası için isUniversalApk

true ise Gradle, ABI başına APK'lara ek olarak evrensel bir APK oluşturur. Evrensel APK, tek bir APK'da tüm ABI'lar için kod ve kaynaklar içerir. Varsayılan değer: false.

Aşağıdaki örnekte her ABI için ayrı bir APK oluşturulur: x86 ve x86_64. Bunu yapmak için reset() kullanarak boş bir ABI listesiyle başlayın ve ardından her biri bir APK alan ABI listesiyle include kullanın.

Modern

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

Desteklenen ABI'lerin listesi için Desteklenen ABI'ler başlıklı makaleyi inceleyin.

Yerel/C++ kodu içermeyen projeler

Yerel/C++ kodu olmayan projelerde Build Variants (Derleme Değişkenleri) panelinde iki sütun bulunur: Şekil 1'de gösterildiği gibi Module (Modül) ve Active Build Variant (Etkin Derleme Değişkeni).

Derleme Değişkenleri panelinde yerel/C++ kodu olmayan projeler için iki sütun bulunur.
Şekil 1. Derleme Değişkenleri panelinde yerel/C++ kodu içermeyen projeler için iki sütun bulunur.

Modülün Etkin Derleme Varyantı değeri, dağıtılan ve düzenleyicide görünen derleme değişkenini belirler. Varyantlar arasında geçiş yapmak için bir modülün Etkin Derleme Değişkeni hücresini tıklayın ve liste alanından seçtiğiniz varyantı belirleyin.

Yerel/C++ kodu içeren projeler

Yerel/C++ kodu içeren projelerde Derleme Değişkenleri panelinde üç sütun bulunur: Şekil 2'de gösterildiği gibi Modül, Etkin Derleme Değişkeni ve Etkin ABI.

Derleme Değişkenleri paneli, yerel/C++ kodu içeren projeler için Etkin ABI sütununu ekler.
Şekil 2. Derleme Değişkenleri paneli, yerel/C++ kodu içeren projeler için Etkin ABI sütununu ekler.

Modülün Etkin Derleme Değişkeni değeri, dağıtılan ve düzenleyicide görünen derleme değişkenini belirler. Yerel modüllerde Etkin ABI değeri, düzenleyicinin kullandığı ABI'yi belirler ancak dağıtılanları etkilemez.

Derleme türünü veya ABI'yi değiştirmek için:

  1. Etkin Derleme Değişkeni veya Etkin ABI sütununun hücresini tıklayın.
  2. Liste alanından seçtiğiniz varyantı veya ABI'yi seçin. Yeni bir senkronizasyon otomatik olarak çalışır.

Bir uygulama veya kitaplık modülü için sütunlardan birini değiştirdiğinizde değişiklik tüm bağımlı satırlara uygulanır.

Sürüm oluşturmayı yapılandırma

Varsayılan olarak, Gradle birden fazla APK oluşturduğunda her APK, modül düzeyindeki build.gradle veya build.gradle.kts dosyasında belirtilen sürüm bilgilerine sahip olur. Google Play Store, aynı uygulama için aynı sürüm bilgilerine sahip birden fazla APK'ya izin vermediğinden, Play Store'a yüklemeden önce her APK'nın benzersiz bir versionCode değerine sahip olduğundan emin olmanız gerekir.

Modül düzeyindeki build.gradle dosyanızı, her APK için versionCode değerini geçersiz kılacak şekilde yapılandırabilirsiniz. Birden fazla APK yapılandırdığınız her ABI için benzersiz bir sayısal değer atayan bir eşleme oluşturarak çıkış sürüm kodunu, defaultConfig veya productFlavors bloğunda tanımlanan sürüm kodunu ABI'ye atanan sayısal değerle birleştiren bir değerle geçersiz kılabilirsiniz.

Aşağıdaki örnekte, x86 ABI için APK'nın versionCode değeri 2004, x86_64 ABI için APK'nın versionCode değeri 3004'tür.

Sürüm kodlarını 1.000 gibi büyük artışlarla atamak, uygulamanızı güncellemeniz gerektiğinde daha sonra benzersiz sürüm kodları atamanıza olanak tanır. Örneğin, sonraki bir güncellemede defaultConfig.versionCode 5'e yükselirse Gradle, x86 APK'ya 2005, x86_64 APK'ya ise 3005 versionCode atar.

Modern

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]

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)

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

Alternatif sürüm kodu şemalarıyla ilgili daha fazla örnek için Sürüm kodları atama bölümüne bakın.

Birden fazla APK oluşturma

Modül düzeyindeki build.gradle veya build.gradle.kts dosyanızı birden fazla APK oluşturacak şekilde yapılandırdıktan sonra Derle > APK Derle'yi tıklayarak Proje bölmesinde seçili olan modül için tüm APK'ları derleyin. Gradle, projenin build/outputs/apk/ dizininde her ABI için APK'lar oluşturur.

Gradle, birden fazla APK yapılandırdığınız her ABI için bir APK oluşturur.

Örneğin, aşağıdaki build.gradle snippet'i x86 ve x86_64 ABI'leri için birden fazla APK oluşturulmasını sağlar:

Modern

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

Kotlin

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

Örnek yapılandırmanın çıkışı aşağıdaki 4 APK'yı içerir:

  • app-X86-release.apk: x86 ABI için kod ve kaynaklar içerir.
  • app-X86_64-release.apk: x86_64 ABI için kod ve kaynaklar içerir.

ABI'ye dayalı birden fazla APK oluştururken Gradle, yalnızca build.gradle dosyanızdaki (Groovy için) splits.abi bloğunda universalApk true veya build.gradle.kts dosyanızdaki (Kotlin komut dosyası için) splits.abi bloğunda isUniversalApk = true değerini belirtirseniz tüm ABI'ler için kod ve kaynaklar içeren bir APK oluşturur.

APK dosya adı biçimi

Gradle, birden fazla APK oluştururken APK dosya adlarını aşağıdaki şemayı kullanarak oluşturur:

modulename-ABI-buildvariant.apk

Şema bileşenleri şunlardır:

modulename
Derlenen modülün adını belirtir.
ABI
ABI için birden fazla APK etkinleştirilmişse APK'nın ABI'sini belirtir (ör. x86).
buildvariant
Oluşturulan derleme değişkenini belirtir (ör. debug).