Wanneer u op 'Installeren' tikt op een APK-bestand of een app downloadt uit de Play Store, begint achter de schermen een complexe reeks handelingen. Wat een eenvoudige voortgangsbalk lijkt, vertegenwoordigt in werkelijkheid tientallen stappen die te maken hebben met het parseren van pakketten, cryptografische verificatie, toestemmingsbeheer, bestandsextractie en code-optimalisatie. Als u dit proces begrijpt, kunt u verklaren waarom installaties soms mislukken en wat u eraan kunt doen.
In dit artikel doorlopen we elke belangrijke stap van de Android-installatiepijplijn, vanaf het moment dat het systeem een APK ontvangt tot het punt waarop de app klaar is om te starten.
Stap 1: Starten van de installatie
Het installatieproces begint anders, afhankelijk van de bron:
- Speelwinkel: De Play Store-app downloadt de APK (of gesplitste APK's) en roept het pakketinstallatieprogramma van het systeem aan met speciale rechten die bepaalde gebruikersbevestigingen omzeilen.
- Zijladen: Wanneer u een APK-bestand opent, start Android de activiteit van het pakketinstallatieprogramma. Op Android 8.0 en hoger moet de installerende app de machtiging 'Onbekende apps installeren' hebben voor de specifieke bron.
- ADB: De opdracht adb install communiceert rechtstreeks met de pakketbeheerservice via USB, waarbij het grafische installatieprogramma volledig wordt omzeild.
Ongeacht de bron bereiken alle installaties uiteindelijk dezelfde systeemdienst: de PakketManagerService (PMS). Dit is de centrale autoriteit voor alle pakketbewerkingen op Android.
Stap 2: Pakketparsering
Het systeem moet eerst begrijpen wat het gaat installeren. De PackageManagerService roept de PakketParser aan om het APK-bestand te lezen en de metagegevens ervan te extraheren.
De parser leest het AndroidManifest.xml-bestand vanuit de APK. Dit binaire XML-bestand bevat essentiële informatie:
- Pakketnaam: De unieke identificatie voor de app (bijvoorbeeld com.example.myapp)
- Versiecode en naam: Wordt gebruikt om te bepalen of dit een upgrade of een nieuwe installatie is
- Minimale en doel-SDK-versies: Bepaalt de compatibiliteit met het apparaat
- Aangegeven machtigingen: Zowel machtigingen die de app aanvraagt als aangepaste machtigingen die de app definieert
- Componenten: Activiteiten, services, uitzendingsontvangers en contentproviders die de app registreert
- Hardware- en softwarefuncties: Vereisten zoals camera, GPS of specifieke OpenGL-versies
Als het manifest een onjuiste indeling heeft of de APK-structuur ongeldig is, mislukt de installatie in dit stadium met het bericht 'Parse error'. Dit is een van de meest voorkomende redenen waarom sideloaded APK's niet kunnen worden geïnstalleerd.
Stap 3: Compatibiliteitscontroles
Nadat het manifest is geparseerd, voert het systeem een reeks compatibiliteitscontroles uit:
- SDK-versie: Als de minSdkVersion van de app hoger is dan het API-niveau van het apparaat, wordt de installatie afgewezen.
- ABI-compatibiliteit: Als de APK native bibliotheken bevat, controleert het systeem of deze overeenkomen met de CPU-architectuur van het apparaat. Een APK met alleen armeabi-v7a-bibliotheken kan niet worden geïnstalleerd op een apparaat dat alleen x86 gebruikt.
- Vereiste kenmerken: Als de app vereiste hardwarefuncties aangeeft (zoals android.hardware.telephony), verifieert het systeem of het apparaat deze ondersteunt.
- Beschikbare opslagruimte: Het systeem controleert of er voldoende vrije ruimte is om de app te installeren, inclusief ruimte voor de uitgepakte native bibliotheken en geoptimaliseerde DEX-bestanden.
Stap 4: Handtekeningverificatie
Dit is een van de meest kritische stappen in het installatieproces. Android verifieert de cryptografische handtekening van de APK om de integriteit en authenticiteit ervan te garanderen.
Het verificatieproces is afhankelijk van welke ondertekeningsschema's aanwezig zijn:
V1-handtekening (JAR-ondertekening)
Het systeem controleert de map META-INF/ op handtekeningbestanden (.SF, .RSA of .DSA). Elk bestand in de APK wordt geverifieerd aan de hand van de samenvattingen die in het manifest worden vermeld. Dit gaat langzaam omdat elk bestand afzonderlijk moet worden gehasht.
V2-handtekening (APK-handtekeningschema v2)
Dit schema, geïntroduceerd in Android 7.0, ondertekent de volledige APK als een binaire blob. Het handtekeningblok wordt ingevoegd tussen de centrale ZIP-directory en het record aan het einde van de centrale directory. Verificatie is veel sneller omdat deze op de onbewerkte bytes werkt zonder dat afzonderlijke vermeldingen hoeven te worden gedecomprimeerd.
V3-handtekening (sleutelrotatie)
V3 is beschikbaar vanaf Android 9.0 en breidt V2 uit met ondersteuning voor sleutelrotatie. Het bevat een proof-of-rotation-structuur die oude en nieuwe ondertekeningssleutels koppelt, waardoor ontwikkelaars hun ondertekeningssleutel kunnen wijzigen terwijl de update-compatibiliteit behouden blijft.
V4-handtekening (incrementeel)
Android 11 introduceerde V4 voor incrementele installaties. Het biedt een op Merkle-boom gebaseerde handtekening die verificatie van individuele blokken mogelijk maakt terwijl ze naar het apparaat worden gestreamd.
Als de handtekeningverificatie om welke reden dan ook mislukt, wordt de installatie onmiddellijk afgebroken. U kunt de handtekening van een APK vóór installatie controleren met behulp van onze APK-verificatietool.
Handtekeningmatching bijwerken
Als er al een app met dezelfde pakketnaam is geïnstalleerd, voert het systeem een extra controle uit: het ondertekeningscertificaat van de nieuwe APK moet overeenkomen met het certificaat van de bestaande installatie. Dit voorkomt dat een kwaadwillende partij een legitieme app vervangt door een geknoeide versie. Als de handtekeningen niet overeenkomen, ziet u de foutmelding 'App niet geïnstalleerd: het pakket conflicteert met een bestaand pakket met dezelfde naam'.
Stap 5: Gebruikersbevestiging
Voor sideloaded installaties geeft het systeem een installatiebevestigingsvenster weer met daarin:
- De naam en het pictogram van de app (geëxtraheerd uit de bronnen van de APK)
- Machtigingen die de app vraagt (op oudere Android-versies)
- Of dit nu een nieuwe installatie of een update is
- Eventuele waarschuwingen over de bron van de app of potentiële risico's
Op Android 12 en hoger is het bevestigingsscherm eenvoudiger omdat runtime-rechten individueel worden verleend wanneer de app deze voor het eerst nodig heeft, in plaats van tijdens de installatie.
Stap 6: Bestandsextractie en plaatsing
Zodra de gebruiker dit bevestigt (of bij een Play Store-installatie automatisch), begint het systeem met het uitpakken en plaatsen van bestanden:
APK-opslag
Het APK-bestand zelf wordt gekopieerd naar /data/app/[package-name]-[random]/base.apk. Voor gesplitste APK-installaties worden extra bestanden zoals split_config.arm64_v8a.apk naast de basis-APK geplaatst. De originele APK in de map Downloads wordt niet gewijzigd of verwijderd.
Native bibliotheekextractie
Als de APK native bibliotheken bevat (in de map lib/, worden deze uitgepakt naar /data/app/[package-name]-[random]/lib/[abi]/). Op nieuwere Android-versies kunnen apps ervoor kiezen om native bibliotheken gecomprimeerd te houden binnen de APK en deze rechtstreeks te laden met android:extractNativeLibs="false", wat opslagruimte bespaart.
Creëren van gegevensdirectory's
Het systeem maakt de privégegevensmap van de app aan op /data/data/[package-name]/ (of /data/user/0/[package-name]/ op apparaten met meerdere gebruikers). Deze map is eigendom van een unieke Linux UID die aan de app is toegewezen, zodat geen enkele andere app er toegang toe heeft zonder rootrechten.
Stap 7: DEX-optimalisatie
Bij deze stap transformeert Android de bytecode van de app naar een formaat dat is geoptimaliseerd voor de specifieke hardware van het apparaat. Het proces is aanzienlijk geëvolueerd in de geschiedenis van Android:
Het Dalvik-tijdperk (Android 4.4 en eerder)
De originele virtuele machine van Dalvik maakte gebruik van Just-In-Time (JIT)-compilatie. Tijdens de installatie werd het classes.dex-bestand geoptimaliseerd tot een ODEX-bestand dat geverifieerde en geoptimaliseerde bytecode bevatte. Dit was relatief snel, maar betekende dat de app tijdens runtime langzamer werkte omdat de meeste code nog steeds werd geïnterpreteerd.
KUNST met AOT (Android 5.0 tot 6.0)
Android Runtime (ART) verving Dalvik en introduceerde Ahead-Of-Time (AOT) -compilatie. Tijdens de installatie werd de volledige DEX-bytecode gecompileerd naar native machinecode. Hierdoor werkten apps sneller, maar nam de installatietijd en het opslaggebruik aanzienlijk toe. Bij sommige apps duurde het enkele minuten om te installeren.
Profielgestuurde compilatie (Android 7.0+)
Modern Android gebruikt een hybride aanpak. Tijdens de installatie worden alleen kritische opstartpaden gecompileerd. Terwijl de gebruiker de app uitvoert, verzamelt het systeem uitvoeringsprofielen die veelgebruikte codepaden identificeren. Tijdens inactief onderhoud (meestal tijdens het opladen 's nachts) compileert het systeem deze hotpaths naar native code. Dit balanceert de installatiesnelheid, het opslaggebruik en de runtime-prestaties.
De gecompileerde code wordt opgeslagen in /data/dalvik-cache/ of naast de APK als .odex-, .vdex- en .art-bestanden. Het .vdex-bestand bevat geverifieerde DEX-code, het .odex-bestand bevat gecompileerde native code en het .art-bestand bevat vooraf geïnitialiseerde heap-images voor sneller opstarten.
Stap 8: Toestemmingsregistratie
De PackageManagerService registreert de gedeclareerde machtigingen en componenten van de app bij het systeem:
- Machtigingen tijdens installatietijd (zoals INTERNET of VIBRATE worden automatisch toegekend zonder tussenkomst van de gebruiker).
- Runtime-machtigingen (zoals CAMERA of LOCATION zijn geregistreerd maar niet toegekend). De app moet ze tijdens runtime opvragen.
- Intentiefilters worden geregistreerd, zodat het systeem weet welke apps welke acties kunnen uitvoeren (zoals het openen van een URL of het delen van inhoud).
- Contentaanbieders zijn geregistreerd bij hun autoriteiten, zodat andere apps ze kunnen bevragen.
Stap 9: Systeemintegratie
De laatste stappen integreren de app in het Android-systeem:
- Pakketdatabase-update: De pakketdatabase van het systeem (/data/system/packages.xml wordt bijgewerkt met de informatie van de nieuwe app, inclusief de toegewezen UID, machtigingen en componentdeclaraties).
- Launcher-melding: De startschermstarter wordt op de hoogte gesteld van de nieuwe app, zodat deze het app-pictogram kan weergeven.
- Uitzending: Het systeem verzendt een PACKAGE_ADDED-uitzending, waardoor andere apps kunnen reageren op de nieuwe installatie (back-up-apps kunnen bijvoorbeeld een back-up plannen).
- SELinux-context: De bestanden van de app zijn gelabeld met de juiste SELinux-beveiligingscontext, gebaseerd op de doel-SDK-versie en gedeclareerde machtigingen.
Waarom installaties mislukken
Als u de installatiepijplijn begrijpt, kunt u veelvoorkomende fouten diagnosticeren:
- "Parsefout": De APK is beschadigd, onvolledig of heeft een verkeerd opgemaakt manifest. Dit gebeurt vaak bij onvolledige downloads of onjuist geconverteerde bestanden.
- "App niet geïnstalleerd" (handtekening komt niet overeen): U probeert een app bij te werken met een APK die met een andere sleutel is ondertekend. U moet eerst de bestaande versie verwijderen.
- "Onvoldoende opslagruimte": Niet genoeg ruimte voor de APK, geëxtraheerde bibliotheken en DEX-optimalisatie-uitvoer. De daadwerkelijk benodigde ruimte is doorgaans 2-3x de APK-grootte.
- "Pakket conflicteert met bestaand pakket": Dezelfde pakketnaam maar andere handtekening. Vaak bij het schakelen tussen Play Store en sideloaded-versies.
- Versiedowngrade geblokkeerd: Standaard voorkomt Android dat een oudere versie over een nieuwere wordt geïnstalleerd. ADB kan dit overschrijven met adb install -d.
Gesplitste APK-installatie
Bij het installeren van gesplitste APK's (uit app-bundels) is het proces enigszins anders. Het systeem maakt gebruik van een sessiegebaseerde installatie API:
- Er wordt een nieuwe installatiesessie aangemaakt
- Elke gesplitste APK wordt naar de sessie geschreven
- De sessie wordt vastgelegd, waardoor de volledige verificatiepijplijn wordt geactiveerd
- Alle splitsingen moeten overeenkomende pakketnamen, versiecodes en handtekeningcertificaten hebben
Dit is het mechanisme dat wordt gebruikt door XAPK-installatieprogramma's en tools zoals onze APKS naar APK-fusie om installaties met meerdere bestanden af te handelen.
Installatie via ADB
Wanneer u adb install gebruikt, omzeilt het proces het grafische installatieprogramma, maar volgt het dezelfde interne pijplijn. ADB communiceert met de pakketbeheerservice via een socketverbinding. Het ondersteunt extra vlaggen die niet beschikbaar zijn via de GUI:
- -r: Bestaande app vervangen (herinstallatie toestaan)
- -d: versiedowngrade toestaan
- -g: Verleen onmiddellijk alle runtime-rechten
- -t: installatie van alleen-test-APK's toestaan
- --install-multiple: Installeer gesplitste APK's in één sessie
Wat er gebeurt tijdens het verwijderen
Voor de volledigheid: dit is wat er gebeurt als een app wordt verwijderd:
- De processen van de app worden gedood
- De APK en geëxtraheerde bibliotheken worden verwijderd uit /data/app/
- De privégegevensmap van de app wordt verwijderd (tenzij de gebruiker ervoor kiest gegevens te behouden)
- Gecompileerde DEX-cachebestanden worden verwijderd
- De pakketdatabase wordt bijgewerkt
- Er wordt een PACKAGE_REMOVED-uitzending verzonden
- Het opstartprogramma verwijdert het app-pictogram
Houd er rekening mee dat app-specifieke bestanden op externe opslag (/Android/data/[package]/ en /Android/obb/[package]/ ook worden verwijderd op Android 10 en hoger, dankzij de beperkte opslaghandhaving).
Waarom het begrijpen van PackageManager tijd voor foutopsporing bespaart
Het Android-installatieproces bestaat uit een zorgvuldig georkestreerde reeks veiligheidscontroles, bestandsbewerkingen en systeemintegraties. Elke stap dient een doel, van het beschermen van gebruikers tegen gemanipuleerde apps tot het optimaliseren van de prestaties voor de specifieke hardware. Wanneer installaties mislukken, wijst de fout meestal op een specifieke stap in deze pijplijn. Als u het proces begrijpt, kunt u problemen snel diagnosticeren en oplossen.
Installeren vanuit de Play Store, handmatig sideloaden van een APK en het pushen van een build met ADB lopen allemaal door dezelfde onderliggende pijplijn, degene die ervoor zorgt dat elke app op uw apparaat is geverifieerd, correct geplaatst en geoptimaliseerd voor uw hardware.