Festlegen, welche Ressourcen behalten werden sollen

Wenn Sie die App-Optimierung aktivieren, wird der Optimierer über die Einstellung isShrinkResources = true angewiesen, nicht verwendete Ressourcen zu entfernen. Dadurch wird die Größe Ihrer App reduziert. Die Ressourcenkomprimierung funktioniert nur in Verbindung mit der Codekomprimierung. Wenn Sie also Ressourcen optimieren, müssen Sie auch isMinifyEnabled = true festlegen, z. B. so:

buildTypes {
    release {
        isMinifyEnabled = true
        isShrinkResources = true
        ...
    }
}

Wenn Sie bestimmte Ressourcen behalten oder verwerfen möchten, erstellen Sie eine XML-Datei vom Typ keep in Ihren Projektressourcen, z. B. res/raw/my.package.keep.xml. Die KEEP-Datei besteht aus den folgenden Komponenten:

  • <resources>-Tag: Enthält alle untergeordneten Ressourcenelemente und Attribute zum Beibehalten oder Verwerfen.
  • tools:keep-Attribut: Akzeptiert eine durch Kommas getrennte Liste von Ressourcennamen, die die zu behaltenden Ressourcen angeben.
  • tools:discard-Attribut: Akzeptiert eine durch Kommas getrennte Liste von Ressourcennamen, die die zu verwerfenden Ressourcen angeben.

Verwenden Sie das Sternchen als Platzhalter, um auf mehrere Ressourcen im selben Ordner zu verweisen, z. B.:

<?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" />

Das Angeben, welche Ressourcen verworfen werden sollen, mag überflüssig erscheinen, wenn Sie sie stattdessen löschen könnten. Das Verwerfen von Ressourcen kann jedoch bei der Verwendung von Buildvarianten nützlich sein.

Targeting auf bestimmte Build-Varianten

Wenn Sie Ressourcen nur in einigen Buildvarianten entfernen möchten, legen Sie alle Ressourcen im gemeinsamen Projektverzeichnis ab und erstellen Sie dann für jede Buildvariante eine separate my.package.build.variant.keep.xml-Datei im Ressourcenverzeichnis der Variante. Geben Sie in der Datei „keep“ manuell Ressourcen an, die entfernt werden sollen, wenn eine bestimmte Ressource im Code verwendet wird (und daher nicht vom Komprimierungstool entfernt wird), Sie aber wissen, dass sie für die jeweilige Buildvariante nicht verwendet wird.

Nicht verwendete alternative Ressourcen entfernen

Der Optimierer entfernt nur Ressourcen, auf die nicht durch Ihren App-Code verwiesen wird. Das bedeutet, dass alternative Ressourcen für verschiedene Gerätekonfigurationen nicht entfernt werden.

Verwenden Sie die Android Gradle-Eigenschaft resConfigs in der Moduldatei build.gradle Ihrer App, um alternative Ressourcendateien zu entfernen, die Ihre App nicht benötigt.

Wenn Sie beispielsweise eine Bibliothek mit Sprachressourcen verwenden (z. B. Google Play-Dienste), enthält Ihre App alle übersetzten Sprachstrings für die Meldungen in diesen Bibliotheken, unabhängig davon, ob der Rest Ihrer App in dieselben Sprachen übersetzt ist oder nicht. Wenn Sie nur die Sprachen beibehalten möchten, die Ihre App offiziell unterstützt, geben Sie diese mithilfe des Attributs resConfigs an. Alle Ressourcen für nicht angegebene Sprachen werden entfernt.

In den folgenden Snippets wird gezeigt, wie Sie Ihre Sprachressourcen auf Englisch und Französisch beschränken:

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

oder

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

Wenn Sie eine App im Android App Bundle-Format (AAB) veröffentlichen, werden beim Installieren der App standardmäßig nur die auf dem Gerät des Nutzers konfigurierten Sprachen heruntergeladen. Ebenso sind nur Ressourcen, die der Bildschirmdichte des Geräts entsprechen, und native Bibliotheken, die dem ABI des Geräts entsprechen, im Download enthalten. Weitere Informationen finden Sie unter Konfigurations-APK-Typen wieder aktivieren oder deaktivieren.

Bei älteren Apps, die mit APKs veröffentlicht werden (vor August 2021 erstellt), können Sie die Bildschirmdichte oder ABI-Ressourcen anpassen, die in Ihr APK aufgenommen werden sollen. Dazu müssen Sie mehrere APKs erstellen, die auf unterschiedliche Gerätekonfigurationen ausgerichtet sind.

