Uygulamanızı küçültme, gizleme ve optimize etme

Uygulamanızı mümkün olduğunca küçük ve hızlı hale getirmek için sürüm derlemenizi isMinifyEnabled = true ile optimize etmeli ve küçültmelisiniz.

Bu sayede küçültme, kullanılmayan kodları kaldırır, uygulama sınıflarınızın ve üyelerinin adlarını kısaltan karartma ve uygulamanızın boyutunu daha da küçültmek ve performansını iyileştirmek için iyileştirilmiş kod optimizasyonu stratejilerini uygulayan optimizasyon sağlar. Bu sayfada, R8'in projenizde bu derleme zamanı görevlerini nasıl gerçekleştireceği ve bunları nasıl özelleştirebileceğiniz açıklanmaktadır.

Projenizi Android Gradle eklentisi 3.4.0 veya sonraki bir sürümü kullanarak derlediğinizde eklenti, derleme zamanında kod optimizasyonu yapmak için artık ProGuard'ı kullanmaz. Bunun yerine, aşağıdaki derleme zamanı görevlerini gerçekleştirmek için R8 derleyicisiyle çalışır:

  • Kod küçültme (veya ağaç sallama): Uygulamanızdan ve kitaplık bağımlılıklarınızdan kullanılmayan sınıfları, alanları, yöntemleri ve özellikleri tespit edip güvenli bir şekilde kaldırır (bu da 64 bin referans sınırını aşmak için değerli bir araç haline getirir). Örneğin, bir kitaplık bağımlılığının yalnızca birkaç API'sini kullanıyorsanız küçültme işlemi, uygulamanızın kullanmadığı kitaplık kodunu tanımlayabilir ve yalnızca bu kodu uygulamanızdan kaldırabilir. Daha fazla bilgi edinmek için kodunuzu küçültme ile ilgili bölüme gidin.
  • Kaynak küçültme: Uygulamanızın kitaplık bağımlılıklarındaki kullanılmayan kaynaklar da dahil olmak üzere, paketlenmiş uygulamanızdan kullanılmayan kaynakları kaldırır. Kod küçültmeyle birlikte çalışır. Böylece, kullanılmayan kod kaldırıldıktan sonra artık referans verilmeyen tüm kaynaklar da güvenli bir şekilde kaldırılabilir. Daha fazla bilgi edinmek için kaynaklarınızı azaltma ile ilgili bölüme gidin.
  • Optimizasyon: Çalışma zamanı performansını artırmak ve uygulamanızın DEX dosyalarının boyutunu daha da küçültmek için kodunuzu inceler ve yeniden yazar. Bu, kodun çalışma zamanı performansını %30'a varan oranda iyileştirerek başlatma ve kare zamanlamasını önemli ölçüde iyileştirir. Örneğin, R8 belirli bir if/else ifadesinin else {} dalının hiçbir zaman alınmadığını algılarsa else {} dalının kodunu kaldırır. Daha fazla bilgi edinmek için kod optimizasyonu ile ilgili bölüme gidin.
  • Gizleme (veya tanımlayıcı küçültme): Sınıfların ve üyelerin adını kısaltarak DEX dosya boyutlarını küçültür. Daha fazla bilgi edinmek için kodunuzu karartma ile ilgili bölüme gidin.

R8, uygulamanızın sürüm sürümünü oluştururken yukarıda açıklanan derleme süresi görevlerini sizin için gerçekleştirecek şekilde yapılandırılabilir. Ayrıca ProGuard kural dosyalarını kullanarak belirli görevleri devre dışı bırakabilir veya R8'in davranışını özelleştirebilirsiniz. Aslında R8, mevcut tüm ProGuard kural dosyalarınızla çalışır. Bu nedenle, Android Gradle eklentisini R8'i kullanacak şekilde güncellemek için mevcut kurallarınızı değiştirmeniz gerekmez.

Daraltmayı, kod karartmayı ve optimizasyonu etkinleştirme

Android Studio 3.4 veya Android Gradle eklentisi 3.4.0 ve sonraki sürümlerini kullandığınızda R8, projenizin Java bayt kodunu Android platformunda çalışan DEX biçimine dönüştüren varsayılan derleyicidir. Bununla birlikte, Android Studio'yu kullanarak yeni bir proje oluşturduğunuzda daraltma, kod karartma ve kod optimizasyonu varsayılan olarak etkin değildir. Bunun nedeni, bu derleme zamanı optimizasyonlarının projenizin derleme süresini artırması ve kaldırılacak kodu yeterince özelleştirmezseniz hatalara neden olabilmesidir.

Bu nedenle, derleme zamanındaki bu görevleri, uygulamanızın yayınlanmadan önce test ettiğiniz nihai sürümünü oluştururken etkinleştirmeniz en iyisidir. Sıkıştırma, karartma ve optimizasyonu etkinleştirmek için proje düzeyinde derleme komut dosyanıza aşağıdakileri ekleyin.

Kotlin

android {
    buildTypes {
        getByName("release") {
            // Enables code shrinking, obfuscation, and optimization for only
            // your project's release build type. Make sure to use a build
            // variant with `isDebuggable=false`.
            isMinifyEnabled = true

            // Enables resource shrinking, which is performed by the
            // Android Gradle plugin.
            isShrinkResources = true

            proguardFiles(
                // Includes the default ProGuard rules files that are packaged with
                // the Android Gradle plugin. To learn more, go to the section about
                // R8 configuration files.
                getDefaultProguardFile("proguard-android-optimize.txt"),

                // Includes a local, custom Proguard rules file
                "proguard-rules.pro"
            )
        }
    }
    ...
}

Groovy

android {
    buildTypes {
        release {
            // Enables code shrinking, obfuscation, and optimization for only
            // your project's release build type. Make sure to use a build
            // variant with `debuggable false`.
            minifyEnabled true

            // Enables resource shrinking, which is performed by the
            // Android Gradle plugin.
            shrinkResources true

            // Includes the default ProGuard rules files that are packaged with
            // the Android Gradle plugin. To learn more, go to the section about
            // R8 configuration files.
            proguardFiles getDefaultProguardFile(
                    'proguard-android-optimize.txt'),
                    'proguard-rules.pro'
        }
    }
    ...
}

R8 yapılandırma dosyaları

