Użytkownicy często unikają pobierania aplikacji, które wydają się za duże, zwłaszcza na rynkach wschodzących, na których urządzenia łączą się z niestabilnymi sieciami 2G i 3G, lub opracowują abonamenty z limitami danych. Na tej stronie opisujemy, jak zmniejszyć rozmiar pliku do pobrania aplikacji, aby umożliwić jej pobranie większej liczbie użytkowników.
Przesyłanie aplikacji za pomocą pakietów Android App Bundle
Prześlij aplikację jako pakiet Android App Bundle, aby od razu zmniejszyć jej rozmiar podczas publikowania w Google Play. Android App Bundle to format przesyłania, który uwzględnia cały skompilowany kod i zasoby aplikacji, ale opóźnia wygenerowanie pliku APK i podpisanie go w Google Play.
Model obsługi aplikacji w Google Play korzysta z Twojego pakietu aplikacji, aby generować i przesyłać zoptymalizowane pliki APK dla każdej konfiguracji urządzenia użytkownika. Dzięki temu użytkownicy pobierają tylko kod i zasoby potrzebne do uruchomienia aplikacji. Nie musisz tworzyć, podpisywać ani zarządzać wieloma plikami APK, aby obsługiwać różne urządzenia. Użytkownicy otrzymują mniejsze, bardziej zoptymalizowane pliki do pobrania.
Google Play stosuje ograniczenie rozmiaru skompresowanego pliku do pobrania na poziomie 200 MB w przypadku aplikacji publikowanych w pakietach aplikacji. Korzystając z funkcji Play Feature Delivery i Play Asset Delivery, możesz używać w większym rozmiarze, ale zwiększenie rozmiaru aplikacji może negatywnie wpłynąć na jej sukces i zwiększyć liczbę odinstalowań. Dlatego zalecamy zastosowanie wskazówek opisanych na tej stronie w celu jak największego zmniejszenia rozmiaru pobieranej aplikacji.
Struktura pliku APK
Zanim zmniejszysz rozmiar aplikacji, warto poznać strukturę pliku APK. Plik APK składa się z archiwum ZIP zawierającego wszystkie pliki, z których składa się aplikacja. Te pliki obejmują pliki klas Java, pliki zasobów i plik zawierający skompilowane zasoby.
Plik APK zawiera te katalogi:
META-INF/
: zawiera pliki podpisuCERT.SF
iCERT.RSA
, a także plik manifestuMANIFEST.MF
.assets/
: zawiera zasoby aplikacji, które aplikacja może pobrać za pomocą obiektuAssetManager
.res/
: zawiera zasoby, które nie są zgrupowane wresources.arsc
.lib/
: zawiera skompilowany kod specyficzny dla warstwy oprogramowania procesora. Ten katalog zawiera podkatalog na potrzeby poszczególnych typów platform, takich jakarmeabi
,armeabi-v7a
,arm64-v8a
,x86
,x86_64
czymips
.
Plik APK zawiera też te pliki: Wymagany jest tylko element AndroidManifest.xml
:
resources.arsc
: zawiera skompilowane zasoby. Ten plik zawiera zawartość XML ze wszystkich konfiguracji folderures/values/
. Narzędzie do pakowania wyodrębnia te treści XML, kompiluje je w postaci binarnej i archiwizuje. Te treści obejmują ciągi tekstowe i style w różnych językach, a także ścieżki do treści, które nie są zawarte bezpośrednio w plikuresources.arsc
, takich jak pliki układu i obrazy.classes.dex
: zawiera klasy skompilowane w formacie pliku DEX obsługiwanym przez maszynę wirtualną Dalvik lub ART.AndroidManifest.xml
: zawiera podstawowy plik manifestu Androida. Ten plik zawiera nazwę, wersję i prawa dostępu aplikacji oraz odniesienia do plików bibliotek. Plik wykorzystuje binarny format XML dla Androida.
Zmniejsz liczbę i rozmiar zasobów
Rozmiar pliku APK ma wpływ na szybkość wczytywania aplikacji, ilość wykorzystywanej pamięci i poziom zużycia energii. Możesz zmniejszyć rozmiar pliku APK, zmniejszając liczbę i rozmiar zasobów, które zawiera. Możesz na przykład usuwać zasoby, których aplikacja już nie używa, oraz używać skalowalnych obiektów Drawable
zamiast plików graficznych. W tej sekcji omawiamy te metody oraz inne sposoby zmniejszania liczby zasobów w aplikacji, aby zmniejszyć ogólny rozmiar pliku APK.
Usuń nieużywane zasoby
Narzędzie lint
, czyli analizator kodu stałego zawarty w Android Studio, wykrywa zasoby w folderze res/
, do których nie odwołuje się kod. Gdy narzędzie lint
wykryje w Twoim projekcie potencjalnie niewykorzystany zasób, wyświetli komunikat podobny do tego:
res/layout/preferences.xml: Warning: The resource R.layout.preferences appears to be unused [UnusedResources]
Biblioteki dodane do kodu mogą zawierać nieużywane zasoby. Gradle może automatycznie usuwać zasoby w Twoim imieniu, jeśli włączysz shrinkResources
w pliku build.gradle.kts
Twojej aplikacji.
Kotlin
android { // Other settings. buildTypes { getByName("release") { minifyEnabled = true shrinkResources = true proguardFiles(getDefaultProguardFile('proguard-android.txt'), "proguard-rules.pro") } } }
Groovy
android { // Other settings. buildTypes { release { minifyEnabled true shrinkResources true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } }
Aby używać shrinkResources
, włącz kompresowanie kodu. Podczas procesu kompilacji R8 najpierw usuwa nieużywany kod. Następnie wtyczka Androida do obsługi Gradle usuwa nieużywane zasoby.
Więcej informacji o skracaniu kodu i zasobów oraz innych sposobach zmniejszania rozmiaru pliku APK w Android Studio znajdziesz w artykule Skracanie, zaciemnianie i optymalizowanie aplikacji.
W pliku Android Gradle Plugin w wersji 7.0 lub nowszej możesz deklarować konfiguracje obsługiwane przez aplikację. Gradle przekazuje te informacje do systemu kompilacji za pomocą rodzaju resourceConfigurations
i opcji defaultConfig
. System kompilacji zapobiega wtedy pojawianiu się w pliku APK zasobów z innych nieobsługiwanych konfiguracji, co zmniejsza jego rozmiar. Więcej informacji o tej funkcji znajdziesz w artykule Usuwanie nieużywanych zasobów alternatywnych.
Minimalizowanie wykorzystania zasobów z bibliotek
Podczas tworzenia aplikacji na Androida zwykle używasz zewnętrznych bibliotek, aby zwiększyć użyteczność i wszechstronność aplikacji. Możesz na przykład skorzystać z AndroidaX, by zwiększyć wygodę użytkowników na starszych urządzeniach, lub skorzystać z Usług Google Play, by pobrać automatyczne tłumaczenia tekstu w aplikacji.
Jeśli biblioteka jest przeznaczona do serwera lub komputera, może zawierać wiele obiektów i metod, których Twoja aplikacja nie potrzebuje. Aby uwzględnić tylko te części biblioteki, których potrzebuje Twoja aplikacja, możesz edytować pliki biblioteki, jeśli licencja pozwala na modyfikowanie biblioteki. Możesz też użyć alternatywnej biblioteki dostosowanej do urządzeń mobilnych, by dodać do swojej aplikacji określone funkcje.
Dekodowanie natywnego obrazu animowanego
W Androidzie 12 (poziom interfejsu API 31) interfejs API NDKImageDecoder
został rozszerzony o funkcję dekodowania wszystkich klatek i danych dotyczących ich czasu trwania w przypadku obrazów w formacie animowanego GIF-a i animowanego WebP.
Zamiast bibliotek innych firm używaj bibliotek ImageDecoder
, aby zmniejszyć rozmiar pliku APK i korzystać z przyszłych aktualizacji dotyczących zabezpieczeń i wydajności.
Więcej informacji o interfejsie API ImageDecoder
znajdziesz w dokumentacji API reference
oraz w przykładowym pliku na GitHubie.
Obsługują tylko określone wartości gęstości.
Android obsługuje różne gęstości ekranu, takie jak:
ldpi
mdpi
tvdpi
hdpi
xhdpi
xxhdpi
xxxhdpi
Chociaż Android obsługuje te gęstości, nie musisz eksportować zasobów rastrowych do każdej gęstości.
Jeśli wiesz, że tylko niewielki odsetek Twoich użytkowników korzysta z urządzeń o określonej gęstości ekranu, zastanów się, czy nie musisz uwzględniać w swojej aplikacji zasobów o określonej gęstości ekranu. Jeśli nie dodasz zasobów dla określonej gęstości ekranu, Android automatycznie skaluje istniejące zasoby, które zostały pierwotnie zaprojektowane pod kątem innych gęstości ekranu.
Jeśli Twoja aplikacja potrzebuje tylko obrazów pomniejszonych, możesz zaoszczędzić jeszcze więcej miejsca, korzystając z jednego wariantu obrazu w formacie drawable-nodpi/
. Zalecamy dodanie do aplikacji co najmniej xxhdpi
wersji obrazu.
Więcej informacji o gęstości ekranu znajdziesz w artykule [GA4] Rozmiary i gęstości ekranu.
Używanie obiektów do rysowania
Niektóre obrazy nie wymagają statycznych zasobów obrazów. Platforma może zamiast tego rysować obraz dynamicznie w czasie działania. Obiekty Drawable
(lub <shape>
w XML) zajmują w pliku APK bardzo mało miejsca. Dodatkowo obiekty XML Drawable
generują obrazy monochromatyczne zgodne z wytycznymi Material Design.
Ponowne używanie zasobów
Możesz dołączyć osobny zasób dla wersji obrazu, np. zabarwionych, zacienionych lub obróconych wersji tego samego obrazu. Zalecamy jednak ponowne używanie tego samego zestawu zasobów i dostosowywanie go w razie potrzeby w czasie wykonywania.
Android udostępnia kilka narzędzi do zmiany koloru zasobu za pomocą atrybutów android:tint
i tintMode
.
Możesz też pominąć zasoby, które są tylko obraconym odpowiednikiem innego zasobu. Ten fragment kodu przedstawia przykład zmiany kciuka w górę w kciuk w dół przez obrócenie środka obrazu i 180 stopni:
<?xml version="1.0" encoding="utf-8"?> <rotate xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/ic_thumb_up" android:pivotX="50%" android:pivotY="50%" android:fromDegrees="180" />
Renderowanie z kodu
Rozmiar pliku APK możesz też zmniejszyć, programowo renderując obrazy. Renderowanie proceduralne zwalnia miejsce, ponieważ nie musisz już przechowywać pliku graficznego w pliku APK.
Cruncha, pliki PNG
Narzędzie aapt
może optymalizować zasoby obrazów umieszczone w res/drawable/
za pomocą bezstratnej kompresji podczas procesu kompilacji. Na przykład narzędzie aapt
może przekonwertować plik PNG w kolorze rzeczywistym, który nie wymaga więcej niż 256 kolorów, do 8-bitowego pliku PNG z paletą kolorów. Dzięki temu obraz będzie miał taką samą jakość, ale zajmie mniej miejsca w pamięci.
aapt
ma te ograniczenia:
- Narzędzie
aapt
nie zmniejsza plików PNG znajdujących się w folderzeasset/
. - Aby narzędzie
aapt
mogło zoptymalizować pliki graficzne, muszą one zawierać maksymalnie 256 kolorów. - Narzędzie
aapt
może rozszerzyć już skompresowane pliki PNG. Aby temu zapobiec, możesz użyć flagiisCrunchPngs
, aby wyłączyć ten proces w przypadku plików PNG:
Kotlin
buildTypes.all { isCrunchPngs = false }
Odlotowe
buildTypes.all { isCrunchPngs = false }
Kompresowanie plików PNG i JPEG
Możesz zmniejszyć rozmiar pliku PNG bez utraty jakości obrazu, korzystając z takich narzędzi jak pngcrush, pngquant czy zopflipng. Wszystkie te narzędzia mogą zmniejszyć rozmiar pliku PNG, zachowując przy tym jakość obrazu.
Narzędzie pngcrush
jest szczególnie skuteczne. To narzędzie przechodzi przez filtry PNG i parametry zlib (Deflate), używając każdej kombinacji filtrów i parametrów do kompresji obrazu.
Następnie wybiera konfigurację, która daje najmniejsze wyjście po skompresowaniu.
Aby skompresować pliki JPEG, możesz użyć narzędzi takich jak packJPG i guetzli.
Używanie formatu pliku WebP
Zamiast plików PNG lub JPEG możesz też używać formatu WebP. Format WebP zapewnia stratną kompresję i przezroczystość, podobnie jak JPG i PNG, a może zapewniać lepszą kompresję niż JPEG czy PNG.
Za pomocą Android Studio możesz przekonwertować istniejące obrazy BMP, JPG, PNG lub GIF statyczny do formatu WebP. Więcej informacji znajdziesz w artykule Tworzenie obrazów WebP.
Używanie grafik wektorowych
Grafiki wektorowej możesz używać do tworzenia ikon niezależnych od rozdzielczości i innych skalowanych multimediów.
Dzięki nim możesz znacznie zmniejszyć rozmiar pliku APK. Obrazy wektorów są reprezentowane w Androidzie jako obiekty VectorDrawable
. W przypadku obiektu VectorDrawable
plik o rozmaju 100 bajtów może wygenerować ostry obraz o rozmiarze ekranu.
Jednak system potrzebuje znacznie więcej czasu na renderowanie każdego obiektu VectorDrawable
, a większe obrazy wyświetlają się jeszcze dłużej.
Dlatego rozważ użycie grafik wektorowych tylko wtedy, gdy wyświetlasz małe obrazy.
Więcej informacji o pracy z obiektami VectorDrawable
znajdziesz w sekcji Elementy rysowalne.
Używanie grafiki wektorowej do obrazów animowanych
Nie używaj pliku AnimationDrawable
do tworzenia animacji klatkowych, ponieważ wymaga to dołączenia osobnego pliku bitmapy do każdej klatki animacji, co znacznie zwiększa rozmiar pliku APK.
Zamiast tego użyj funkcji
AnimatedVectorDrawableCompat
, aby utworzyć animowane wektorowe obiekty rysunkowe.
Ograniczanie kodu natywnego i Java
Aby zmniejszyć rozmiar kodu natywnego i Java w aplikacji, możesz użyć tych metod.
Usuwanie niepotrzebnego wygenerowanego kodu
Pamiętaj, aby zapoznać się z zawartością każdego kodu, który jest generowany automatycznie. Na przykład wiele narzędzi do buforowania protokołów generuje nadmierną liczbę metod i klas, co może podwoić lub potroić rozmiar aplikacji.
Unikaj enumeracji
Pojedynczy typ enum może zwiększyć rozmiar pliku classes.dex
aplikacji o 1,0–1,4 KB. W przypadku złożonych systemów lub bibliotek współdzielonych te dodatki mogą szybko się kumulować. Jeśli to możliwe, użyj adnotacji @IntDef
i skracania kodu, aby usunąć wyliczenia i przekształcić je w liczby całkowite. Ta konwersja zachowuje wszystkie korzyści związane z bezpieczeństwem typów enum.
Zmniejszanie rozmiaru natywnych plików binarnych
Jeśli aplikacja używa kodu natywnego i Android NDK, możesz też zmniejszyć rozmiar wersji aplikacji, optymalizując kod. Dwie przydatne techniki to usuwanie symboli debugowania i niewyodrębnianie bibliotek natywnych.
Usuwanie symboli debugowania
Używanie symboli debugowania ma sens, jeśli aplikacja jest w fazie opracowywania i nadal wymaga debugowania. Aby usunąć zbędne symbole debugowania z bibliotek natywnych, użyj narzędzia arm-eabi-strip
dostępnego w Android NDK. Następnie możesz skompilować wersję wydania.
Unikaj wyodrębniania bibliotek natywnych
Podczas kompilowania wersji aplikacji przeznaczonej do publikacji skompresowane pliki .so
zapakuj w pliku APK, ustawiając w pliku build.gradle.kts
aplikacji wartość useLegacyPackaging
na false
. Wyłączenie tej flagi uniemożliwi aplikacji PackageManager
kopiowanie plików .so
z pliku APK do systemu plików podczas instalacji. Dzięki temu aktualizacje aplikacji będą mniejsze.
Utrzymywanie wielu smukłych plików APK
Plik APK może zawierać treści, które użytkownicy pobierają, ale nigdy z nich nie korzystają, np. dodatkowe zasoby językowe lub zasoby dla różnych gęstości ekranu. Aby zapewnić użytkownikom minimalny rozmiar pliku do pobrania, prześlij aplikację do Google Play za pomocą pakietów aplikacji na Androida. Po przesłaniu pakietów aplikacji Google Play może generować i udostępniać zoptymalizowane pliki APK dostosowane do konfiguracji urządzenia każdego użytkownika. Dzięki temu użytkownicy pobierają tylko kod i zasoby niezbędne do uruchomienia Twojej aplikacji. Nie musisz tworzyć i podpisywać wielu plików APK ani zarządzać nimi, aby obsługiwać różne urządzenia, a użytkownicy pobierają pliki mniejsze i bardziej zoptymalizowane.
Jeśli nie publikujesz aplikacji w Google Play, możesz podzielić ją na kilka pakietów APK, które różnią się od siebie pod względem takich czynników jak rozmiar ekranu czy obsługa tekstur GPU.
Gdy użytkownik pobierze Twoją aplikację, urządzenie otrzyma odpowiedni plik APK z funkcjami i ustawieniami urządzenia. Dzięki temu urządzenia nie otrzymują zasobów dla funkcji, których nie mają. Jeśli na przykład użytkownik ma urządzenie hdpi
, nie potrzebuje zasobów xxxhdpi
, które możesz uwzględnić na urządzeniach z wyświetlaczami o wyższej gęstości.
Więcej informacji znajdziesz w artykułach Tworzenie wielu plików APK i Obsługa wielu plików APK.