Birden fazla APK oluşturma

Dikkat: Ağustos 2021'den itibaren tüm yeni uygulamalar App Bundle olarak yayınlanmalıdır. Uygulamanızı Google Play'de yayınlarsanız bir Android App Bundle oluşturup yükleyin. Bunu yaptığınızda, Google Play her kullanıcının cihaz yapılandırmasına göre optimize edilmiş APK'ları otomatik olarak oluşturup yayınlar. Böylece kullanıcılar yalnızca uygulamanızı çalıştırmak için gereken kod ve kaynakları indirir. Birden fazla APK yayınlamak, AAB biçimini desteklemeyen bir mağazada yayınlıyorsanız yararlıdır. Bu durumda, her APK'yı kendiniz oluşturmanız, imzalamanız ve yönetmeniz gerekir.

Mümkün olduğunda tüm hedef cihazlarınızı destekleyecek şekilde tek bir APK oluşturmak daha iyi olsa da bu durum, birden fazla ekran yoğunluğunu veya Uygulama İkili Arabirimini (ABI'ler) destekleyen dosyalar nedeniyle çok büyük bir APK'ya neden olabilir. APK'nızın boyutunu küçültmenin bir yolu, belirli ekran yoğunluklarına veya ABI'lere yönelik dosyalar içeren birden fazla APK oluşturmaktır.

Gradle, yalnızca her yoğunluğa veya ABI'ye özgü 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 ekran yoğunluğuna veya ABI'ye dayalı olmayan farklı sürümlerini oluşturmanız gerekiyorsa bunun yerine varyantları oluşturma özelliğini 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 bloku içinde, Gradle'ın yoğunluk başına APK'ları nasıl oluşturmasını istediğinizi belirten bir density bloğu veya Gradle'ın ABI başına APK'ları nasıl oluşturmasını istediğinizi belirten bir abi bloğu sağlayın. Hem yoğunluk hem de ABI blokları sağlayabilirsiniz. Derleme sistemi, her yoğunluk ve ABI kombinasyonu için bir APK oluşturur.

Ekran yoğunlukları için birden fazla APK yapılandırma

Farklı ekran yoğunluklarına yönelik ayrı APK'lar oluşturmak için splits blokunuzun içine bir density bloğu ekleyin. density blokunuzda, istediğiniz ekran yoğunluklarının ve uyumlu ekran boyutlarının listesini sağlayın. Uyumlu ekran boyutları listesini yalnızca her bir APK'nın manifest dosyasında belirli <compatible-screens> öğelerine ihtiyacınız varsa kullanın.

Aşağıdaki Gradle DSL seçenekleri, ekran yoğunluklarına göre birden fazla APK'yı yapılandırmak için kullanılır:

Groovy için enable, Kotlin komut dosyası için isEnable
Bu öğeyi true olarak ayarlarsanız Gradle, tanımladığınız ekran yoğunluklarına göre birden fazla APK oluşturur. false, varsayılan değerdir.
exclude
Gradle'ın ayrı APK'lar oluşturmasını istemediğiniz yoğunlukların virgülle ayrılmış listesini belirtir. Çoğu yoğunluk için APK oluşturmak istiyor ancak uygulamanızın desteklemediği birkaç yoğunluğu hariç tutmanız gerekiyorsa exclude politikasını kullanın.
reset()

Varsayılan ekran yoğunlukları listesini temizler. Yalnızca eklemek istediğiniz yoğunlukları belirtmek için include öğesiyle birleştirildiğinde kullanın.

Aşağıdaki snippet, listeyi temizlemek için reset() çağrısını yaptıktan sonra include kullanarak yoğunluk listesini yalnızca ldpi ve xxhdpi olarak ayarlar:

reset()                  // Clears the default list from all densities
                         // to no densities.
include "ldpi", "xxhdpi" // Specifies the two densities to generate APKs
                         // for.
include
Gradle'ın APK'lar oluşturmasını istediğiniz yoğunlukların virgülle ayrılmış listesini belirtir. Yalnızca tam bir yoğunluk listesi belirtmek için reset() ile birlikte kullanın.
compatibleScreens

Uyumlu ekran boyutlarının virgülle ayrılmış listesini belirtir. Bu işlem, her APK için manifest dosyasına eşleşen bir <compatible-screens> düğümü ekler.

Bu ayar, aynı build.gradle bölümünde hem ekran yoğunluklarını hem de ekran boyutlarını yönetmenin kullanışlı bir yolunu sunar. Ancak <compatible-screens> kullanmak, uygulamanızın çalıştığı cihaz türlerini sınırlayabilir. Farklı ekran boyutlarını desteklemenin alternatif yolları için ekran uyumluluğuna genel bakış konusuna bakın.

Ekran yoğunluğuna dayalı her APK, birden fazla APK yayınlasanız bile APK'nın desteklediği ekran türleriyle ilgili belirli kısıtlamalara sahip bir <compatible-screens> etiketi içerdiğinden, bazı yeni cihazlar birden fazla APK filtrenizle eşleşmez. Bu nedenle, Gradle her zaman tüm ekran yoğunluklarına yönelik öğeleri içeren ve <compatible-screens> etiketi içermeyen ek bir evrensel APK oluşturur. <compatible-screens> etiketiyle eşleşmeyen cihazlar için yedek sağlamak amacıyla bu evrensel APK'yı yoğunluk başına APK'larınızla birlikte yayınlayın.

Aşağıdaki örnekte ldpi, xxhdpi ve xxxhdpi dışındaki her bir ekran yoğunluğu için ayrı bir APK oluşturulur. Bu işlem, bu üç yoğunluğun varsayılan tüm yoğunluklar listesinden kaldırılması için exclude kullanılarak yapılır.

Modern

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

Yoğunluk ve ekran boyutu adlarının bir listesi için Farklı ekran boyutlarını destekleme sayfasını inceleyin. Uygulamanızın farklı derleme varyantlarını belirli ekran türlerine ve cihazlara göre özelleştirme hakkında daha fazla bilgi için Kısıtlanmış ekran desteği beyan etme bölümüne bakın.

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

Farklı ABI'ler için ayrı APK'lar oluşturmak isterseniz splits blokunuzun içine bir abi bloğu ekleyin. abi blokunuzda, istenen ABI'lerin listesini sağlayın.

Aşağıdaki Gradle DSL seçenekleri, ABI başına birden fazla APK'yı 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 dayanarak 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 istiyorsanız ancak uygulamanızın desteklemediği birkaç ABI'yi hariç tutmanız gerekiyorsa exclude politikasını kullanın.
reset()

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

Aşağıdaki snippet, listeyi temizlemek için reset() çağrısını yaptıktan sonra include 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 listesini 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'ler için kod ve kaynak içerir. Varsayılan değer: false.

Bu seçeneğin yalnızca splits.abi blokunda kullanılabildiğini unutmayın. Ekran yoğunluğuna dayalı birden fazla APK oluştururken Gradle her zaman tüm ekran yoğunlukları için kod ve kaynaklar içeren evrensel bir APK oluşturur.

Aşağıdaki örnek, her ABI için ayrı bir APK oluşturur: x86 ve x86_64. Bu, boş bir ABI listesiyle başlamak için reset() ve ardından her biri bir APK alan ABI'lerin listesiyle birlikte include öğesi kullanılarak yapılır.

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 konusuna bakın.

Yerel/C++ kodu olmayan projeler

Yerel/C++ kodu olmayan projeler için Varyantları Derleme panelinde iki sütun bulunur: Şekil 1'de gösterildiği gibi Modül ve Etkin Derleme Varyantı.

Varyant oluşturma paneli
Şekil 1. Derleme Varyantları panelinde yerel/C++ kodu olmayan projeler için iki sütun bulunur.

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

Yerel/C++ kodu olan projeler

Yerel/C++ kodu olan projeler için Varyant Oluşturma panelinde üç sütun bulunur: Şekil 2'de gösterildiği gibi Modül, Etkin Derleme Varyantı ve Etkin ABI.

Şekil 2. Varyantları Derleme paneli, yerel/C++ kodu olan projeler için Etkin ABI sütununu ekler.

Modülün Aktif Derleme Varyantı değeri, dağıtılan ve düzenleyicide görünen derleme varyantını belirler. Yerel modüller için Etkin ABI değeri, düzenleyicinin kullandığı ABI'yi belirler ancak dağıtılan öğeyi etkilemez.

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

  1. Etkin Derleme Varyantı veya Etkin ABI sütunuyla ilgili hücreyi tıklayın.
  2. Liste alanından istediğiniz varyantı veya ABI'yi seçin. Otomatik olarak yeni bir senkronizasyon çalıştırılır.

Bir uygulama veya kitaplık modülü için sütunlardan birinin değiştirilmesi, değişikliği tüm bağımlı satırlara uygular.

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 belirtilenle aynı sürüm bilgilerine sahip olur. Google Play Store, aynı uygulama için hepsi aynı sürüm bilgisine sahip olan 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 bir APK için versionCode kodunu geçersiz kılacak şekilde yapılandırabilirsiniz. Birden fazla APK yapılandırdığınız her ABI ve yoğunluk 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 yoğunluğa veya 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 2004 versionCode ve x86_64 ABI 3004 versionCode almaktadır.

Sürüm kodlarını 1000 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, defaultConfig.versionCode sonraki bir güncellemede 5'e yinelenirse Gradle, x86 APK'sına versionCode ve x86_64 APK'sına 3005 versionCode atar.

İpucu: Yapınız evrensel bir APK içeriyorsa buna diğer APK'larınızınkinden daha düşük bir versionCode atayın. Google Play Store, uygulamanızın hem hedef cihazla uyumlu hem de en yüksek versionCode değerine sahip sürümünü yüklediğinden, evrensel APK'ya daha düşük bir versionCode atamak, Google Play Store'un evrensel APK'ya geri dönmeden önce APK'larınızdan birini yüklemeyi denemesini sağlar. Aşağıdaki örnek kod, bunu evrensel bir APK'nın varsayılan versionCode değerini geçersiz kılmadan yapar.

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]

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

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

