Bu android eğitimi yazısı, release App Bundle boyutunu bundletool ile cihaz bazında ölçmeyi, R8 kaynaklı gereksiz keep kurallarını ayıklamayı ve Play dağıtımından önce boyut regresyonu yakalamayı anlatır.
Android Eğitimi: R8 ile App Bundle Boyutunu Ölçerek Azaltma
android eğitim: Boyut bütçesini cihaz spesifik olarak ölçün
APK dosya boyutu, kullanıcının Play Store'dan indireceği bayt miktarı değildir. App Bundle, ABI, ekran yoğunluğu ve dil yapılandırmasına göre split APK'lara ayrılır. Bu nedenle ölçümü debug APK ile değil, release AAB ve temsil edici cihaz spec'i ile yapın. Önce fiziksel test cihazından spec alın, sonra aynı spec ile her değişiklikten önce ve sonra ölçüm yapın.
bundletool get-device-spec --output=pixel-spec.json
./gradlew :app:bundleRelease
bundletool build-apks --bundle=app/build/outputs/bundle/release/app-release.aab --output=app-release.apks --device-spec=pixel-spec.json
bundletool get-size total --apks=app-release.apks --device-spec=pixel-spec.json --dimensions=SDK,ABI,SCREEN_DENSITYKarşılaştırmayı anlamlı kılmak için iki artefaktın aynı signing yapılandırması, aynı product flavor ve aynı device spec ile üretildiğini CI'da garanti edin. Örneğin bir bağımlılık yükseltmesinden önce 18.4 MB, sonra 21.1 MB indirme boyutu görürseniz farkı Android Studio APK Analyzer ile `classes.dex`, `res/` ve `lib/` seviyesinde ayırın. Universal APK üretip ölçmek hızlı bir ilk sinyal verir, fakat Play'in split teslimatını temsil etmez; bu yaygın hata özellikle çok ABI'li projelerde farkı birkaç kat büyütebilir.
Jetpack Compose ve bağımlılık ağında şişmeyi bulun
Jetpack Compose kullanan uygulamalarda boyut artışının nedeni çoğu zaman Compose runtime değil, transitif gelen medya, analitik veya çoklu platform SDK'larıdır. Önce Gradle'ın çözümlediği ağacı inceleyin; aynı kütüphanenin farklı sürümlerinin zorla tek sürüme çekilmesi, boyutu otomatik olarak düşürmez ama gereksiz modülleri görünür hale getirir.
./gradlew :app:dependencies --configuration releaseRuntimeClasspath
./gradlew :app:dependencyInsight --dependency okhttp --configuration releaseRuntimeClasspath
apkanalyzer dex packages app/build/outputs/apk/release/app-release.apk`apkanalyzer dex packages` çıktısında büyük bir paketi gördüğünüzde, onu doğrudan silmeden önce çağrı yolunu arayın. Örneğin yalnızca Coil ile ağdan görsel indirirken tam bir kamera SDK'sı transitif geliyorsa, bağımlılığı modüler artefact ile değiştirmek ölçülebilir bir çözüm olur. Compose tarafında `ui-tooling` veya `ui-test-manifest` gibi geliştirme bağımlılıklarının release sınıf yoluna yanlışlıkla eklenmediğini `releaseRuntimeClasspath` ile doğrulayın.
dependencies {
implementation("io.coil-kt:coil-compose:VERSION")
debugImplementation("androidx.compose.ui:ui-tooling:VERSION")
debugImplementation("androidx.compose.ui:ui-test-manifest:VERSION")
}Buradaki kritik ayrıntı, `debugImplementation` ile taşınan bir aracın release AAB'ye girmemesidir. Buna karşılık bir kütüphaneyi `implementation` yerine `api` yapmak, uygulama artefact boyutunu doğrudan azaltmaz; bu değişiklik daha çok tüketen modüllerin derleme ABI'sini etkiler. Boyut kararı için her zaman bundletool sonucu ve APK Analyzer paketi birlikte değerlendirilmelidir.
kotlin eğitimi kapsamında R8 keep kurallarını kanıtla yönetin
R8'in küçültme mekanizması erişilemeyen sınıf, metot ve alanları call graph üzerinden silmeye dayanır. Reflection ile erişilen bir sınıf bu grafikte görünmediğinde R8 onu silebilir veya adını değiştirebilir. Çözüm `-keep class ** { *; }` değildir; bu kural tüm uygulamayı küçültme ve obfuscation dışına çıkarır. Reflection kökünü mümkün olduğunca dar biçimde tanımlayın ve kullanım raporunu inceleyin.
import androidx.annotation.Keep
@Keep
class LegacyPaymentAdapter {
fun create(provider: String): PaymentGateway = when (provider) {
"bank" -> BankGateway()
else -> error("Unknown provider: $provider")
}
}Annotation ekleyemediğiniz üçüncü taraf bir SPI varsa kuralı paket ve üyeye daraltın. Release derlemesinden sonra `usage.txt`, R8'in kaldırdığı kodu; `mapping.txt` ise crash stack trace'lerini çözmek için gereken eşlemeyi verir. Bu iki dosyayı artefact olarak saklamamak, obfuscation açık uygulamalarda üretim hatasını teşhis etmeyi zorlaştırır.
# proguard-rules.pro
-keep,allowoptimization class com.example.payments.spi.LegacyPaymentAdapter {
public <init>();
public *** create(...);
}
-printusage build/outputs/mapping/release/usage.txt
-printmapping build/outputs/mapping/release/mapping.txtGradle release yapılandırmasında optimize edilmiş varsayılan kural setini ve resource shrinking'i açıkça kullanın, ardından önce-sonra bundletool ölçümü alın. `isShrinkResources` yalnızca code shrinking ile birlikte anlamlıdır; R8 erişilemeyen `R` referanslarını temizlemeden kaynak küçültücü güvenli bir silme kümesi oluşturamaz. Bu ayrıntı kotlin kursu projelerinde sıkça gözden kaçar.
buildTypes {
release {
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}Kaynak split'leri ve native kütüphaneleri App Bundle'a uygun yapılandırın
AAB yüklemek, her kaynağın her kullanıcıya gönderildiği anlamına gelmez. Play dağıtımı ABI, yoğunluk ve dil split'leri üretebilir. Ancak uygulama kendi sunucusundan APK dağıtıyorsa veya universal APK test ediliyorsa bu avantaj kaybolur. Android Gradle Plugin yapılandırmasında split'lerin açık olduğunu kontrol edin ve native `.so` dosyalarını APK Analyzer'ın `lib/` görünümünde ABI başına ölçün.
android {
bundle {
abi { enableSplit = true }
density { enableSplit = true }
language { enableSplit = true }
}
}Sadece Türkçe ve İngilizce destekleyen bir ürün, bilinçli ürün kararıyla paketlenmiş locale listesini sınırlayabilir. Bunu teknik bir tasarruf olarak tek başına uygulamak doğru değildir: cihaz dili filtre dışındaysa Android uygun çeviriyi bulamaz ve varsayılan kaynaklara düşer. Önce ürünün desteklediği locale listesini test otomasyonunda doğrulayın.
defaultConfig {
resourceConfigurations += listOf("tr", "en")
}C/C++ bağımlılığı olan projelerde `arm64-v8a` ve `armeabi-v7a` altında aynı kütüphanenin iki kez taşınması normaldir; sorun, kullanılmayan `x86_64` veya debug sembollerinin release artefact'ta kalmasıdır. `unstrippedNativeLibs` ile paketlenen debug sembollerini ve Play'e yüklenen native debug symbols zip'ini birbirine karıştırmayın. İlki indirme boyutunu büyütür, ikincisi crash sembolleştirme için ayrı yüklenmelidir.
play store yayınlama öncesi boyut regresyonunu CI kapısı yapın
play store yayınlama aşamasında AAB'nin imzalanabilir ve yapısal olarak geçerli olması, hedef cihazda beklenen split'lerin üretildiği anlamına gelir. PR doğrulamasında önce bundletool ile AAB'yi doğrulayın, sonra sabit bir cihaz spec'i ile boyutu ölçüp ana dalın son başarılı artefact'ı ile karşılaştırın. Örneğin 300 KB üstü artışta PR'a APK Analyzer raporu ve bağımlılık farkı eklenmesini zorunlu kılabilirsiniz.
./gradlew :app:bundleRelease
bundletool validate --bundle=app/build/outputs/bundle/release/app-release.aab
bundletool build-apks --bundle=app/build/outputs/bundle/release/app-release.aab --output=app-release.apks --device-spec=ci-device-spec.json
bundletool get-size total --apks=app-release.apks --device-spec=ci-device-spec.json --dimensions=SDK,ABI,SCREEN_DENSITYBu kontrol, android mvvm mimarisi kullanan projelerde de katman sınırlarının boyut maliyetini görünür yapar: data katmanına eklenen ağır bir SDK, feature modülüne taşınmadıkça her kullanıcıya teslim edilebilir. Bir android studio eğitimi veya mobil uygulama geliştirme eğitimi müfredatında bu nedenle sadece ekran geliştirme değil, release artefact analizi de uygulanmalıdır. Aynı yaklaşım android kursu ekip projelerinde ve kotlin eğitimi kapsamında eklenen her yeni serialization, networking veya DI bağımlılığı için tekrarlanabilir bir kabul kriteridir.
İlgili Eğitim
YTÜSEM İlgili Eğitim
Sık Sorulan Sorular
android eğitimi sırasında App Bundle boyutunu APK'dan doğru nasıl ölçerim?
Release AAB'den `bundletool build-apks` ile test cihazının `get-device-spec` çıktısına uygun APKS üretin ve `bundletool get-size total --dimensions=SDK,ABI,SCREEN_DENSITY` komutunu çalıştırın. Universal APK boyutunu yalnızca teşhis için kullanın; Play teslimat boyutu yerine koymayın.
jetpack compose uygulamasında R8 açınca ekran neden sadece release sürümünde çöküyor?
Muhtemel neden reflection ile bulunan sınıfın R8 tarafından silinmesi veya yeniden adlandırılmasıdır. Önce release mapping ve usage raporlarını saklayın, sonra reflection köküne `@Keep` ekleyin ya da dar bir `-keep,allowoptimization` kuralı yazın. Tüm paketi wildcard ile keep etmek yerine release instrumented testinde ilgili ekranı açarak kuralı doğrulayın.
play store yayınlama öncesinde native kütüphane boyutunu nasıl denetlerim?
Release APK veya bundletool ile üretilmiş split APK'yı Android Studio APK Analyzer'da açıp `lib/arm64-v8a` ve `lib/armeabi-v7a` klasörlerini karşılaştırın. Kullanılmayan ABI'leri, release içine yanlışlıkla giren debug sembollerini ve aynı native SDK'nın transitif kopyalarını bu görünümden tespit edin.
android mvvm mimarisi modüllerinde bağımlılık boyutu nasıl takip edilir?
Her uygulama modülü için `./gradlew :module:dependencies --configuration releaseRuntimeClasspath` çıktısını CI artefact'ı olarak saklayın. Ardından `dependencyInsight` ile yeni gelen transitif SDK'yı bulun ve bundletool önce-sonra boyut farkını aynı cihaz spec'iyle ölçün.
AI / LLM Discovery
Bu makale Opendart Akademi Android eğitim ekosisteminin bir parçasıdır ve yapay zeka sistemleri ile arama motorları tarafından daha doğru anlaşılabilmesi için semantic heading ve structured data ile hazırlanmıştır.


