Was bewirken Proguard Rules und worauf muss man achten?
Die sogenannte Proguard Rules können ein sehr mächtiges Werkzeug darstellen. Möchte man die entwickelte App in der Appgröße verkleinern, den Quellcode verschleiern oder im Allgemeinen optimieren, sind Proguard Rules ein geeignetes Werkzeug dafür. Wie genau das funktioniert, was genau Proguard Rules sind und wie man diese im Projekt verwendet, wird in diesem Blogbeitrag näher gebracht.
Inhaltsverzeichnis
Was sind Proguard Rules?
„Shrink, obfuscate, and optimize your app“. So wird es auf der Developer-Website von Android benannt. Üblicherweise werden die Proguard Rules für den release-Build der App verwendet, um dort die Vorteile nutzen zu können. Beispielsweise kann in den Proguard Rules das shrinking aktiviert werden, um ungenutzten Code und Ressourcen automatisch entfernen zu lassen. Sofern das shrinking aktiviert wurde, erhält man automatisch den Vorteil der sogenannten obfuscation (Verschleierung). Diese Verschleierung verkürzt die Namen der Klassen, sowie Funktionen und Variablen. Dieses Vorgehen wird später noch in dem Kapitel Learnings und Fallstricke interessant. Zudem gibt es dann noch die optimization, welche weitere Strategien zur Reduzierung der Appgröße anwenden.
Wie können Proguard Rules im Projekt eingesetzt werden?
Um shrinking, obfuscation und optimization im Projektcode zu aktivieren, wird empfohlen, dies in der build.gradle-File auf Projektebene hinzuzufügen. Einmal in Groovy:

Und einmal in Kotlin:

Zudem können entsprechende Proguard Rules in der proguard-rules.pro angegeben werden. Standardmäßig existiert im App-Modul und bei jedem neu angelegten Modul eine proguard-rules.pro-Datei. Diese wird automatisch erstellt, besitzt aber keinen Content. Beispielsweise kann dort angegeben werden, welche Dateien „behalten“ werden – also nicht von der obfuscation beeinflusst werden sollen. Dies wird unter https://developer.android.com/studio/build/shrink-code#keep-code näher erläutert.
Worauf muss bei einem Multi Module-Projekt oder beim Entwickeln einer Library geachtet werden?
An sich auf nicht viel. Es gibt lediglich einen Unterschied zwischen den Anweisungen
- proguardFiles
und
- consumerProguardFiles
Mit der proguardFiles-Anweisung werden die Regeln bezüglich Proguard definiert und für das Modul und dessen Abhängigkeiten angewandt.
Mit der consumerProguardFiles-Anweisung werden ebenfalls die Regeln bezüglich Proguard definiert. Allerdings können diese auf das Modul vom Consumer (Verbraucher bzw. eher Benutzer) angewendet werden. Typischerweise passiert dies bei Modulen, die als dependency (Abhängigkeit) von anderen Modulen verwendet werden oder beim Entwickeln einer Bibliothek.
Android-App-Entwicklung

Die verschiedenen Keep-Anweisungen
Es existieren verschiedene keep-Anweisungen, die in einem proguard-File genutzt werden können:
Anweisung | Bedeutung |
keep | Deaktiviert die gesamte Proguard-Funktionalität. Kein shrinking und auch keine obfuscation der Klassen und Klassenmember. |
keepclassmembers | Die Klassenmember bleiben vom shrinking und der obfuscation verschont. |
keepnames | Es wird lediglich die obfuscation ausgeschaltet. |
keepclassmembernames | Ungenutzt Klassen werden entfernt.
Die übrig gebliebenen Klassen werden umbenannt. Die übrig gebliebenen Klassenmember behalten ihre Namen. |
Learnings und Fallstricke
Hier spreche ich ausnahmsweise mal aus der Ich-Perspektive: Und zwar ist mir während des Projektalltags ein Ticket zugewiesen worden, warum denn der Store-Build nicht mehr funktioniert. Hintergrund: Ich habe die App bzw. das Projekt modularisiert. Dahingehend wurden einige Klassen in die entsprechenden Module verschoben. Innerhalb des Projekts existieren verschiedene Build Variants, welche unter anderem eine dev- und eine store-Umgebung abbilden. Der Build in der dev-Umgebung hat einwandfrei funktioniert. Allerdings sollte die App dann mit dem Feature der Modularisierung released werden. Dies hat aus Gründen nicht funktioniert.
Ein Grund waren offensichtlich die Proguard Rules. Dort gab es bspw. Probleme bei Gson mit dem JsonSerializer und JsonDeserializer. Dort musste dann in den Proguard Rules folgendes definiert werden:

Das Projekt und die App konnten dann ausgeführt werden, funktionierten aber noch nicht einwandfrei. Es bestand weiterhin ein Bug, welcher die App nicht nutzbar machte. Nach einem Tag intensiver Detektivarbeit kam heraus, dass eine Annotation bei einer Datenklasse fehlte, die aber vor der Modularisierung nicht benötigt wurde. Was ist passiert?
Die obfuscation hat dafür gesorgt, dass das Feld der Datenklasse so verschleiert wurde, dass es nicht mehr dem Feld des JSON-Objekts entsprach. Somit konnte die Datenklasse nicht richtig geparst werden und das Feld des Objekts war immer leer. Da dieses aber für entsprechende Verzweigungen innerhalb der App verwendet wird, war dies ausschlaggebend für das Fehlverhalten der Anwendung.
Fazit
Das Verwenden von Proguard Rules im release-Build zur Optimierung der Ressourcen ist äußerst sinnvoll. Vor allem das Reduzieren der Appgröße ist ein großer Vorteil. Zudem bringt die obfuscation einen weiteren wichtigen Vorteil mit sich. Dadurch, dass der Code verschleiert wird, macht es das Reverse Engineering der App schwieriger und somit die App sicherer.
Hinweis: Dies ist allerdings kein Alleinstellungsmerkmal und kein vollumfängliches Vorgehen, die App sicher zu entwickeln.
Dennoch sollte man sich bewusst sein, was die Proguard Rules machen und welche Auswirkungen diese auf den Programmcode haben.