Konflikte beim Zusammenführen von Ressourcen vermeiden

Standardmäßig werden mit dem Android Gradle-Plug-in (AGP) Ressourcen mit identischem Namen zusammengeführt, z. B. Drawables mit demselben Namen, die sich in verschiedenen Ressourcenordnern befinden. Dieses Verhalten wird nicht durch die Property shrinkResources gesteuert und kann nicht deaktiviert werden, da es erforderlich ist, um Fehler zu vermeiden, wenn mehrere Ressourcen den Namen haben, auf den Ihr Code verweist.

Die Ressourcenzusammenführung erfolgt nur, wenn zwei oder mehr Dateien denselben Ressourcennamen, -typ und -qualifizierer haben. AGP wählt die Datei aus, die es als beste Wahl unter den Duplikaten identifiziert (basierend auf einer unten beschriebenen Prioritätsreihenfolge) und übergibt nur diese eine Ressource an AAPT für die Verteilung im endgültigen Build-Artefakt.

AGP sucht an folgenden Orten nach doppelten Ressourcen:

  • Hauptressourcen, die mit dem Hauptquellensatz verknüpft sind, befinden sich in der Regel unter src/main/res/.
  • Varianten-Overlays vom Build-Typ und den Build-Varianten
  • Abhängigkeiten des Library Project

AGP führt doppelte Ressourcen in der folgenden absteigenden Prioritätsreihenfolge zusammen:

„Dependencies“ (Abhängigkeiten) → „Main“ (Haupt) → „Build flavor“ (Build-Variante) → „Build type“ (Build-Typ)

Wenn sich beispielsweise eine doppelte Ressource sowohl in Ihren Hauptressourcen als auch in einer Build-Variante befindet, wählt Gradle die Ressource in der Build-Variante aus.

Wenn identische Ressourcen im selben Quellsatz vorhanden sind, kann Gradle sie nicht zusammenführen und gibt einen Fehler beim Zusammenführen von Ressourcen aus. Das kann passieren, wenn Sie in der Property sourceSet Ihrer Moduldatei build.gradle mehrere Quellsätze definieren, z. B. wenn sowohl src/main/res/ als auch src/main/res2/ identische Ressourcen enthalten.

Fehlerbehebung bei Entfernung von Ressourcen

Wenn Sie Ressourcen verkleinern, wird im Fenster Build eine Zusammenfassung der aus der App entfernten Ressourcen angezeigt. Klicken Sie links im Fenster auf Ansicht umschalten, um eine detaillierte Textausgabe von Gradle aufzurufen. Beispiel:

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

Gradle erstellt außerdem eine Diagnosedatei namens resources.txt in <module-name>/build/outputs/mapping/release/ (im selben Ordner wie die Ausgabedateien von ProGuard). Die Datei enthält Details dazu, welche Ressourcen auf andere Ressourcen verweisen und welche Ressourcen verwendet oder entfernt werden.

Wenn Sie beispielsweise wissen möchten, warum @drawable/ic_plus_anim_016 noch in Ihrer App vorhanden ist, öffnen Sie die Datei resources.txt und suchen Sie nach diesem Dateinamen. Möglicherweise wird auf die Ressource von einer anderen Ressource aus verwiesen:

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

Sie müssen jetzt wissen, warum @drawable/add_schedule_fab_icon_anim erreichbar ist. Wenn Sie nach oben suchen, finden Sie die Ressource in resources.txt unter der Überschrift Die über die Wurzel erreichbaren Ressourcen sind:.

Das bedeutet, dass es eine Codereferenz auf add_schedule_fab_icon_anim gibt, d. h., die R.drawable-ID wurde im erreichbaren Code gefunden.

Sofern Sie keine strenge Prüfung verwenden, können Ressourcen-IDs als erreichbar markiert werden, wenn es Stringkonstanten gibt, die so aussehen, als könnten sie zum Erstellen von Ressourcennamen für dynamisch geladene Ressourcen verwendet werden. Wenn Sie in diesem Fall in der Build-Ausgabe nach dem Ressourcennamen suchen, sehen Sie möglicherweise eine Meldung wie diese:

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

Wenn Sie einen dieser Strings sehen und sicher sind, dass er nicht zum dynamischen Laden der entsprechenden Ressource verwendet wird, verwenden Sie das Attribut tools:discard in Ihrer Keep-Datei, um das Build-System zum Entfernen der Ressource aufzufordern.