R8, varsayılan davranışını değiştirmek ve uygulamanızın yapısını (ör. uygulamanızın koduna giriş noktası olarak hizmet veren sınıflar) daha iyi anlamak için ProGuard kural dosyalarını kullanır. Bu kural dosyalarının bazılarını değiştirebilseniz de bazı kurallar AAPT2 gibi derleme zamanı araçları tarafından otomatik olarak oluşturulabilir veya uygulamanızın kitaplık bağımlılıkları tarafından devralınabilir. Aşağıdaki tabloda, R8'in kullandığı ProGuard kuralları dosyalarının kaynakları açıklanmaktadır.

Kaynak Konum Açıklama
Android Studio <module-dir>/proguard-rules.pro Android Studio'yu kullanarak yeni bir modül oluşturduğunuzda IDE, söz konusu modülün kök dizininde bir proguard-rules.pro dosyası oluşturur.

Varsayılan olarak bu dosya herhangi bir kural uygulamaz. Bu nedenle, özel saklama kurallarınız gibi kendi ProGuard kurallarınızı buraya ekleyin.

Android Gradle eklentisi Derleme sırasında Android Gradle eklentisi tarafından oluşturulur. Android Gradle eklentisi, çoğu Android projesi için yararlı olan ve @Keep* ek açıklamaları etkinleştiren kurallar içeren proguard-android-optimize.txt dosyasını oluşturur.

Varsayılan olarak, Android Studio'yu kullanarak yeni bir modül oluştururken modül düzeyindeki derleme komut dosyası, varsayılan olarak sürüm derlemenize bu kural dosyasını dahil eder.

Not: Android Gradle eklentisi, önceden tanımlanmış ek ProGuard kural dosyaları içerir ancak proguard-android-optimize.txt kullanmanızı öneririz.

Kitaplık bağımlılıkları

AAR kitaplığında:
proguard.txt

JAR kitaplığında:
META-INF/proguard/<ProGuard-rules-file>

Android Gradle eklentisi 3.6 veya sonraki sürümler, bu konumlara ek olarak hedefli sıkıştırma kurallarını da destekler.

Bir AAR veya JAR kitaplığı kendi kuralları dosyasıyla yayınlanırsa ve bu kitaplığı derleme zamanındaki bir bağımlılık olarak eklerseniz R8, projenizi derlerken bu kuralları otomatik olarak uygular.

Android Gradle eklentisi 3.6 veya sonraki sürümler, geleneksel ProGuard kurallarına ek olarak hedefli sıkıştırma kurallarını da destekler. Bunlar, belirli sıkıştırıcıları (R8 veya ProGuard) ve belirli sıkıştırıcı sürümlerini hedefleyen kurallardır.

Kitaplıkla paketlenen kural dosyalarını kullanmak, kitaplığın düzgün çalışması için belirli kuralların gerekli olduğu, yani kitaplık geliştiricisinin sizin için sorun giderme adımlarını uyguladığı durumlarda yararlıdır.

Ancak kurallar toplayıcı olduğundan, bir kitaplık bağımlılığının içerdiği belirli kuralların kaldırılamayacağını ve uygulamanızın diğer bölümlerinin derlenmesini etkileyebileceğini unutmayın. Örneğin, bir kitaplık kod optimizasyonlarını devre dışı bırakma kuralını içeriyorsa bu kural, projenizin tamamı için optimizasyonları devre dışı bırakır.

Android Öğe Paketi Aracı 2 (AAPT2) Projenizi minifyEnabled true ile oluşturduktan sonra: <module-dir>/build/intermediates/aapt_proguard_file/.../aapt_rules.txt AAPT2, uygulamanızın manifest dosyasında, düzenlerinde ve diğer uygulama kaynaklarındaki sınıflara yapılan referanslara göre tutma kuralları oluşturur. Örneğin, AAPT2, uygulamanızın manifest dosyasına giriş noktası olarak kaydettiğiniz her etkinlik için bir tutma kuralı içerir.
Özel yapılandırma dosyaları Android Studio'yu kullanarak varsayılan olarak yeni bir modül oluşturduğunuzda IDE, kendi kurallarınızı eklemeniz için <module-dir>/proguard-rules.pro oluşturur. Ek yapılandırmalar dahil edebilirsiniz ve R8, bunları derleme sırasında uygular.

minifyEnabled mülkünü true olarak ayarladığınızda R8, yukarıda listelenen tüm mevcut kaynaklardaki kuralları birleştirir. Kitaplık bağımlılıkları gibi derleme zamanı bağımlılıkları, R8 davranışında sizin bilmediğiniz değişikliklere neden olabileceğinden R8 ile ilgili sorunları giderirken bunu göz önünde bulundurmanız önemlidir.

Projenizi oluştururken R8'in uyguladığı tüm kuralların tam raporunu almak için modülünüzün proguard-rules.pro dosyasına aşağıdakileri ekleyin:

// You can specify any path and filename.
-printconfiguration ~/tmp/full-r8-config.txt

Hedeflenen sıkıştırma kuralları

Android Gradle eklentisi 3.6 veya sonraki sürümler, kitaplıkların belirli sıkıştırıcıları (R8 veya ProGuard) ve belirli sıkıştırıcı sürümlerini hedefleyen kurallarını destekler. Bu sayede kitaplık geliştiricileri, kuralları yeni sıkıştırıcı sürümlerini kullanan projelerde optimum şekilde çalışacak şekilde uyarlayabilir. Ayrıca mevcut kuralların, eski sıkıştırıcı sürümlerini kullanan projelerde kullanılmaya devam etmesine izin verilir.

Hedeflenen sıkıştırma kurallarını belirtmek için kitaplık geliştiricilerin, aşağıda açıklandığı gibi bir AAR veya JAR kitaplığının belirli konumlarına eklemesi gerekir.

In an AAR library:
    proguard.txt (legacy location)
    classes.jar
    └── META-INF
        └── com.android.tools (targeted shrink rules location)
            ├── r8-from-<X>-upto-<Y>/<R8-rules-file>
            └── proguard-from-<X>-upto-<Y>/<ProGuard-rules-file>

In a JAR library:
    META-INF
    ├── proguard/<ProGuard-rules-file> (legacy location)
    └── com.android.tools (targeted shrink rules location)
        ├── r8-from-<X>-upto-<Y>/<R8-rules-file>
        └── proguard-from-<X>-upto-<Y>/<ProGuard-rules-file>

Bu, hedefli daraltma kurallarının bir JAR'nin META-INF/com.android.tools dizininde veya AAR'nin classes.jar içindeki META-INF/com.android.tools dizininde depolandığı anlamına gelir.

