Förbättra APK-analysatorn

Wojtek Kaliciński

Follow

23 nov, 2016 – 6 min read

En av mina favoriter bland de senaste tilläggen till Android Studio är APK Analyzer, som du hittar i toppmenyn under Build → Analyze APK.

Pro-tip: Du kan också dra och släppa APK-filer till redigeraren för att öppna dem

APK Analyzer låter dig öppna och inspektera innehållet i alla APK-filer som du har på din dator, antingen byggda från ditt lokala Android Studio-projekt eller hämtade från din byggserver eller ett annat artefaktförråd. Den behöver inte vara byggd från något projekt som du har öppet i Android Studio och du behöver inte källkoden för just den APK-filen.

Anmärkningar: APK Analyzer fungerar bäst med release-builds. Om du behöver analysera en felsökningsbyggnad av din app ska du se till att du använder en APK som inte är instrumenterad för Instant Run. För att få fram den kan du använda kommandot Build → Build APK. Du kan se om du har öppnat en APK som är instrumenterad för Instant Run genom att kontrollera om det finns en instant-run.zip-fil i arkivet.

Användning av APK-analysatorn är ett utmärkt sätt att snoka runt i APK-filer och lära sig mer om deras struktur, verifiera filinnehållet innan du släpper eller felsöka vissa vanliga problem, inklusive APK-storlek och DEX-problem.

Apk-analysatorn kan ge dig en hel del användbar, uppföljningsbar information om appens storlek. Överst på skärmen kan du se Raw File Size (rå filstorlek) som bara är APK-storleken på disken. Nedladdningsstorleken visar en uppskattning av hur mycket data som kommer att användas för att ladda ner din app genom att ta hänsyn till den komprimering som tillämpas av Play Store.

Listan över filer och mappar är sorterad efter total storlek i fallande ordning. Detta gör den utmärkt för att identifiera de lågt hängande frukterna för optimering av APK-storleken. Varje gång du borrar ner i en mapp kan du se de resurser och andra enheter som tar upp mest utrymme i din APK.

Resurser sorterade i fallande ordning efter storlek

I det här exemplet kunde jag, när jag undersökte en APK för att hitta möjliga storleksminskningar, genast märka att en PNG-animation med 3 ramar är den enskilt största saken i våra ritbara resurser och väger in på 1.5 MB, och det är bara för densiteten xxhdpi!

Med tanke på att dessa bilder ser ut att vara perfekta kandidater för lagring som vektorer, hittade vi källfilerna för konstverket och importerade dem som VectorDrawables med hjälp av det nya PSD-stödet i verktyget för import av vektortillgångar i Android Studio 2.2.

Då vi gick igenom samma process för den andra återstående animationen (instruction_touch_*.png) och tog bort dessa PNG-filer i alla densiteter, kunde vi spara över 5 MB. För att bibehålla bakåtkompatibilitet använde vi VectorDrawableCompat från supportbiblioteket.

Om vi tittade på andra resursmappar var det lätt att upptäcka några okomprimerade WAV-filer som kunde konverteras till OGG, vilket innebar ännu större besparingar utan att röra en kodrad.

Bläddring av andra mappar i APK

Nästan på listan över saker att kontrollera var mappen lib/, som innehåller inhemska bibliotek för de tre ABI:er som vi stöder.

Beslutet fattades att använda stödet för APK splits i vårt Gradle-bygge för att skapa separata versioner av appen för varje ABI.

Jag tittade snabbt över AndroidManifest.xml härnäst och märkte att <application> saknar attributet android:extractNativeLibs. Att ställa in det här attributet till false kan spara lite utrymme på enheten eftersom det förhindrar att kopiera ut de ursprungliga biblioteken från APK:n till filsystemet. Det enda kravet är att filerna är sidjusterade och lagras okomprimerade i APK:n, vilket stöds med det nya paketeringsverktyget i Android Gradle-pluginet version 2.2.0+.

Den fullständiga AndroidManifest.xml som den visas i APK Analyzer

Efter att ha gjort dessa ändringar var jag nyfiken på att se hur den nya versionen av appen står sig i jämförelse med den tidigare. För att göra det kollade jag upp källkoden från den git commit som jag började med, kompilerade APK:n och sparade den i en annan mapp. Jag använde sedan funktionen Jämför med… för att se en uppdelning av storleksskillnaderna mellan den gamla och den nya versionen.

APK-jämförelse – få tillgång till den via knappen längst upp till höger

Vi har gjort stora framsteg när det gäller resurserna och de inbyggda biblioteken, och sparade sammanlagt 17 MB med mycket små förändringar i appen. Jag kan dock se att vår DEX-storlek gick tillbaka, med classes2.dex som växte med 400KB.

Buggning av DEX-problem

I det här fallet kom skillnaden från att vi uppgraderade våra beroenden till nyare versioner och lade till nya bibliotek. Proguard och Multidex var redan aktiverade för våra byggen så det finns inte mycket att göra åt vår DEX-storlek. Ändå är APK analyzer ett utmärkt verktyg för att felsöka eventuella problem med den här inställningen, särskilt när du aktiverar Multidex eller Proguard för ditt projekt för första gången.

Exploatering av innehållet i klasser.dex

När du klickar på en DEX-fil visas en sammanfattning av hur många klasser och metoder den definierar och hur många totala referenser den innehåller (det är referenser som räknas mot 64K-gränsen i en enda DEX-fil). I den här exempelskärmsbilden är appen precis på väg att nå gränsen, vilket innebär att den kommer att behöva MultiDex för att dela upp klasserna i separata filer inom en snar framtid.

Du kan borra ner i paketen för att se vilka av dem som använder alla referenser. I det här fallet kan vi se att supportbiblioteket och Google Play Services är huvudorsakerna till den här situationen:

Referensantal per paket

När du har aktiverat MultiDex och kompilerat appen kommer du att märka en andra classes2.dex-fil (och eventuellt classes3.dex, och så vidare). MultiDex-lösningen i Android gradle-pluginet räknar ut vilka klasser som behövs för att starta din app och lägger dem i den primära classes.dex-filen, men i det sällsynta fallet när det inte fungerar och du får ett ClassNotFoundException kan du använda APK Analyzer för att inspektera DEX-filerna och sedan tvinga de saknade klasserna att läggas in i den primära DEX-filen.

Du kommer att stöta på liknande problem när du aktiverar Proguard och använder klasser eller metoder med hjälp av reflektion eller från XML-layouter. APK Analyzer kan hjälpa dig att verifiera att din Proguard-konfiguration är korrekt, genom att du enkelt kan kontrollera om de metoder och klasser du behöver finns i APK:n och om de döps om (förvrängs). Du kan också se till att de klasser du vill ha bort faktiskt tas bort och inte tar upp ditt värdefulla antal referensmetoder.

Vi är nyfikna på att höra vilka andra användningsområden du hittar för APK Analyzer och vilka andra funktioner du skulle vilja se integrerade i verktyget!

Lämna en kommentar