Birden fazla APK oluşturma

Birden fazla APK oluşturmak için modül düzeyindeki build.gradle veya build.gradle.kts dosyanızı yapılandırdıktan sonra Proje bölmesinde seçili olan modülle ilgili tüm APK'ları oluşturmak için Oluştur > APK Derle'yi tıklayın. Gradle, projenin build/outputs/apk/ dizininde her yoğunluk veya ABI için APK'lar oluşturur.

Gradle, birden fazla APK yapılandırdığınız her yoğunluk veya ABI için bir APK oluşturur. Hem yoğunluklar hem de ABI'ler için birden fazla APK'yı etkinleştirirseniz Gradle, her yoğunluk ve ABI kombinasyonu için bir APK oluşturur.

Örneğin, aşağıdaki build.gradle snippet'i mdpi ve hdpi yoğunluklarının yanı sıra x86 ve x86_64 ABI'leri için birden fazla APK oluşturmayı sağlar:

Modern

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

Örnek yapılandırmadan elde edilen çıkış aşağıdaki 4 APK'yı içerir:

  • app-hdpiX86-release.apk: hdpi yoğunluk ve x86 ABI için kod ve kaynaklar içerir.
  • app-hdpiX86_64-release.apk: hdpi yoğunluk ve x86_64 ABI için kod ve kaynaklar içerir.
  • app-mdpiX86-release.apk: mdpi yoğunluk ve x86 ABI için kod ve kaynaklar içerir.
  • app-mdpiX86_64-release.apk: mdpi yoğunluk ve x86_64 ABI için kod ve kaynaklar içerir.

