Kiedy klikniesz „Zainstaluj” w pliku APK lub pobierzesz aplikację ze Sklepu Play, za kulisami rozpoczyna się złożona sekwencja operacji. To, co wydaje się być prostym paskiem postępu, w rzeczywistości reprezentuje dziesiątki kroków obejmujących analizowanie pakietów, weryfikację kryptograficzną, zarządzanie uprawnieniami, wyodrębnianie plików i optymalizację kodu. Zrozumienie tego procesu pomaga wyjaśnić, dlaczego instalacje czasami kończą się niepowodzeniem i co można z tym zrobić.
W tym artykule omówimy każdy główny etap instalacji Androida, od momentu otrzymania przez system pliku APK do momentu, w którym aplikacja będzie gotowa do uruchomienia.
Krok 1: Rozpoczęcie instalacji
Proces instalacji rozpoczyna się inaczej w zależności od źródła:
- Sklep Play: Aplikacja Sklep Play pobiera plik APK (lub podzielone pliki APK) i wywołuje instalatora pakietu systemowego ze specjalnymi uprawnieniami, które omijają niektóre potwierdzenia użytkownika.
- Ładowanie boczne: Po otwarciu pliku APK system Android uruchamia czynność instalatora pakietu. W systemie Android 8.0 i nowszych aplikacja instalująca musi mieć uprawnienie „Instaluj nieznane aplikacje” dla swojego konkretnego źródła.
- ADB: Polecenie adb install komunikuje się bezpośrednio z usługą menedżera pakietów przez USB, całkowicie pomijając instalator graficzny.
Niezależnie od źródła, wszystkie instalacje ostatecznie docierają do tej samej usługi systemowej: Usługa PackageManager (PMS). Jest to organ centralny odpowiedzialny za wszystkie operacje na pakietach w systemie Android.
Krok 2: Analiza pakietu
Przede wszystkim system musi zrozumieć, co ma zamiar zainstalować. Usługa PackageManagerService wywołuje Parser pakietów w celu odczytania pliku APK i wyodrębnienia jego metadanych.
Parser odczytuje plik AndroidManifest.xml z poziomu pliku APK. Ten binarny plik XML zawiera najważniejsze informacje:
- Nazwa pakietu: Unikalny identyfikator aplikacji (np). com.example.myapp
- Kod wersji i nazwa: Służy do określenia, czy jest to aktualizacja, czy nowa instalacja
- Minimalne i docelowe wersje SDK: Określa kompatybilność z urządzeniem
- Deklarowane uprawnienia: Zarówno uprawnienia żądane przez aplikację, jak i uprawnienia niestandardowe, które definiuje
- Komponenty: Działania, usługi, odbiorcy transmisji i dostawcy treści rejestrowane przez aplikację
- Funkcje sprzętu i oprogramowania: Wymagania takie jak aparat, GPS lub określone wersje OpenGL
Jeśli plik manifestu jest uszkodzony lub struktura pakietu APK jest nieprawidłowa, instalacja zakończy się na tym etapie niepowodzeniem i komunikatem „Błąd parsowania”. Jest to jedna z najczęstszych przyczyn problemów z instalacją plików APK pobranych spoza sklepu.
Krok 3: Sprawdzanie zgodności
Po przeanalizowaniu manifestu system przeprowadza serię kontroli zgodności:
- Wersja pakietu SDK: Jeśli poziom minSdkVersion aplikacji jest wyższy niż poziom API urządzenia, instalacja zostanie odrzucona.
- Kompatybilność z ABI: Jeśli plik APK zawiera biblioteki natywne, system sprawdza, czy odpowiadają one architekturze procesora urządzenia. Plik APK zawierający wyłącznie biblioteki armeabi-v7a nie zostanie zainstalowany na urządzeniu wyposażonym wyłącznie w procesor x86.
- Wymagane funkcje: Jeśli aplikacja zadeklaruje wymagane funkcje sprzętowe (np. android.hardware.telephony), system sprawdza, czy urządzenie je obsługuje.
- Dostępne miejsce do przechowywania: System sprawdza, czy jest wystarczająca ilość wolnego miejsca do zainstalowania aplikacji, w tym miejsca na wyodrębnione biblioteki natywne i zoptymalizowane pliki DEX.
Krok 4: Weryfikacja podpisu
Jest to jeden z najważniejszych etapów procesu instalacji. Android weryfikuje podpis kryptograficzny pliku APK, aby zapewnić jego integralność i autentyczność.
Proces weryfikacji zależy od tego, jakie schematy podpisywania są obecne:
Podpis V1 (podpisywanie JAR)
System sprawdza katalog META-INF/ pod kątem plików sygnatur (.SF, .RSA lub .DSA). Każdy plik w pliku APK jest weryfikowany pod kątem podsumowań wymienionych w manifeście. Jest to powolne, ponieważ każdy plik musi być indywidualnie mieszany.
Podpis V2 (schemat podpisów APK v2)
Schemat ten, wprowadzony w systemie Android 7.0, podpisuje cały plik APK jako binarny obiekt blob. Blok podpisu jest wstawiany pomiędzy centralnym katalogiem ZIP a rekordem końca katalogu centralnego. Weryfikacja jest znacznie szybsza, ponieważ działa na surowych bajtach bez konieczności dekompresji poszczególnych wpisów.
Podpis V3 (obrót klawisza)
Dostępna od systemu Android 9.0 wersja 3 stanowi rozszerzenie wersji 2 o obsługę rotacji klawiszy. Zawiera strukturę dowodu rotacji, która łączy stare i nowe klucze podpisywania, umożliwiając programistom zmianę klucza podpisywania przy jednoczesnym zachowaniu zgodności aktualizacji.
Podpis V4 (przyrostowy)
W systemie Android 11 wprowadzono wersję V4 do instalacji przyrostowych. Zapewnia sygnaturę opartą na drzewie Merkle, która umożliwia weryfikację poszczególnych bloków podczas ich przesyłania strumieniowego do urządzenia.
Jeśli z jakiegoś powodu weryfikacja podpisu nie powiedzie się, instalacja zostanie natychmiast przerwana. Możesz sprawdzić podpis pliku APK przed instalacją, korzystając z naszego Narzędzie weryfikatora APK.
Zaktualizuj dopasowanie podpisu
Jeśli aplikacja o tej samej nazwie pakietu jest już zainstalowana, system przeprowadza dodatkową weryfikację: certyfikat podpisu nowego pliku APK musi zgadzać się z certyfikatem istniejącej instalacji. Chroni to przed podmianą oryginalnej aplikacji na zmodyfikowaną wersję przez niepowołane osoby. Jeśli podpisy się nie zgadzają, zobaczysz błąd „Aplikacja nie została zainstalowana: pakiet jest w konflikcie z istniejącym pakietem o tej samej nazwie”.
Krok 5: Potwierdzenie użytkownika
W przypadku instalacji ładowanych z boku system wyświetla okno dialogowe potwierdzenia instalacji, zawierające:
- Nazwa i ikona aplikacji (pobrane z zasobów APK)
- Uprawnienia żądań aplikacji (w starszych wersjach Androida)
- Niezależnie od tego, czy jest to nowa instalacja, czy aktualizacja
- Wszelkie ostrzeżenia dotyczące źródła aplikacji lub potencjalnych zagrożeń
W systemie Android 12 i nowszych wersjach ekran potwierdzenia jest prostszy, ponieważ uprawnienia wykonawcze są przyznawane indywidualnie, gdy aplikacja ich potrzebuje po raz pierwszy, a nie w czasie instalacji.
Krok 6: Wyodrębnianie i umieszczanie plików
Po potwierdzeniu przez użytkownika (lub w przypadku instalacji w Sklepie Play automatycznie) system rozpoczyna wyodrębnianie i umieszczanie plików:
Pamięć APK
Sam plik APK jest kopiowany do /data/app/[package-name]-[random]/base.apk. W przypadku rozdzielonych instalacji APK dodatkowe pliki, takie jak split_config.arm64_v8a.apk, są umieszczane obok podstawowego pliku APK. Oryginalny plik APK w folderze Pobrane nie jest modyfikowany ani usuwany.
Ekstrakcja natywnej biblioteki
Jeśli plik APK zawiera biblioteki natywne (w katalogu lib/), są one wypakowywane do ścieżki /data/app/[package-name]-[random]/lib/[abi]/. W nowszych wersjach Androida aplikacje mogą pozostawić biblioteki natywne wewnątrz pliku APK i ładować je bezpośrednio dzięki ustawieniu android:extractNativeLibs="false", co pozwala zaoszczędzić miejsce w pamięci.
Tworzenie katalogu danych
System tworzy prywatny katalog danych aplikacji pod adresem /data/data/[package-name]/ (lub /data/user/0/[package-name]/ na urządzeniach z wieloma użytkownikami). Właścicielem tego katalogu jest unikalny identyfikator UID systemu Linux przypisany do aplikacji, co gwarantuje, że żadna inna aplikacja nie będzie mogła uzyskać do niego dostępu bez uprawnień roota.
Krok 7: Optymalizacja DEX
Na tym etapie system Android przekształca kod bajtowy aplikacji w format zoptymalizowany pod kątem konkretnego sprzętu urządzenia. Proces ten znacznie ewoluował w historii Androida:
Era Dalvik (Android 4.4 i starsze)
Oryginalna maszyna wirtualna Dalvik korzystała z kompilacji Just-In-Time (JIT). Podczas instalacji plik classes.dex został zoptymalizowany do pliku ODEX zawierającego zweryfikowany i zoptymalizowany kod bajtowy. Było to stosunkowo szybkie, ale oznaczało, że aplikacja działała wolniej w czasie wykonywania, ponieważ większość kodu była nadal interpretowana.
ART z AOT (Android 5.0 do 6.0)
Android Runtime (ART) zastąpił Dalvik i wprowadził kompilację Ahead-Of-Time (AOT). Podczas instalacji cały kod bajtowy DEX został skompilowany do natywnego kodu maszynowego. Dzięki temu aplikacje działały szybciej, ale znacznie wydłużyły czas instalacji i wykorzystanie pamięci. Instalacja niektórych aplikacji trwała kilka minut.
Kompilacja oparta na profilu (Android 7.0 lub nowszy)
Nowoczesny Android wykorzystuje podejście hybrydowe. Podczas instalacji kompilowane są tylko krytyczne ścieżki startowe. Gdy użytkownik uruchamia aplikację, system zbiera profile wykonania identyfikujące często używane ścieżki kodu. Podczas bezczynnej konserwacji (zwykle podczas nocnego ładowania) system kompiluje te gorące ścieżki do kodu natywnego. Zapewnia to równowagę między szybkością instalacji, wykorzystaniem pamięci i wydajnością środowiska wykonawczego.
Skompilowany kod jest przechowywany w /data/dalvik-cache/ lub obok pliku APK jako pliki .odex, .vdex i .art. Plik .vdex zawiera zweryfikowany kod DEX, plik .odex zawiera skompilowany kod natywny, a plik .art zawiera wstępnie zainicjowane obrazy sterty w celu szybszego uruchamiania.
Krok 8: Rejestracja uprawnień
Usługa PackageManagerService rejestruje zadeklarowane uprawnienia i komponenty aplikacji w systemie:
- Uprawnienia w czasie instalacji (jak INTERNET lub VIBRATE są przyznawane automatycznie, bez interakcji użytkownika).
- Uprawnienia wykonawcze (jak CAMERA lub LOCATION są zarejestrowane, ale nie są przyznawane). Aplikacja musi zażądać ich w czasie wykonywania.
- Filtry intencji są zarejestrowane, dzięki czemu system wie, które aplikacje mogą obsługiwać dane działania (takie jak otwieranie adresu URL lub udostępnianie treści).
- Dostawcy treści są zarejestrowane w odpowiednich władzach, więc inne aplikacje mogą do nich wysyłać zapytania.
Krok 9: Integracja systemu
Ostatnie kroki integrują aplikację z systemem Android:
- Aktualizacja bazy danych pakietów: Baza danych pakietów systemu (/data/system/packages.xml jest aktualizowana o informacje o nowej aplikacji, w tym o przypisany UID, uprawnienia i deklaracje komponentów).
- Powiadomienie o programie uruchamiającym: Program uruchamiający ekran główny jest powiadamiany o nowej aplikacji, dzięki czemu może wyświetlić ikonę aplikacji.
- Audycja: System wysyła rozgłoszenie PACKAGE_ADDED, umożliwiając innym aplikacjom reakcję na nową instalację (na przykład aplikacje do tworzenia kopii zapasowych mogą zaplanować utworzenie kopii zapasowej).
- Kontekst SELinuksa: Pliki aplikacji są oznaczone odpowiednim kontekstem bezpieczeństwa SELinux w oparciu o docelową wersję SDK i zadeklarowane uprawnienia.
Dlaczego instalacje kończą się niepowodzeniem
Zrozumienie przebiegu instalacji pomaga zdiagnozować typowe awarie:
- „Błąd analizy”: Plik APK jest uszkodzony, niekompletny lub ma zniekształcony manifest. Dzieje się tak często w przypadku niekompletnych pobrań lub nieprawidłowo przekonwertowanych plików.
- „Aplikacja nie została zainstalowana” (niezgodność podpisu): Próbujesz zaktualizować aplikację za pomocą pliku APK podpisanego innym kluczem. Najpierw musisz odinstalować istniejącą wersję.
- „Niewystarczająca ilość miejsca”: Za mało miejsca na plik APK, wyodrębnione biblioteki i dane wyjściowe optymalizacji DEX. Rzeczywista potrzebna przestrzeń jest zwykle 2-3 razy większa niż rozmiar pliku APK.
- „Pakiet koliduje z istniejącym pakietem”: Ta sama nazwa pakietu, ale inny podpis. Często podczas przełączania między Sklepem Play a wersjami ładowanymi z boku.
- Zablokowano obniżenie wersji: Domyślnie system Android uniemożliwia instalację starszej wersji na nowszej. ADB może to zastąpić za pomocą adb install -d.
Podziel instalację APK
Podczas instalowania podzielonych plików APK (z pakietów aplikacji) proces jest nieco inny. System wykorzystuje API instalacja oparta na sesji:
- Utworzona zostanie nowa sesja instalacyjna
- Każdy podzielony plik APK jest zapisywany w sesji
- Sesja zostaje zatwierdzona, co uruchamia potok pełnej weryfikacji
- Wszystkie podziały muszą mieć zgodne nazwy pakietów, kody wersji i certyfikaty podpisywania
Jest to mechanizm używany przez instalatory i narzędzia XAPK, takie jak nasz Połączenie APKS z APK, do obsługi instalacji wieloplikowych.
Instalacja poprzez ADB
Kiedy używasz adb install, proces omija instalator graficzny, ale przebiega według tego samego wewnętrznego potoku. ADB komunikuje się z usługą menedżera pakietów poprzez połączenie z gniazdem. Obsługuje dodatkowe flagi, które nie są dostępne poprzez GUI:
- -r: Zastąp istniejącą aplikację (zezwól na ponowną instalację)
- -d: Zezwól na obniżenie wersji
- -g: Natychmiast przyznaj wszystkie uprawnienia wykonawcze
- -t: Zezwalaj na instalację testowych plików APK
- --install-multiple: Zainstaluj podzielone pliki APK w jednej sesji
Co się stanie podczas dezinstalacji
Dla kompletności oto, co dzieje się po usunięciu aplikacji:
- Procesy aplikacji są zabijane
- Plik APK i wyodrębnione biblioteki zostały usunięte z /data/app/
- Prywatny katalog danych aplikacji zostanie usunięty (chyba że użytkownik zdecydował się zachować dane)
- Skompilowane pliki pamięci podręcznej DEX są usuwane
- Baza danych pakietów została zaktualizowana
- Wysłano transmisję PACKAGE_REMOVED
- Program uruchamiający usuwa ikonę aplikacji
Pamiętaj, że pliki specyficzne dla aplikacji w pamięci zewnętrznej (/Android/data/[package]/ i /Android/obb/[package]/ są również usuwane w systemie Android 10 i nowszych wersjach dzięki wymuszeniu ograniczonego miejsca na dane).
Dlaczego zrozumienie PackageManager oszczędza czas debugowania
Proces instalacji Androida to starannie zaplanowana sekwencja kontroli bezpieczeństwa, operacji na plikach i integracji systemu. Każdy krok ma swój cel – od ochrony użytkowników przed zmodyfikowanymi aplikacjami po optymalizację wydajności dla konkretnego sprzętu. W przypadku niepowodzenia instalacji błąd zwykle wskazuje na konkretny etap potoku, a zrozumienie procesu pomaga w szybkim diagnozowaniu i rozwiązywaniu problemów.
Instalowanie ze Sklepu Play, ręczne ładowanie pliku APK i przesyłanie kompilacji za pomocą ADB odbywa się przez ten sam potok, który gwarantuje, że każda aplikacja na Twoim urządzeniu została zweryfikowana, poprawnie umieszczona i zoptymalizowana pod kątem Twojego sprzętu.