Użytkownicy często unikają pobierania aplikacji, które wydają się za duże, zwłaszcza na rynkach wschodzących, gdzie urządzenia łączą się z niestabilnymi sieciami 2G i 3G, lub opracowują abonamenty z limitami danych. Na tej stronie dowiesz się, jak zmniejszyć rozmiar pobieranej aplikacji, aby więcej użytkowników mogło ją pobrać.
Przesyłanie aplikacji za pomocą pakietów Android App Bundle
Prześlij aplikację jako pakiet Android App Bundle, aby natychmiast zapisać jej rozmiar po opublikowaniu 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 udostępniania aplikacji w Google Play wykorzystuje następnie Twój pakiet aplikacji do generowania i udostępniania zoptymalizowanych plików APK dla konfiguracji urządzeń poszczególnych użytkowników. Dzięki temu użytkownicy pobierają tylko kod i zasoby niezbędne do uruchomienia aplikacji. Nie musisz tworzyć i podpisywać wielu plików APK obsługiwanych na różnych urządzeniach ani nimi zarządzać, a użytkownicy uzyskują mniejsze, lepiej zoptymalizowane pliki do pobrania.
W przypadku aplikacji opublikowanych z pakietami aplikacji Google Play wymusza ograniczenie rozmiaru pobieranych plików skompresowanych do 200 MB. W przypadku korzystania z funkcji Play Feature Delivery i Play Asset Delivery możesz używać większych rozmiarów, 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.
Informacje o strukturze plików APK
Zanim zmniejszysz rozmiar aplikacji, warto poznać strukturę jej pliku APK. Plik APK to archiwum ZIP zawierające wszystkie pliki tworzące aplikację. Pliki te obejmują m.in. pliki klasy Java, pliki zasobów oraz plik zawierający skompilowane zasoby.
Plik APK zawiera te katalogi:
META-INF/
: zawiera pliki podpisuCERT.SF
iCERT.RSA
oraz plik manifestuMANIFEST.MF
.assets/
: zawiera zasoby aplikacji, które aplikacja może pobrać za pomocą obiektuAssetManager
.res/
: zawiera zasoby, które nie są skompilowane wresources.arsc
.lib/
: zawiera skompilowany kod związany z warstwą 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ż wymienione niżej pliki. Wymagane jest podanie tylko pola AndroidManifest.xml
:
resources.arsc
: zawiera skompilowane zasoby. Ten plik zawiera treść XML ze wszystkich konfiguracji folderures/values/
. Narzędzie do pakowania wyodrębnia zawartość XML, skompiluje ją do postaci binarnej i archiwizuje. Obejmuje to ciągi tekstowe i style językowe oraz ścieżki do treści, które nie są umieszczone bezpośrednio w plikuresources.arsc
, np. do plików układu i obrazów.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 wpływa na to, jak szybko się wczytuje, ile pamięci zużywa oraz ile energii zużywa. Aby zmniejszyć rozmiar pliku APK, zmniejsz liczbę i rozmiar zawartych w nim zasobów. 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 i inne sposoby zmniejszenia zasobów w aplikacji, aby zmniejszyć ogólny rozmiar pliku APK.
Usuń nieużywane zasoby
Narzędzie lint
– statyczny analizator kodu dostępny w Android Studio – wykrywa w folderze res/
zasoby, do których nie odwołuje się Twój kod. Gdy narzędzie lint
wykryje potencjalnie nieużywany zasób w projekcie, 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") } } }
Odlotowe
android { // Other settings. buildTypes { release { minifyEnabled true shrinkResources true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } }
Aby używać funkcji shrinkResources
, włącz zmniejszanie kodu. Podczas kompilacji R8 najpierw usuwa nieużywany kod. Następnie wtyczka Androida do obsługi Gradle usuwa nieużywane zasoby.
Więcej informacji o zmniejszaniu kodu i zasobów oraz innych sposobach zmniejszania pliku APK w Android Studio znajdziesz w artykule Zmniejszanie, zaciemnianie i optymalizowanie aplikacji.
We wtyczce Androida do obsługi Gradle w wersji 7.0 i nowszych możesz zadeklarować konfiguracje obsługiwane przez aplikację. Gradle przekazuje te informacje do systemu kompilacji za pomocą rodzaju resourceConfigurations
i opcji defaultConfig
. System kompilacji zapobiega wyświetlaniu w pliku APK zasobów z innych nieobsługiwanych konfiguracji, zmniejszając jego rozmiar. Więcej informacji o tej funkcji znajdziesz w artykule Usuwanie nieużywanych zasobów alternatywnych.
Minimalizuj wykorzystanie zasobów z bibliotek
Gdy tworzysz aplikację na Androida, zwykle korzystasz z bibliotek zewnętrznych, by zwiększyć przydatność i wszechstronność aplikacji. Możesz na przykład skorzystać z AndroidaX, by zwiększyć wygodę użytkowników na wcześniejszych urządzeniach, lub skorzystać z Usług Google Play, by pobrać automatyczne tłumaczenia tekstu w aplikacji.
Jeśli biblioteka jest przeznaczona dla 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 jej modyfikowanie. Możesz też użyć alternatywnej biblioteki przyjaznej dla urządzeń mobilnych, aby dodać do swojej aplikacji określone funkcje.
Natywne dekodowanie animowanego obrazu
W Androidzie 12 (poziom interfejsu API 31) interfejs API NDK ImageDecoder
jest rozszerzony i dekoduje wszystkie klatki i dane o czasie z obrazów, które używają animowanych plików GIF i WebP.
Aby jeszcze bardziej zmniejszyć rozmiar pliku APK i korzystać z przyszłych aktualizacji dotyczących bezpieczeństwa i wydajności, używaj ImageDecoder
zamiast bibliotek innych firm.
Więcej informacji o interfejsie ImageDecoder
API znajdziesz w API reference
i przykładzie na GitHubie.
Obsługuj tylko określone gęstości
Android obsługuje różne gęstości ekranu, na przykład:
ldpi
mdpi
tvdpi
hdpi
xhdpi
xxhdpi
xxxhdpi
Mimo że Android obsługuje poprzednie gęstości, nie musisz eksportować zrastrowanych zasobów do poszczególnych 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 przeskalowanych obrazów, możesz zaoszczędzić jeszcze więcej miejsca, tworząc pojedynczy wariant obrazu w usłudze drawable-nodpi/
. Zalecamy dodanie do aplikacji co najmniej xxhdpi
wersji obrazu.
Więcej informacji o gęstościach ekranu znajdziesz w sekcji Rozmiary i gęstości ekranu.
Używanie obiektów rysowalnych
Niektóre obrazy nie wymagają zasobu obrazu statycznego. Platforma może zamiast tego dynamicznie
rysować obraz w czasie działania aplikacji. Obiekty Drawable
– lub <shape>
w formacie XML – mogą zajmować niewielką ilość miejsca w pliku APK. Dodatkowo obiekty XML Drawable
generują obrazy monochromatyczne zgodne z wytycznymi Material Design.
Ponowne wykorzystywanie zasobów
Możesz dodać osobny zasób dla odmian obrazu, np. podbarwione, zacienione lub obrócone wersje tego samego obrazu. Zalecamy jednak ponowne używanie tego samego zestawu zasobów i dostosowywanie ich w czasie działania.
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 rotacyjnym odpowiednikiem innego zasobu. Ten fragment kodu zawiera 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ć, proceduralnie renderując obrazy. Renderowanie proceduralne pozwala zwolnić miejsce, ponieważ w pakiecie APK nie przechowujesz już pliku graficznego.
Cruncha, pliki PNG
Narzędzie aapt
może zoptymalizować zasoby obrazu umieszczone w res/drawable/
przy użyciu bezstratnej kompresji podczas kompilacji. Narzędzie aapt
może na przykład przekonwertować plik PNG z prawdziwymi kolorami, który nie wymaga więcej niż 256 kolorów, na 8-bitowy plik PNG z paletą kolorów. Dzięki temu obraz będzie miał taką samą jakość, ale mniejszy rozmiar pamięci.
aapt
ma te ograniczenia:
- Narzędzie
aapt
nie zmniejsza plików PNG znajdujących się w folderzeasset/
. - Pliki obrazów mogą mieć maksymalnie 256 kolorów, aby można je było zoptymalizować za pomocą narzędzia
aapt
. - Narzędzie
aapt
może zwiększać rozmiar już skompresowanych plików PNG. Aby temu zapobiec, możesz użyć flagiisCrunchPngs
do wyłączenia tego procesu w przypadku plików PNG:
Kotlin
buildTypes.all { isCrunchPngs = false }
Odlotowe
buildTypes.all { isCrunchPngs = false }
Kompresuj pliki 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 przy zachowaniu postrzeganej jakości obrazu.
Szczególnie skuteczne jest narzędzie pngcrush
. To narzędzie iteruje filtry PNG i parametry zlib (Deflate), wykorzystując każdą kombinację filtrów i parametrów do skompresowania obrazu.
Następnie wybiera konfigurację, która generuje najmniejsze skompresowane dane wyjściowe.
Do skompresowania plików JPEG możesz użyć narzędzi takich jak packJPG czy guetzli.
Użyj formatu pliku WebP
Zamiast plików PNG lub JPEG możesz też użyć formatu pliku WebP. Format WebP zapewnia kompresję stratną i przejrzystość, np. JPG i PNG, i może zapewnić lepszą kompresję niż JPEG czy PNG.
Korzystając z Android Studio, możesz przekonwertować istniejące obrazy w formacie BMP, JPG, PNG lub statyczne pliki GIF na format WebP. Więcej informacji znajdziesz w artykule Tworzenie obrazów WebP.
Używaj grafiki wektorowej
Za pomocą grafiki wektorowej możesz tworzyć ikony niezależne od rozdzielczości i inne skalowalne multimedia.
Dzięki nim możesz znacznie zmniejszyć rozmiar pliku APK. Obrazy wektorowe są reprezentowane na Androidzie jako obiekty VectorDrawable
. Korzystając z obiektu VectorDrawable
, plik 100-bajtowy może wygenerować ostry obraz wielkości ekranu.
Wyrenderowanie każdego obiektu VectorDrawable
przez system zajmuje jednak znacznie więcej czasu, a większe obrazy pojawiają się na ekranie jeszcze dłużej.
Dlatego przy wyświetlaniu małych obrazów używaj grafiki wektorowej.
Więcej informacji o pracy z obiektami VectorDrawable
znajdziesz w sekcji Elementy rysowalne.
Używaj grafiki wektorowej jako animowanych obrazów
Nie używaj AnimationDrawable
do tworzenia animacji klatka po klatce, bo wymaga to dołączenia osobnego pliku bitmapy dla każdej klatki animacji, co znacznie zwiększa rozmiar pliku APK.
Zamiast tego użyj funkcji
AnimatedVectorDrawableCompat
, aby utworzyć animowane wektorowe obiekty rysunkowe.
Ogranicz kod natywny i kod Java
Aby zmniejszyć rozmiar natywnej bazy kodu w Javie i w aplikacji, możesz użyć poniższych metod.
Usuń zbędny wygenerowany kod
Upewnij się, że znasz zasięg każdego kodu, który jest generowany automatycznie. Na przykład wiele narzędzi do buforowania protokołów generuje zbyt wiele metod i klas, co może skutkować dwukrotnie lub nawet trzykrotnym rozmiarem aplikacji.
Unikaj wyliczeń
Pojedyncze wyliczenie może dodać około 1,0–1,4 KB do pliku classes.dex
aplikacji. Te dodatki mogą się szybko akumulować w przypadku złożonych systemów lub bibliotek udostępnionych. Jeśli to możliwe, rozważ użycie adnotacji @IntDef
i zmniejszanie kodu w celu wyeliminowania wyliczeń i przekonwertowania ich na liczby całkowite. Konwersja tego typu zachowuje wszystkie korzyści związane z bezpieczeństwem tego typu wyliczenia.
Zmniejszanie rozmiaru natywnych plików binarnych
Jeśli Twoja aplikacja korzysta z kodu natywnego i pakietu Android NDK, możesz też zmniejszyć rozmiar jej wersji, optymalizując kod. Dwie przydatne metody to usuwanie symboli debugowania i wyodrębnianie bibliotek natywnych.
Usuń symbole debugowania
Używanie symboli debugowania ma sens, jeśli aplikacja jest w fazie opracowywania i nadal wymaga debugowania. Aby usunąć z bibliotek natywnych niepotrzebne symbole debugowania, użyj narzędzia arm-eabi-strip
dostępnego w pakiecie Android NDK. Później możesz skompilować kompilację wersji.
Unikaj wyodrębniania bibliotek natywnych
Podczas tworzenia wersji produkcyjnej aplikacji utwórz pakiet nieskompresowanych plików .so
w pliku APK, ustawiając parametr useLegacyPackaging
na false
w pliku build.gradle.kts
aplikacji. Wyłączenie tej flagi uniemożliwia usłudze PackageManager
kopiowanie plików .so
z pakietu APK do systemu plików podczas instalacji. Ta metoda zmniejsza rozmiar aktualizacji aplikacji.
Utrzymywanie wielu uproszczonych plików APK
Plik APK może zawierać treści, które użytkownicy pobierają, ale nigdy nie używają, np. dodatkowe języki lub materiały o określonej gęstości ekranu. Aby ograniczyć pobieranie do minimum, prześlij aplikację do Google Play przy użyciu pakietów Android App Bundle. 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 w Google Play, możesz podzielić aplikację na kilka plików APK różniących się takimi czynnikami jak rozmiar ekranu czy obsługa tekstury 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 na potrzeby funkcji, których nie mają. Jeśli na przykład użytkownik ma urządzenie z hdpi
, nie potrzebuje zasobów xxxhdpi
, które możesz uwzględnić w przypadku urządzeń o większej gęstości.
Więcej informacji znajdziesz w artykułach Tworzenie wielu plików APK i Obsługa wielu plików APK.