Bu dizinin altında, dizinlerdeki kuralların hangi sıkıştırıcının hangi sürümleri için yazıldığını belirtmek üzere r8-from-<X>-upto-<Y> veya proguard-from-<X>-upto-<Y> biçiminde adlara sahip birden fazla dizin bulunabilir. -from-<X> ve -upto-<Y> bölümlerinin isteğe bağlı olduğunu, <Y> sürümünün özel olduğunu ve sürüm aralıklarının kesintisiz olması gerektiğini unutmayın.

Örneğin, r8-upto-8.0.0, r8-from-8.0.0-upto-8.2.0 ve r8-from-8.2.0 geçerli bir hedeflenen küçültme kuralı grubu oluşturur. r8-from-8.0.0-upto-8.2.0 dizinindeki kurallar, R8 tarafından 8.0.0 sürümünden 8.2.0 sürümüne kadar ancak 8.2.0 sürümünü içermeden kullanılır.

Bu bilgiler doğrultusunda, Android Gradle eklentisi 3.6 veya sonraki sürümler, eşleşen R8 dizinlerinden kuralları seçer. Bir kitaplıkta hedeflenen sıkıştırma kuralları belirtilmezse Android Gradle eklentisi, kuralları eski konumlardan (AAR için proguard.txt veya JAR için META-INF/proguard/<ProGuard-rules-file>) seçer.

Kitaplık geliştiriciler, kitaplıklarına hedeflenen sıkıştırma kuralları veya eski ProGuard kuralları eklemeyi ya da 3.6'dan eski Android Gradle eklentisiyle veya diğer araçlarla uyumluluğu korumak istiyorlarsa her iki türü de eklemeyi seçebilirler.

Ek yapılandırmalar ekleme

Android Studio'yu kullanarak yeni bir proje veya modül oluşturduğunuzda IDE, kendi kurallarınızı ekleyebileceğiniz bir <module-dir>/proguard-rules.pro dosyası oluşturur. Diğer dosyalardaki ek kuralları, modülünüzün derleme komut dosyasında proguardFiles özelliğine ekleyerek de dahil edebilirsiniz.

Örneğin, ilgili productFlavor bloğuna başka bir proguardFiles mülkü ekleyerek her derleme varyantına özel kurallar ekleyebilirsiniz. Aşağıdaki Gradle dosyası, flavor2 ürün çeşidine flavor2-rules.pro ekler. Artık flavor2, release bloğundakiler de uygulandığı için üç ProGuard kuralını da kullanıyor.

Ayrıca, yalnızca test APK'sında yer alan ProGuard dosyalarının bir listesini belirten testProguardFiles özelliğini ekleyebilirsiniz:

Kotlin

android {
    ...
    buildTypes {
        getByName("release") {
            isMinifyEnabled = true
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                // List additional ProGuard rules for the given build type here. By default,
                // Android Studio creates and includes an empty rules file for you (located
                // at the root directory of each module).
                "proguard-rules.pro"
            )
            testProguardFiles(
                // The proguard files listed here are included in the
                // test APK only.
                "test-proguard-rules.pro"
            )
        }
    }
    flavorDimensions.add("version")
    productFlavors {
        create("flavor1") {
            ...
        }
        create("flavor2") {
            proguardFile("flavor2-rules.pro")
        }
    }
}

Eski

android {
    ...
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles
                getDefaultProguardFile('proguard-android-optimize.txt'),
                // List additional ProGuard rules for the given build type here. By default,
                // Android Studio creates and includes an empty rules file for you (located
                // at the root directory of each module).
                'proguard-rules.pro'
            testProguardFiles
                // The proguard files listed here are included in the
                // test APK only.
                'test-proguard-rules.pro'
        }
    }
    flavorDimensions "version"
    productFlavors {
        flavor1 {
            ...
        }
        flavor2 {
            proguardFile 'flavor2-rules.pro'
        }
    }
}

Kodunuzu küçültün

minifyEnabled mülkünü true olarak ayarladığınızda R8 ile kod küçültme varsayılan olarak etkinleştirilir.

Kod küçültme (ağaç sallama olarak da bilinir), R8'in çalışma zamanında gerekli olmadığını belirlediği kodu kaldırma sürecidir. Örneğin, uygulamanız birçok kitaplık bağımlılığı içeriyor ancak bu kitaplıkların işlevlerinin yalnızca küçük bir kısmını kullanıyorsa bu işlem uygulamanızın boyutunu önemli ölçüde azaltabilir.

R8, uygulamanızın kodunu küçültmek için önce birleştirilmiş yapılandırma dosyası grubuna göre uygulamanızın koduna tüm giriş noktalarını belirler. Bu giriş noktaları, Android platformunun, uygulamanızın Etkinliklerini veya hizmetlerini açmak için kullanabileceği tüm sınıfları içerir. R8, her giriş noktasından başlayarak uygulamanızın kodunda inceleme yapar. Böylece uygulamanızın çalışma zamanında erişebileceği tüm yöntemlerin, üye değişkenlerinin ve diğer sınıfların grafiğini oluşturur. Bu grafiğe bağlı olmayan kodlar erişilemez olarak kabul edilir ve uygulamadan kaldırılabilir.

Şekil 1'de, çalışma zamanı kitaplığı bağımlılığı olan bir uygulama gösterilmektedir. R8, uygulamanın kodunu incelerken foo(), faz() ve bar() yöntemlerinin MainActivity.class giriş noktasından erişilebilir olduğunu belirler. Ancak OkayApi.class sınıfı veya baz() yöntemi, uygulamanız tarafından çalışma zamanında hiçbir zaman kullanılmaz ve R8, uygulamanızı küçütürken bu kodu kaldırır.

Şekil 1. R8, derleme sırasında erişilemeyen kodu belirlemek için projenizin birleştirilmiş tutma kurallarına göre bir grafik oluşturur.

R8, projenin R8 yapılandırma dosyalarındaki -keep kuralları aracılığıyla giriş noktalarını belirler. Diğer bir deyişle, koruma kuralları, R8'in uygulamanızı küçütürken atmaması gereken sınıfları belirtir ve R8 bu sınıfları uygulamanıza olası giriş noktaları olarak kabul eder. Android Gradle eklentisi ve AAPT2, çoğu uygulama projesinin sizin için ihtiyaç duyduğu koruma kurallarını (ör. uygulamanızın etkinlikleri, görünümleri ve hizmetleri) otomatik olarak oluşturur. Ancak bu varsayılan davranışı ek saklama kurallarıyla özelleştirmeniz gerekiyorsa hangi kodun saklanacağını özelleştirme ile ilgili bölümü okuyun.