Gradle, ekran yoğunluğuna dayalı birden fazla APK oluştururken her zaman, yoğunluk başına APK'ların yanı sıra tüm yoğunluklar için kod ve kaynaklar içeren evrensel bir APK oluşturur.

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

APK dosya adı biçimi

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

modulename-screendensityABI-buildvariant.apk

Şema bileşenleri şunlardır:

modulename
Oluşturulan modül adını belirtir.
screendensity
Ekran yoğunluğu için birden fazla APK etkinse APK için ekran yoğunluğunu belirtir (ör. mdpi).
ABI

ABI için birden fazla APK etkinse APK için x86 gibi ABI'yı belirtir.

Hem ekran yoğunluğu hem de ABI için birden fazla APK etkinleştirilirse Gradle, yoğunluk adını ABI adıyla birleştirir (örneğin, mdpiX86). universalApk, ABI başına APK'lar için etkinleştirilirse Gradle, evrensel APK dosya adının ABI kısmı olarak universal kodunu kullanır.

buildvariant
Oluşturulmakta olan derleme varyantını belirtir (ör. debug).

Örneğin, myApp'in hata ayıklama sürümü için mdpi ekran yoğunluğu APK'sı oluştururken APK'nın dosya adı myApp-mdpi-debug.apk olur. myApp'in hem mdpi ekran yoğunluğu hem de x86 ABI için birden fazla APK oluşturacak şekilde yapılandırılmış sürüm sürümünün APK dosya adı myApp-mdpiX86-release.apk şeklindedir.