Uygulamanızın minSdk
API düzeyi 20 veya daha düşükse ve uygulamanız ile referans verdiği kitaplıklar 65.536 yöntemi aşıyorsa uygulamanızın Android derleme mimarisinin sınırına ulaştığını belirten aşağıdaki derleme hatasıyla karşılaşırsınız:
trouble writing output: Too many field references: 131000; max is 65536. You may try using --multi-dex option.
Derleme sisteminin eski sürümleri, aynı sorunun göstergesi olan farklı bir hata bildirir:
Conversion to Dalvik format failed: Unable to execute dex: method ID not in [0, 0xffff]: 65536
Bu hata koşullarında ortak bir sayı gösterilir: 65536. Bu sayı, tek bir Dalvik yürütülebilir (DEX) bayt kodu dosyasındaki kod tarafından çağrılabilecek toplam referans sayısını gösterir. Bu sayfada, uygulamanızın birden fazla DEX dosyası oluşturmasına ve okumasına olanak tanıyan multidex olarak bilinen bir uygulama yapılandırmasını etkinleştirerek bu sınırlamayı nasıl aşacağınız açıklanmaktadır.
64 KB referans sınırı hakkında
Android uygulama (APK) dosyaları, uygulamanızı çalıştırmak için kullanılan derlenmiş kodu içeren Dalvik Yürütülebilir (DEX) dosyası biçiminde yürütülebilir bayt kodu dosyaları içerir. Dalvik Yürütülebilir spesifikasyonu, Android çerçeve yöntemleri, kitaplık yöntemleri ve kendi kodunuzdaki yöntemler dahil olmak üzere tek bir DEX dosyasında referans verilebilen toplam yöntem sayısını 65.536 ile sınırlar.
Bilgisayar bilimi bağlamında kilo veya K terimi 1024'ü (veya 2^10) ifade eder. 65.536, 64x1024'e eşit olduğundan bu sınıra _64K referans sınırı_ denir.Android 5.0'den önceki sürümlerde çoklu paket desteği
Platformun Android 5.0 (API düzeyi 21) öncesi sürümleri, uygulama kodunu yürütmek için Dalvik çalışma zamanını kullanır. Dalvik, uygulamaları varsayılan olarak APK başına tek bir classes.dex
bytecode dosyasıyla sınırlar. Bu sınırlamayı aşmak için multidex kitaplığını modül düzeyindeki build.gradle
veya build.gradle.kts
dosyasına ekleyin:
Groovy
dependencies { def multidex_version = "2.0.1" implementation "androidx.multidex:multidex:$multidex_version" }
Kotlin
dependencies { val multidex_version = "2.0.1" implementation("androidx.multidex:multidex:$multidex_version") }
Bu kitaplık, uygulamanızın birincil DEX dosyasının bir parçası olur ve ardından ek DEX dosyalarına ve bu dosyaların içerdiği koda erişimi yönetir. Bu kitaplığın mevcut sürümlerini görüntülemek için multidex sürümlerine bakın.
Daha fazla bilgi için uygulamanızı multidex için yapılandırma ile ilgili bölüme bakın.Android 5.0 ve sonraki sürümler için çoklu paket desteği
Android 5.0 (API düzeyi 21) ve sonraki sürümler, APK dosyalarından birden fazla DEX dosyasının yüklenmesini doğal olarak destekleyen ART adlı bir çalışma zamanı kullanır. ART, uygulama yükleme sırasında ön derleme gerçekleştirir, classesN.dex
dosyalarını tarar ve Android cihaz tarafından yürütülmesi için tek bir OAT dosyasında derler. Bu nedenle, minSdkVersion
21 veya daha yeni bir sürümse multidex varsayılan olarak etkindir ve multidex kitaplığına ihtiyacınız yoktur.
Android 5.0 çalışma zamanı hakkında daha fazla bilgi edinmek için Android Çalışma Zamanı (ART) ve Dalvik başlıklı makaleyi okuyun.
Not: Uygulamanızı Android Studio'yu kullanarak çalıştırdığınızda derleme, dağıttığınız hedef cihazlar için optimize edilir. Hedef cihazlarda Android 5.0 ve sonraki sürümler çalıştırıldığında çoklu dizin etkinleştirme de buna dahildir. Bu optimizasyon yalnızca uygulamanızı Android Studio kullanılarak dağıtırken uygulandığından, 64 KB sınırını aşmamak için sürüm derlemenizi multidex olarak yapılandırmanız gerekebilir.
64 KB sınırını aşmayın
Uygulamanızı 64K veya daha fazla yöntem referansının kullanılmasını sağlayacak şekilde yapılandırmadan önce, uygulama kodunuz tarafından tanımlanan yöntemler veya dahil edilen kitaplıklar dahil olmak üzere uygulama kodunuz tarafından çağrılan toplam referans sayısını azaltmak için adımlar atın.
Aşağıdaki stratejiler, DEX referans sınırına ulaşmanızı önlemeye yardımcı olabilir:
- Uygulamanızın doğrudan ve geçişli bağımlılıklarını inceleme
- Uygulamanıza dahil ettiğiniz büyük kitaplık bağımlılıklarının değerinin, uygulamaya eklenen kod miktarından daha fazla olup olmadığını düşünün. Birkaç yardımcı program yöntemi yararlı olduğu için çok büyük bir kitaplık eklemek yaygın ancak sorunlu bir uygulamadır. Uygulama kodunuzdaki bağımlılıkları azaltmak genellikle DEX referans sınırını aşmanızı önleyebilir.
- R8 ile kullanılmayan kodları kaldırma
- Sürüm derlemelerinizde R8'i çalıştırmak için kod küçültmeyi etkinleştirin. APK'larınızla kullanılmayan kod göndermediğinizden emin olmak için küçültmeyi etkinleştirin. Kod küçültme doğru şekilde yapılandırılmışsa bağımlılıklarınızdan kullanılmayan kodları ve kaynakları da kaldırabilir.
Bu teknikleri kullanmak, APK'nızın genel boyutunu küçültmenize ve uygulamanızda multidex kullanma ihtiyacını önlemenize yardımcı olabilir.
Uygulamanızı multidex için yapılandırma
Not:minSdkVersion
değeriniz 21 veya daha yüksek bir değere ayarlanmışsa çoklu dex varsayılan olarak etkindir ve çoklu dex kitaplığına ihtiyacınız yoktur.
minSdkVersion
değeriniz 20 veya daha düşükse multidex kitaplığını kullanmanız ve uygulama projenizde aşağıdaki değişiklikleri yapmanız gerekir:
-
Multidex'i etkinleştirmek için modül düzeyindeki
build.gradle
dosyasını değiştirin ve multidex kitaplığını bağımlı bir kaynak olarak ekleyin.Groovy
android { defaultConfig { ... minSdkVersion 15 targetSdkVersion 33 multiDexEnabled true } ... } dependencies { implementation "androidx.multidex:multidex:2.0.1" }
Kotlin
android { defaultConfig { ... minSdk = 15 targetSdk = 33 multiDexEnabled = true } ... } dependencies { implementation("androidx.multidex:multidex:2.0.1") }
Application
sınıfını geçersiz kılmanıza bağlı olarak aşağıdakilerden birini yapın:Application
sınıfını geçersiz kılmıyorsanız manifest dosyanızı düzenleyerek<application>
etiketindekiandroid:name
değerini aşağıdaki gibi ayarlayın:<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapp"> <application android:name="androidx.multidex.MultiDexApplication" > ... </application> </manifest>
Application
sınıfını geçersiz kılarsanız aşağıdaki gibiMultiDexApplication
'u genişletecek şekilde değiştirin:Kotlin
class MyApplication : MultiDexApplication() {...}
Java
public class MyApplication extends MultiDexApplication { ... }
Application
sınıfını geçersiz kılarsanız ancak temel sınıfı değiştirmek mümkün değilse bunun yerineattachBaseContext()
yöntemini geçersiz kılın ve çoklu dizeyi etkinleştirmek içinMultiDex.install(this)
'i çağırın:Kotlin
class MyApplication : SomeOtherApplication() { override fun attachBaseContext(base: Context) { super.attachBaseContext(base) MultiDex.install(this) } }
Java
public class MyApplication extends SomeOtherApplication { @Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); MultiDex.install(this); } }
Dikkat:
MultiDex.install()
tamamlanmadan önceMultiDex.install()
'yi veya başka bir kodu yansıma veya JNI aracılığıyla yürütmeyin. Çoklu Dex izleme bu çağrıları takip etmez. Bu da DEX dosyaları arasındaki sınıf bölümünün bozuk olması nedeniyleClassNotFoundException
veya doğrulama hatalarına neden olur.
Artık uygulamanızı oluşturduğunuzda Android derleme araçları, birincil bir DEX dosyası (classes.dex
) ve gerektiğinde destekleyici DEX dosyaları (classes2.dex
, classes3.dex
vb.) oluşturur.
Derleme sistemi daha sonra tüm DEX dosyalarını APK'nıza paketler.
Çoklu DEX API'leri, çalışma zamanında yalnızca ana classes.dex
dosyasında arama yapmak yerine, yöntemleriniz için mevcut tüm DEX dosyalarında arama yapmak üzere özel bir sınıf yükleyici kullanır.
Multidex kitaplığının sınırlamaları
Multidex kitaplığının bilinen bazı sınırlamaları vardır. Kitaplığı uygulama derleme yapılandırmanıza dahil ederken aşağıdakileri göz önünde bulundurun:
- DEX dosyalarının cihazın veri bölümüne başlatılma sırasında yüklenmesi karmaşık bir işlemdir ve ikincil DEX dosyaları büyükse uygulama yanıt vermiyor (ANR) hatalarına neden olabilir. Bu sorunu önlemek için DEX dosyalarının boyutunu en aza indirmek ve kodun kullanılmayan bölümlerini kaldırmak amacıyla kod küçültmeyi etkinleştirin.
- Android 5.0'den (API düzeyi 21) önceki sürümlerde çalıştırırken, linearalloc sınırını aşmak için multidex kullanmak yeterli değildir (37008143 numaralı sorun). Bu sınır Android 4.0'da (API düzeyi 14) artırıldı ancak sorun tamamen çözülmedi.
Android 4.0'dan önceki sürümlerde, DEX dizini sınırına ulaşmadan önce linearalloc sınırına ulaşabilirsiniz. Bu nedenle, 14'ten düşük API seviyelerini hedefliyorsanız uygulamanızın başlangıçta veya belirli sınıf grupları yüklenirken sorun yaşayabileceğinden platformun bu sürümlerinde kapsamlı bir test yapın.
Kod küçültme, bu sorunları azaltabilir veya tamamen ortadan kaldırabilir.
Birincil DEX dosyasında gerekli sınıfları tanımlama
Derleme araçları, çok DEX'li bir uygulamanın her DEX dosyasını oluştururken birincil DEX dosyasında hangi sınıflara ihtiyaç duyulduğunu belirlemek için karmaşık kararlar alır. Bu sayede uygulamanız başarıyla başlatılabilir. Başlatma sırasında gerekli olan sınıflar birincil DEX dosyasında sağlanmazsa uygulamanız java.lang.NoClassDefFoundError
hatasıyla kilitlenir.
Derleme araçları, doğrudan uygulama kodunuzdan erişilen kodun kod yollarını tanır. Ancak bu sorun, kod yolları daha az görünür olduğunda (ör. kullandığınız kitaplığın karmaşık bağımlılıkları olduğunda) ortaya çıkabilir. Örneğin, kodda yerel koddan Java yöntemlerinin iç gözlemi veya çağrılması kullanılıyorsa bu sınıflar birincil DEX dosyasında gerekli olarak tanınmayabilir.
java.lang.NoClassDefFoundError
alırsanız birincil DEX dosyasında gerekli olan ek sınıfları, derleme türünüzde multiDexKeepProguard
mülküyle açıklayarak manuel olarak belirtmeniz gerekir. multiDexKeepProguard
dosyasında eşleşen bir sınıf varsa bu sınıf birincil DEX dosyasına eklenir.
multiDexKeepProguard mülkü
multiDexKeepProguard
dosyası, ProGuard ile aynı biçimi kullanır ve ProGuard dil bilgisinin tamamını destekler. Uygulamanızda nelerin tutulacağını özelleştirme hakkında daha fazla bilgi için Hangi kodun tutulacağını özelleştirme başlıklı makaleyi inceleyin.
multiDexKeepProguard
içinde belirttiğiniz dosya, geçerli bir ProGuard söz diziminde -keep
seçenekleri içermelidir. Örneğin,
-keep com.example.MyClass.class
. multidex-config.pro
adlı şu dosyayı oluşturabilirsiniz:
-keep class com.example.MyClass -keep class com.example.MyClassToo
Bir paketteki tüm sınıfları belirtmek istiyorsanız dosya şu şekilde görünür:
-keep class com.example.** { *; } // All classes in the com.example package
Ardından, bu dosyayı bir derleme türü için aşağıdaki gibi tanımlayabilirsiniz:
Groovy
android { buildTypes { release { multiDexKeepProguard file('multidex-config.pro') ... } } }
Kotlin
android { buildTypes { getByName("release") { multiDexKeepProguard = file("multidex-config.pro") ... } } }
Geliştirme derlemelerinde multidex'i optimize etme
Derleme sistemi, birincil DEX dosyasına hangi sınıfların dahil edilmesi ve ikincil DEX dosyalarına hangi sınıfların dahil edilebileceği konusunda karmaşık kararlar vermesi gerektiğinden, çoklu DEX yapılandırması önemli ölçüde daha uzun derleme işleme süresi gerektirir. Bu, multidex kullanan artımlı derlemelerin genellikle daha uzun sürdüğü ve geliştirme sürecinizi yavaşlatabileceği anlamına gelir.
Artımlı derleme sürelerini kısaltmak için ön dexing özelliğini kullanarak derlemeler arasında çoklu dex çıktısını yeniden kullanın.
Ön dex oluşturma işlemi, yalnızca Android 5.0 (API düzeyi 21) ve sonraki sürümlerde kullanılabilen bir ART biçimine dayanır. Android Studio kullanıyorsanız IDE, uygulamanızı Android 5.0 (API düzeyi 21) veya sonraki bir sürümü çalıştıran bir cihaza dağıtırken otomatik olarak ön dexing kullanır.
Ancak Gradle derlemelerini komut satırından çalıştırıyorsanız ön derlemeyi etkinleştirmek için minSdkVersion
değerini 21 veya daha yüksek bir değere ayarlamanız gerekir.
minSdkVersion
için farklı değerler kullanılır.
Groovy
android { defaultConfig { ... multiDexEnabled true // The default minimum API level you want to support. minSdkVersion 15 } productFlavors { // Includes settings you want to keep only while developing your app. dev { // Enables pre-dexing for command-line builds. When using // Android Studio 2.3 or higher, the IDE enables pre-dexing // when deploying your app to a device running Android 5.0 // (API level 21) or higher, regardless of minSdkVersion. minSdkVersion 21 } prod { // If you've configured the defaultConfig block for the production version of // your app, you can leave this block empty and Gradle uses configurations in // the defaultConfig block instead. You still need to include this flavor. // Otherwise, all variants use the "dev" flavor configurations. } } buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { implementation "androidx.multidex:multidex:2.0.1" }
Kotlin
android { defaultConfig { ... multiDexEnabled = true // The default minimum API level you want to support. minSdk = 15 } productFlavors { // Includes settings you want to keep only while developing your app. create("dev") { // Enables pre-dexing for command-line builds. When using // Android Studio 2.3 or higher, the IDE enables pre-dexing // when deploying your app to a device running Android 5.0 // (API level 21) or higher, regardless of minSdkVersion. minSdk = 21 } create("prod") { // If you've configured the defaultConfig block for the production version of // your app, you can leave this block empty and Gradle uses configurations in // the defaultConfig block instead. You still need to include this flavor. // Otherwise, all variants use the "dev" flavor configurations. } } buildTypes { getByName("release") { isMinifyEnabled = true proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") } } } dependencies { implementation("androidx.multidex:multidex:2.0.1") }
Android Studio'da veya komut satırında derleme hızlarını artırmaya yardımcı olacak daha fazla strateji öğrenmek için Derleme hızınızı optimize etme başlıklı makaleyi okuyun. Derleme varyantlarını kullanma hakkında daha fazla bilgi için Derleme varyantlarını yapılandırma başlıklı makaleyi inceleyin.
İpucu: Farklı multidex ihtiyaçları için farklı derleme varyantlarınız varsa her varyant için farklı bir manifest dosyası sağlayabilirsiniz. Böylece, yalnızca API düzeyi 20 ve daha düşük olan dosyada <application>
etiket adı değişir. Ayrıca, her varyant için farklı bir Application
alt sınıfı oluşturabilirsiniz. Böylece, yalnızca API düzeyi 20 ve daha düşük olan alt sınıf MultiDexApplication
sınıfını genişletir veya MultiDex.install(this)
'yi çağırır.
Multidex uygulamalarını test etme
Çok dex'li uygulamalar için enstrümantasyon testleri yazarken
MonitoringInstrumentation
veya
AndroidJUnitRunner
enstrümantasyonu kullanıyorsanız ek yapılandırma gerekmez. Başka bir Instrumentation
kullanıyorsanız onCreate()
yöntemini aşağıdaki kodla geçersiz kılmanız gerekir:
Kotlin
fun onCreate(arguments: Bundle) { MultiDex.install(targetContext) super.onCreate(arguments) ... }
Java
public void onCreate(Bundle arguments) { MultiDex.install(getTargetContext()); super.onCreate(arguments); ... }