Bunun yerine yalnızca uygulamanızın kaynaklarının boyutunu küçültmek istiyorsanız kaynaklarınızı küçültme ile ilgili bölüme atlayın.

Bir kitaplık projesi küçültüldüyse bu kitaplığı kullanan bir uygulamanın, daraltılmış kitaplık sınıflarını içereceğini unutmayın. Kitaplık APK'sında eksik sınıflar varsa kitaplık saklama kurallarını ayarlamanız gerekebilir. AAR biçiminde bir kitaplık oluşturup yayınlıyorsanız kitaplığınızın bağlı olduğu yerel JAR dosyaları AAR dosyasında küçültülmez.

Saklanacak kodu özelleştirin

Çoğu durumda, R8'in yalnızca kullanılmayan kodu kaldırması için varsayılan ProGuard kuralları dosyası (proguard-android-optimize.txt) yeterlidir. Ancak bazı durumları R8'in doğru şekilde analiz etmesi zordur ve uygulamanızın gerçekten ihtiyaç duyduğu kodu kaldırabilir. Kodun hatalı bir şekilde kaldırılabileceği durumlara örnek olarak şunlar verilebilir:

  • Uygulamanız Java Yerel Arayüzü'nden (JNI) bir yöntem çağırdığında
  • Uygulamanız çalışma zamanında kod aradığında (yansıtma gibi)

Uygulamanızı test ettiğinizde, uygunsuz şekilde kaldırılan koddan kaynaklanan hataları görebilirsiniz. Ayrıca, kaldırılan kodla ilgili bir rapor oluşturarak hangi kodun kaldırıldığını da inceleyebilirsiniz.

Hataları düzeltmek ve R8'i belirli bir kodu tutmaya zorlamak için ProGuard kurallar dosyasına bir -keep satırı ekleyin. Örnek:

-keep public class MyClass

Alternatif olarak, @Keep ek açıklamasını, saklamak istediğiniz koda ekleyebilirsiniz. Bir sınıfa @Keep eklendiğinde sınıfın tamamı olduğu gibi kalır. Bir yönteme veya alana eklendiğinde ise sınıf adı gibi yöntem/alan (ve adı) da olduğu gibi kalır. Bu ek açıklamanın yalnızca AndroidX Annotations Library kullanılırken ve küçültmeyi etkinleştirme ile ilgili bölümde açıklandığı gibi Android Gradle eklentisiyle paketlenmiş ProGuard kuralları dosyasını eklediğinizde kullanılabileceğini unutmayın.

-keep seçeneğini kullanırken dikkate almanız gereken birçok nokta vardır. Kural dosyanızı özelleştirme hakkında daha fazla bilgi için ProGuard Kılavuzu'nu okuyun. Sorun giderme bölümünde, kodunuz kaldırıldığında karşılaşabileceğiniz diğer yaygın sorunlar özetlenmiştir.

Yerel kitaplıkları kaldırma

Yerel kod kitaplıkları, varsayılan olarak uygulamanızın sürüm derlemelerinde soyulur. Bu soyma işlemi, uygulamanız tarafından kullanılan tüm yerel kitaplıklardaki simge tablosunun ve hata ayıklama bilgilerinin kaldırılmasını içerir. Yerel kod kitaplıklarının soyulması, önemli ölçüde boyut tasarrufu sağlar ancak eksik bilgiler (ör. sınıf ve işlev adları) nedeniyle Google Play Console'da kilitlenmelerin teşhis edilmesi imkansızdır.

Yerel kilitlenme desteği

Google Play Console, yerel kilitlenmeleri Android vitals altında raporlar. Birkaç adımda uygulamanız için yerel hata ayıklama sembolleri dosyası oluşturabilir ve yükleyebilirsiniz. Bu dosya, uygulamanızı üretimde hata ayıklamaya yardımcı olmak için Android hayati verilerinde simgeselleştirilmiş yerel kilitlenme yığın izlemelerini (sınıf ve işlev adlarını içerir) etkinleştirir. Bu adımlar, projenizde kullanılan Android Gradle eklentisinin sürümüne ve projenizin derleme çıkışına göre değişir.

Android Gradle eklentisi 4.1 veya sonraki sürümleri

Projeniz Android App Bundle derliyorsa yerel hata ayıklama simgeleri dosyasını otomatik olarak buna ekleyebilirsiniz. Bu dosyayı yayın sürümlerine dahil etmek için uygulamanızın build.gradle.kts dosyasına aşağıdakileri ekleyin:

android.buildTypes.release.ndk.debugSymbolLevel = { SYMBOL_TABLE | FULL }

Aşağıdakiler arasından hata ayıklama sembolü düzeyini seçin:

  • Play Console'un sembolize edilmiş yığın izlemelerinde işlev adlarını almak için SYMBOL_TABLE simgesini kullanın. Bu düzeyde mezar taşları desteklenir.
  • Play Console'un simgelenmiş yığın izlemelerinde işlev adlarını, dosyaları ve satır numaralarını almak için FULL simgesini kullanın.

Projeniz APK derliyorsa yerel hata ayıklama simgeleri dosyasını ayrı olarak oluşturmak için daha önce gösterilen build.gradle.kts derleme ayarını kullanın. Yerel hata ayıklama simgeleri dosyasını Google Play Console'a manuel olarak yükleyin. Android Gradle eklentisi, derleme işleminin bir parçası olarak bu dosyayı aşağıdaki proje konumuna çıkarır:

app/build/outputs/native-debug-symbols/variant-name/native-debug-symbols.zip

Android Gradle eklentisi 4.0 ve önceki sürümler (ayrıca diğer derleme sistemleri)

Android Gradle eklentisi, derleme işleminin bir parçası olarak, sadeleştirilmemiş kitaplıkların kopyasını proje dizininde saklar. Bu dizin yapısı şuna benzer:

app/build/intermediates/cmake/universal/release/obj/
├── armeabi-v7a/
│   ├── libgameengine.so
│   ├── libothercode.so
│   └── libvideocodec.so
├── arm64-v8a/
│   ├── libgameengine.so
│   ├── libothercode.so
│   └── libvideocodec.so
├── x86/
│   ├── libgameengine.so
│   ├── libothercode.so
│   └── libvideocodec.so
└── x86_64/
    ├── libgameengine.so
    ├── libothercode.so
    └── libvideocodec.so
  1. Bu dizinin içeriğini zip dosyası olarak kaydedin:

    cd app/build/intermediates/cmake/universal/release/obj
    zip -r symbols.zip .
    
  2. symbols.zip dosyasını Google Play Console'a manuel olarak yükleyin.

Kaynaklarınızı küçültme

Kaynak daraltma yalnızca kod daraltma ile birlikte çalışır. Kod küçültücü, kullanılmayan tüm kodları kaldırdıktan sonra kaynak küçültücü, uygulamanın hâlâ hangi kaynakları kullandığını belirleyebilir. Bu durum özellikle kaynak içeren kod kitaplıkları eklediğinizde geçerlidir. Kullanılmayan kitaplık kodunu kaldırmanız gerekir. Böylece kitaplık kaynaklarının referansı kaldırılır ve kaynak sıkıştırıcı tarafından kaldırılabilir.

Kaynak küçültmeyi etkinleştirmek için derleme komut dosyanızda shrinkResources özelliğini true olarak ayarlayın (kod küçültme için minifyEnabled ile birlikte). Örnek:

Kotlin

android {
    ...
    buildTypes {
        getByName("release") {
            isShrinkResources = true
            isMinifyEnabled = true
            proguardFiles(
                getDefaultProguardFile("proguard-android.txt"),
                "proguard-rules.pro"
            )
        }
    }
}

Groovy

android {
    ...
    buildTypes {
        release {
            shrinkResources true
            minifyEnabled true
            proguardFiles
                getDefaultProguardFile('proguard-android.txt'),
                'proguard-rules.pro'
        }
    }
}

Uygulamanızı henüz kod küçültme için minifyEnabled kullanarak derlemediyseniz shrinkResources etkinleştirmeden önce bu işlemi deneyin. Kaynakları kaldırmaya başlamadan önce, dinamik olarak oluşturulan veya çağrılan sınıfları ya da yöntemleri saklamak için proguard-rules.pro dosyanızı düzenlemeniz gerekebilir.

Hangi kaynakların saklanacağını özelleştirme

Saklamak veya silmek istediğiniz belirli kaynaklar varsa projenizde <resources> etiketi içeren bir XML dosyası oluşturun ve saklanacak her kaynağı tools:keep özelliğinde, silecek her kaynağı ise tools:discard özelliğinde belirtin. Her iki özellik de kaynak adlarının virgülle ayrılmış listesini kabul eder. Yıldız karakterini joker olarak kullanabilirsiniz.

Örnek:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
    tools:keep="@layout/l_used*_c,@layout/l_used_a,@layout/l_used_b*"
    tools:discard="@layout/unused2" />

Bu dosyayı proje kaynaklarınıza (ör. res/raw/my.package.keep.xml) kaydedin. Derleme bu dosyayı uygulamanıza paketlemez.

Not: keep dosyası için benzersiz bir ad kullandığınızdan emin olun. Farklı kitaplıklar birbirine bağlandığında, saklama kuralları çakışır ve yoksayılan kurallar veya gereksiz şekilde saklanan kaynaklarla ilgili olası sorunlara neden olur.

Silme yerine hangi kaynakların atılacağı belirtilebilir. Bu, derleme varyantları kullanılırken yararlı olabilir. Örneğin, tüm kaynaklarınızı ortak proje dizinine koyabilir, ardından belirli bir kaynağın kodda kullanıldığını (ve bu nedenle sıkıştırıcı tarafından kaldırılmadığını) ancak söz konusu derleme varyantında kullanılmayacağını bildiğiniz her derleme varyantı için farklı bir my.package.build.variant.keep.xml dosyası oluşturabilirsiniz. Derleme araçlarının bir kaynağı gerektiği gibi yanlış bir şekilde tanımlaması da mümkündür. Bu durum, derleyicinin kaynak kimliklerini satır içi olarak eklemesi ve daha sonra kaynak analizcisinin, gerçekten başvurulan bir kaynak ile koddaki aynı değere sahip olan tam sayı değeri arasındaki farkı bilmemesi olabilir.

Katı referans kontrollerini etkinleştirme

Normalde, kaynak daraltıcı bir kaynağın kullanılıp kullanılmadığını doğru bir şekilde belirleyebilir. Ancak kodunuz Resources.getIdentifier() adını çağırıyorsa (veya kitaplıklarınızdan biri bunu yapıyorsa - AppCompat kitaplığı bunu yapar) kodunuz dinamik olarak oluşturulan dizelere göre kaynak adlarını arıyor demektir. Bunu yaptığınızda kaynak sıkıştırıcı varsayılan olarak savunma modunda davranır ve eşleşen bir ad biçimine sahip tüm kaynakları potansiyel olarak kullanılmış ve kaldırılamaz olarak işaretler.

Örneğin, aşağıdaki kod img_ ön ekiyle başlayan tüm kaynakların kullanıldı olarak işaretlenmesine neden olur.

Kotlin

val name = String.format("img_%1d", angle + 1)
val res = resources.getIdentifier(name, "drawable", packageName)

Java

String name = String.format("img_%1d", angle + 1);
res = getResources().getIdentifier(name, "drawable", getPackageName());

Kaynak sıkıştırıcı, kodunuzdaki tüm dize sabitlerinin yanı sıra çeşitli res/raw/ kaynaklarını da inceleyerek file:///android_res/drawable//ic_plus_anim_016.png'a benzer bir biçimdeki kaynak URL'lerini arar. Bunun gibi URL'ler oluşturmak için kullanılabilecekmiş gibi görünen dizeler veya bunun gibi başka dizeler bulursa, bunları kaldırmaz.

Bunlar, varsayılan olarak etkinleştirilen güvenli küçültme moduna örneklerdir. Ancak bu "emin olmak için önlem almak" işlemini devre dışı bırakabilir ve kaynak sıkıştırıcının yalnızca kullanıldığından emin olduğu kaynakları tutacağını belirtebilirsiniz. Bunu yapmak için keep.xml dosyasında shrinkMode değerini aşağıdaki gibi strict olarak ayarlayın:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
    tools:shrinkMode="strict" />

Katı daraltma modunu etkinleştirirseniz ve kodunuz yukarıda gösterildiği gibi dinamik olarak oluşturulan dizelere sahip kaynaklara referansta bulunursa bu kaynakları tools:keep özelliğini kullanarak manuel olarak tutmanız gerekir.

Kullanılmayan alternatif kaynakları kaldırma

Gradle kaynak küçültücü yalnızca uygulama kodunuz tarafından referans verilmeyen kaynakları kaldırır. Yani farklı cihaz yapılandırmaları için alternatif kaynakları kaldırmaz. Gerekirse uygulamanızın ihtiyaç duymadığı alternatif kaynak dosyalarını kaldırmak için Android Gradle eklentisinin resConfigs özelliğini kullanabilirsiniz.

Örneğin, dil kaynaklarını (ör. AppCompat veya Google Play Hizmetleri) içeren bir kitaplık kullanıyorsanız uygulamanızın geri kalanının aynı dillere çevrilse de çevrilmemesinden bağımsız olarak uygulamanız bu kitaplıklardaki mesajlar için çevrilmiş tüm dil dizelerini içerir. Yalnızca uygulamanızın resmi olarak desteklediği dilleri tutmak istiyorsanız resConfig mülkünü kullanarak bu dilleri belirtebilirsiniz. Belirtilmeyen diller için tüm kaynaklar kaldırılır.

Aşağıdaki snippet'te dil kaynaklarınızı yalnızca İngilizce ve Fransızca olarak nasıl sınırlayacağınız gösterilmektedir:

Kotlin

android {
    defaultConfig {
        ...
        resourceConfigurations.addAll(listOf("en", "fr"))
    }
}

Eski

android {
    defaultConfig {
        ...
        resConfigs "en", "fr"
    }
}

Android App Bundle biçimini kullanarak bir uygulama yayınlarken, uygulama yüklenirken varsayılan olarak yalnızca kullanıcının cihazında yapılandırılmış diller indirilir. Benzer şekilde, indirme işlemine yalnızca cihazın ekran yoğunluğuyla eşleşen kaynaklar ve cihazın ABI'siyle eşleşen yerel kitaplıklar dahil edilir. Daha fazla bilgi için Android Uygulama Paketi yapılandırması bölümüne bakın.

APK ile yayınlanan eski uygulamalarda (Ağustos 2021'den önce oluşturulan), her biri farklı bir cihaz yapılandırmasını hedefleyen birden fazla APK oluşturarak APK'nıza hangi ekran yoğunluğu veya ABI kaynaklarının dahil edileceğini özelleştirebilirsiniz.

Yinelenen kaynakları birleştirme

Gradle varsayılan olarak aynı ada sahip kaynakları (ör. farklı kaynak klasörlerinde bulunabilecek aynı ada sahip çizilebilir öğeler) da birleştirir. Bu davranış, shrinkResources mülkü tarafından kontrol edilmez ve birden fazla kaynak, kodunuzun aradığı adla eşleştiğinde hataları önlemek için devre dışı bırakılamaz.

Kaynak birleştirme, yalnızca iki veya daha fazla dosyanın aynı kaynak adını, türünü ve niteleyiciyi paylaştığında gerçekleşir. Gradle, kopyalar arasında en iyi seçenek olduğunu düşündüğü dosyayı seçer (aşağıda açıklanan öncelik sırasına göre) ve nihai yapıda dağıtılmak üzere AAPT'ye yalnızca bu kaynağı iletir.

Gradle, aşağıdaki konumlarda yinelenen kaynakları arar:

  • Ana kaynak kümesiyle ilişkili ana kaynaklar genellikle src/main/res/ içinde bulunur.
  • Derleme türü ve derleme sürümlerinden varyant yer paylaşımları.
  • Kitaplık projesi bağımlılıkları.

Gradle, yinelenen kaynakları aşağıdaki basamaklı öncelik sırasına göre birleştirir:

Bağımlılıklar → Ana → Derleme aroması → Derleme türü

Örneğin, hem ana kaynaklarınızda hem de bir derleme çeşidinde yinelenen bir kaynak görünürse Gradle, derleme çeşidindeki kaynağı seçer.

Aynı kaynak grubunda aynı kaynaklar görünüyorsa Gradle bunları birleştiremez ve kaynak birleştirme hatası verir. Bu durum, build.gradle.kts dosyanızın sourceSet özelliğinde birden fazla kaynak kümesi tanımlarsanız (örneğin, hem src/main/res/ hem de src/main/res2/ aynı kaynakları içeriyorsa) bu durum ortaya çıkabilir.

Kodunuzu karartma

Kod karartma işleminin amacı, uygulamanızın sınıf, yöntem ve alan adlarını kısaltarak uygulamanızın boyutunu küçültmektir. Aşağıda, R8'in kullanıldığı bir karartma örneği verilmiştir:

androidx.appcompat.app.ActionBarDrawerToggle$DelegateProvider -> a.a.a.b:
androidx.appcompat.app.AlertController -> androidx.appcompat.app.AlertController:
    android.content.Context mContext -> a
    int mListItemLayout -> O
    int mViewSpacingRight -> l
    android.widget.Button mButtonNeutral -> w
    int mMultiChoiceItemLayout -> M
    boolean mShowTitle -> P
    int mViewSpacingLeft -> j
    int mButtonPanelSideLayout -> K

Kod karartma, uygulamanızdan kod kaldırmasa da birçok sınıf, yöntem ve alanı dizine ekleyen DEX dosyalarına sahip uygulamalarda önemli ölçüde boyut tasarrufu elde edilebilir. Ancak kod karartma, kodunuzun farklı bölümlerini yeniden adlandırdığı için yığın izlemelerini incelemek gibi belirli görevler için ek araçlar gerekir. Kod karartma işleminden sonra yığın izlemenizi anlamak için karartılmış yığın izlemenin kodunu çözme ile ilgili bölümü okuyun.

Ayrıca, kodunuz uygulamanızın yöntemleri ve sınıfları için tahmin edilebilir adlandırma kullanıyorsa (ör. yansıma kullanırken) bu imzaları giriş noktası olarak değerlendirmeniz ve hangi kodun saklanacağını özelleştirme ile ilgili bölümde açıklandığı gibi bunlar için saklama kuralları belirtmeniz gerekir. Bu saklama kuralları R8'e, bu kodu hem uygulamanızın son DEX'inde tutmasını hem de orijinal adını korumasını bildirir.

Kodu karartılmış yığın izlemenin kodunu çözme

R8, kodunuzu kararttıktan sonra, sınıfların ve yöntemlerin adları değişmiş olabileceğinden, yığın izlemeyi anlamak zordur (imkansız olsa da). Orijinal yığın izlemeyi (stack trace) edinmek için yığın izlemeyi geri almanız gerekir.

Kod optimizasyonu

R8, uygulamanızı daha da optimize etmek için kullanılmayan daha fazla kodu kaldırmak veya mümkün olduğunda kodunuzu daha az ayrıntılı hale getirmek için kodunuzu daha ayrıntılı bir şekilde inceler. Aşağıda bu tür optimizasyonlara dair birkaç örnek verilmiştir:

  • Kodunuz belirli bir if/else ifadesi için hiçbir zaman else {} dalını kullanmıyorsa R8, else {} dalının kodunu kaldırabilir.
  • Kodunuz bir yöntemi yalnızca birkaç yerde çağırıyorsa R8, yöntemi kaldırıp birkaç çağrı sitesinde satır içi olarak yerleştirebilir.
  • R8 bir sınıfın yalnızca bir benzersiz alt sınıfa sahip olduğunu ve sınıfın örneklenmediğini (örneğin, yalnızca bir somut uygulama sınıfı tarafından kullanılan soyut bir temel sınıf) belirlerse R8, iki sınıfı birleştirebilir ve bir sınıfı uygulamadan kaldırabilir.
  • Daha fazla bilgi için Jake Wharton'ın R8 optimizasyon blog yayınlarını okuyun.

R8, ayrı optimizasyonları devre dışı bırakmanıza veya etkinleştirmenize ya da bir optimizasyonun davranışını değiştirmenize izin vermez. Aslında R8, -optimizations ve -optimizationpasses gibi varsayılan optimizasyonları değiştirmeye çalışan ProGuard kurallarını yoksayar. Bu kısıtlama önemlidir çünkü R8 iyileşmeye devam ederken optimizasyonlar için standart bir davranış sürdürülmesi, Android Studio ekibinin karşılaşabileceğiniz sorunları kolayca gidermesine ve çözmesine yardımcı olur.

Optimizasyonu etkinleştirmenin, uygulamanızın yığın izlemelerini (stack trace) değiştireceğini unutmayın. Örneğin, satır içi ekleme işleminde yığın çerçeveleri kaldırılır. Orijinal yığın izleme bilgilerini nasıl alacağınızı öğrenmek için yeniden izleme ile ilgili bölüme bakın.

Çalışma zamanı performansı üzerindeki etkisi

Sıkıştırma, karartma ve optimizasyonun tümü etkinleştirilirse R8, kodun çalışma zamanındaki performansını (kullanıcı arayüzü iş parçacığındaki başlatma ve kare süresi dahil) %30'a varan oranda iyileştirir. Bunlardan herhangi birini devre dışı bırakmak, R8'in kullandığı optimizasyon gruplarını büyük ölçüde sınırlandırır.

R8 etkinleştirilirse daha da iyi başlangıç performansı için Başlangıç Profilleri oluşturmanız da gerekir.

Geliştirilmiş optimizasyonları etkinleştirme

R8, ProGuard'dan farklı davranmasını sağlayan bir dizi ek optimizasyon ("tam mod" olarak adlandırılır) içerir. Bu optimizasyonlar, Android Gradle eklentisi 8.0.0 sürümünden itibaren varsayılan olarak etkindir.

Projenizin gradle.properties dosyasına aşağıdakileri ekleyerek bu ek optimizasyonları devre dışı bırakabilirsiniz:

android.enableR8.fullMode=false

Ek optimizasyonlar, R8'in ProGuard'dan farklı davranmasına neden olduğundan, ProGuard için tasarlanmış kurallar kullanıyorsanız çalışma zamanı sorunlarını önlemek için ek ProGuard kuralları eklemenizi gerektirebilir. Örneğin, kodunuzun Java Reflection API aracılığıyla bir sınıfa başvurduğunu düşünelim. "Tam mod" kullanılmadığında R8, kodunuzda böyle bir işlem yapılmasa bile çalışma zamanında bu sınıfın nesnelerini incelemek ve değiştirmek istediğinizi varsayar ve sınıfı ve statik başlatıcısını otomatik olarak korur.

Ancak "tam mod" kullanıldığında R8 bu varsayımı yapmaz ve kodunuzun çalışma zamanında sınıfı hiçbir zaman kullanmadığını iddia ederse sınıfı uygulamanızın nihai DEX'inden kaldırır. Yani sınıfı ve statik başlatıcısını korumak istiyorsanız bunu yapmak için kurallar dosyanıza bir keep kuralı eklemeniz gerekir.

R8'in "tam modunu" kullanırken herhangi bir sorunla karşılaşırsanız olası bir çözüm için R8 SSS sayfasına bakın. Sorunu çözemezseniz lütfen hata bildirin.

Yığın izlemeyi geri çekme

R8 tarafından işlenen kodların farklı şekillerde değiştirilmesi, yığın izlemelerin anlaşılmasını zorlaştırabilir. Bunun nedeni, yığın izlemelerin kaynak koda tam olarak karşılık gelmemesidir. Hata ayıklama bilgileri saklanmadığı zaman satır numaralarında yapılan değişiklikler bu duruma neden olabilir. Bu durum, satır içi ekleme ve ana hat oluşturma gibi optimizasyonlardan kaynaklanabilir. En büyük katkıyı, sınıfların ve yöntemlerin bile adlarının değişeceği karartma sağlar.

R8, orijinal yığın izlemeyi kurtarmak için komut satırı araçları paketiyle birlikte sunulan yeniden izleme komut satırı aracını sağlar.

Uygulamanızın yığın izlemelerinin yeniden izlenmesini desteklemek için modülünüzün proguard-rules.pro dosyasına aşağıdaki kuralları ekleyerek derlemenin yeniden izleme için yeterli bilgiyi içerdiğinden emin olmanız gerekir:

-keepattributes LineNumberTable,SourceFile
-renamesourcefileattribute SourceFile

LineNumberTable özelliği, yöntemlerdeki konum bilgilerini, bu konumların yığın izlemelerinde basılması için saklar. SourceFile özelliği, tüm potansiyel çalışma zamanlarının konum bilgilerini gerçekten yazdırmasını sağlar. -renamesourcefileattribute yönergesi, yığın izlemelerdeki kaynak dosya adını yalnızca SourceFile olarak ayarlar. Eşleme dosyası orijinal kaynak dosyayı içerdiğinden, yeniden izleme sırasında gerçek orijinal kaynak dosyası adı gerekmez.

R8 her çalıştırıldığında bir mapping.txt dosyası oluşturur. Bu dosya, yığın izlerini orijinal yığın izleriyle eşleştirmek için gereken bilgileri içerir. Android Studio, dosyayı <module-name>/build/outputs/mapping/<build-type>/ dizinine kaydeder.

Uygulamanızı Google Play'de yayınlarken mapping.txt dosyasını uygulamanızın her sürümü için yükleyebilirsiniz. Android App Bundle kullanarak yayınlarken bu dosya otomatik olarak uygulama paketi içeriğinin bir parçası olarak eklenir. Ardından Google Play, kullanıcı tarafından bildirilen sorunlardan gelen yığın izlemelerini geri izleyerek Play Console'da inceleyebilmenizi sağlar. Daha fazla bilgi için çökmeyle sonuçlanan yığın izlemelerin (stack trace) kodunu gösterme ile ilgili Yardım Merkezi makalesine bakın.

R8 ile ilgili sorunları giderme

Bu bölümde, R8'i kullanarak sıkıştırma, karartma ve optimizasyonu etkinleştirirken karşılaşılan sorunları gidermeye yönelik bazı stratejiler açıklanmaktadır. Sorununuzun çözümünü aşağıda bulamazsanız R8 SSS sayfasını ve ProGuard'ın sorun giderme kılavuzunu da okuyun.

Kaldırılan (veya tutulan) kodun raporunu oluşturma

Belirli R8 sorunlarını gidermenize yardımcı olması için R8'in uygulamanızdan kaldırdığı tüm kodun raporunu görmek yararlı olabilir. Bu raporu oluşturmak istediğiniz her modül için özel kurallar dosyanıza -printusage <output-dir>/usage.txt ekleyin. R8'i etkinleştirdiğinizde ve uygulamanızı derlediğinizde, R8 belirttiğiniz yolu ve dosya adını içeren bir rapor oluşturur. Kaldırılan kodun raporu aşağıdaki gibi görünür:

androidx.drawerlayout.R$attr
androidx.vectordrawable.R
androidx.appcompat.app.AppCompatDelegateImpl
    public void setSupportActionBar(androidx.appcompat.widget.Toolbar)
    public boolean hasWindowFeature(int)
    public void setHandleNativeActionModesEnabled(boolean)
    android.view.ViewGroup getSubDecor()
    public void setLocalNightMode(int)
    final androidx.appcompat.app.AppCompatDelegateImpl$AutoNightModeManager getAutoNightModeManager()
    public final androidx.appcompat.app.ActionBarDrawerToggle$Delegate getDrawerToggleDelegate()
    private static final boolean DEBUG
    private static final java.lang.String KEY_LOCAL_NIGHT_MODE
    static final java.lang.String EXCEPTION_HANDLER_MESSAGE_SUFFIX
...

Bunun yerine , R8'in projenizin saklama kurallarına göre belirlediği giriş noktalarının raporunu görmek istiyorsanız özel kurallar dosyanıza -printseeds <output-dir>/seeds.txt ekleyin. R8'i etkinleştirip uygulamanızı oluşturduğunuzda R8, belirttiğiniz yolu ve dosya adını içeren bir rapor oluşturur. Tutulan giriş noktalarının raporu aşağıdakine benzer:

com.example.myapplication.MainActivity
androidx.appcompat.R$layout: int abc_action_menu_item_layout
androidx.appcompat.R$attr: int activityChooserViewStyle
androidx.appcompat.R$styleable: int MenuItem_android_id
androidx.appcompat.R$styleable: int[] CoordinatorLayout_Layout
androidx.lifecycle.FullLifecycleObserverAdapter
...

Kullanılmayan kaynakları kaldırmayla ilgili sorunları giderme

Kaynakları küçülttüğünüzde Derleme penceresinde uygulamadan kaldırılan kaynakların bir özeti gösterilir. (Gradle'dan ayrıntılı metin çıkışını görüntülemek için önce pencerenin sol tarafındaki Görünümü aç/kapat tıklamanız gerekir.) Örnek:

:android:shrinkDebugResources
Removed unused resources: Resource data reduced from 2570KB to 1711KB: Removed 33%
:android:validateDebugSigning

Gradle ayrıca <module-name>/build/outputs/mapping/release/ (ProGuard'ın çıkış dosyalarıyla aynı klasör) içinde resources.txt adlı bir teşhis dosyası oluşturur. Bu dosya, hangi kaynakların diğer kaynaklara referans verdiği ve hangi kaynakların kullanıldığı veya kaldırıldığı gibi ayrıntıları içerir.

Örneğin, @drawable/ic_plus_anim_016 dosyasının uygulamanızda neden hâlâ bulunduğunu öğrenmek için resources.txt dosyasını açıp dosya adını arayın. Aşağıdaki gibi başka bir kaynaktan referans aldığını görebilirsiniz:

16:25:48.005 [QUIET] [system.out] @drawable/add_schedule_fab_icon_anim : reachable=true
16:25:48.009 [QUIET] [system.out]     @drawable/ic_plus_anim_016

Şimdi @drawable/add_schedule_fab_icon_anim neden erişilebilir olduğunu bilmeniz gerekiyor. Daha yukarıya bakarsanız bu kaynağın, "Kök ulaşılabilir kaynaklar" bölümünde listelendiğini görürsünüz. Bu, add_schedule_fab_icon_anim için bir kod referansı olduğu anlamına gelir (yani, R.drawable kimliği erişilebilir kodda bulunmuştur).

Katı denetim kullanmıyorsanız dinamik olarak yüklenen kaynakların kaynak adlarını oluşturmak için kullanılabilecek gibi görünen dize sabitleri varsa kaynak kimlikleri erişilebilir olarak işaretlenebilir. Bu durumda, kaynak adı için derleme çıkışını ararsanız aşağıdaki gibi bir mesaj görebilirsiniz:

10:32:50.590 [QUIET] [system.out] Marking drawable:ic_plus_anim_016:2130837506
    used because it format-string matches string pool constant ic_plus_anim_%1$d.

Bu dizelerden birini görürseniz ve dizenin ilgili kaynağı dinamik olarak yüklemek için kullanılmadığından eminseniz saklanacak kaynakların özelleştirilmesi ile ilgili bölümde açıklandığı gibi derleme sistemine bu kaynağı kaldırması için tools:discard özelliğini kullanabilirsiniz.