Principe de construction de l'APK de peu profond à profond

Aperçu

Le processus de création d'APK implique de nombreux outils et processus de conversion d'un projet en package d'application Android (APK). Le processus de création est très flexible, il est donc utile de comprendre certains de ses principes de fonctionnement sous-jacents.

Le processus de construction détaillé de l'APK est un peu plus compliqué. Cet article sera divisé en quatre étapes, de la moins profonde à la plus profonde, avec une analyse approfondie du processus de construction par les lecteurs.

  • La première étape: voir la construction
  • Étape 2: Revisitez la construction
  • La troisième étape: la construction en profondeur
  • Étape 4: abandonner la construction

Construction à la première vue

Tout d'abord " voir la construction ", dans cette étape, nous pouvons d'abord ignorer les détails de la construction, et d'abord avoir une compréhension générale du processus principal.

Comme le montre la figure ci-dessus ( carré : indique le fichier, losange : indique l'opération):

1, l'ensemble de la construction est divisé en deux opérations principales: la compilation (la compilation), le conditionnement (package APK)

2. Compilateur : le compilateur compile le code source, les fichiers AIDL, les fichiers de ressources et les packages dépendants, et génère finalement des fichiers Dex et des fichiers de ressources compilés.

3. Empaquetage : Le conditionneur (APK Packager) utilise le fichier de signature (KeyStore), le fichier Dex généré lors du processus de compilation précédent et le fichier de ressources compilé à empaqueter dans le fichier APK final.

Revisiter la construction

Dans l'étape précédente " First See Construction ", nous avons une compréhension générale du processus de packaging de l'APK, allons un peu plus en détail.

( Carré : indique le fichier, ellipse : indique l'outil et l'opération)

L'image ci-dessus montre un processus de construction plus détaillé. Délimitée par une ligne discontinue, la première partie décrit le processus de compilation , décrit dans la dernière partie du processus de conditionnement .

L'analyse spécifique suivante du flux de génération est divisée en sept étapes (compilation 1-4, packaging 5-7):

    1. Utilisez l'outil __aapt__ pour compiler le res/fichier et générer le fichier de ressources binaires compilé (fichier .ap_) et le fichier R.java. (Actuellement, la nouvelle version utilise l'outil aapt2, et R.java a également été remplacé par R.jar)

    2. Utilisez l'outil __aidl__ pour générer le fichier d'interface Java correspondant basé sur le fichier aidl

    3. Utilisez l'outil __Java Compiler__, Java Compiler (communément appelé javac) pour compiler R.java, le code du projet et le fichier d'interface Aidl dans un fichier .class.

    4. Utilisez l'outil __dex__ pour compiler le fichier .class généré à l'étape précédente et le .class des dépendances tierces dans un fichier .dex. (Actuellement, la nouvelle version utilise l'outil d8)

    5. Utilisez l'outil __apkbuilder__ pour compresser les ressources compilées (fichiers .ap_), les fichiers dex et d'autres fichiers de ressources (par exemple: les fichiers so) dans un fichier .apk.

    6. Utilisez l'outil __Jarsigner__ pour lire le fichier de signature, signer le fichier apk généré à l'étape précédente et générer un fichier apk signé.

    7. Utilisez l'outil __zipalign__ pour optimiser le volume du fichier apk signé (cette étape n'est disponible que pour la signature v1, et l'apk signé v2 sera endommagé après zipalign).

Reposons-nous 3 minutes et digérons.

Construire en profondeur

Prêt à approfondir le processus de construction, l'image semble compliquée, mais il existe des compétences en lecture d'images:

Nous pouvons interpréter cet organigramme en nous référant aux images présentées dans " Revisiting Construction ".

Prenez l'ellipse (outils et opérations) comme indice et suivez le processus de construction décrit précédemment pour comprendre ce diagramme. Est-ce que aapt, aidl, javac, dex, apkbuilder, Jarsigner
et zipalign sont familiers?
Le gros bloc à gauche concerne Render Script et la compilation ndk, nous pouvons l'ignorer pour le moment (je crois que vous pouvez l'analyser vous-même si vous ne l'ignorez pas après avoir lu cet article), sachez simplement qu'il fournit .so fichiers et pièces Fichiers Java.

Tout d'abord, regardez dans le coin inférieur gauche. L'opération ellipse est divisée en trois types: plug-in Gradle (complété par tâche), outil de construction , JDK est livré avec

Prenons comme exemple aapt une analyse approfondie d'un processus de construction plus détaillé:

    Avant aapt, diverses tâches de fusion dans le plug-in Gradle fusionneront Manifest, Res et Assets. Ces ressources fusionnées peuvent provenir de tiers tels que des projets internes, android.jar et arr. Ces fichiers fusionnés sont utilisés comme fichiers d'entrée. Une fois appt compilé, les fichiers de ressources compilés, les fichiers R.java et aapt sont également responsables de la fusion de divers fichiers masqués.

    De plus, il existe un proguard (obfuscation) entre les opérations javac et dex. Proguard lit le fichier .class, génère le fichier .class obscurci et le donne à dex (ou d8).

Abandonner la construction

Très puissant, votre compréhension du processus de construction d'Android a dépassé la plupart des développeurs (je suppose :-)).

Mais c'est encore un peu loin de la pratique. Pensez à la façon dont gradle implémente le processus de construction mentionné ci-dessus lorsque nous cliquons pour exécuter?
Quand nous exécutons la assembleReleasecommande pour emballer, hein? Quelle est cette chaîne? Face au processus d'analyse ci-dessus, vous saurez de quoi il s'agit.

Version d'interprétation:

//以下两个task是预编译工作,暂不关心
> Task :app:preBuild UP-TO-DATE
> Task :app:preReleaseBuild UP-TO-DATE

//aidl编译
> Task :app:compileReleaseAidl NO-SOURCE

//生成BuildConfig文件
> Task :app:generateReleaseBuildConfig

//编译Renderscrip,暂不关心(感兴趣的可以去探究Renderscrip)
> Task :app:compileReleaseRenderscript NO-SOURCE
//*
> Task :app:javaPreCompileRelease

//生成资源文件并合并
> Task :app:generateReleaseResValues
> Task :app:generateReleaseResources
> Task :app:createReleaseCompatibleScreenManifests
> Task :app:extractDeepLinksRelease
> Task :app:processReleaseManifest
> Task :app:prepareLintJar UP-TO-DATE
> Task :app:checkReleaseDuplicateClasses
> Task :app:desugarReleaseFileDependencies
> Task :app:mergeReleaseResources

//产生build/intermediates/compile_and_runtime_not_namespaced_r_class_jar/release/R.jar文件
> Task :app:processReleaseResources

//javac将java编译成Class文件
> Task :app:compileReleaseJavaWithJavac

//将资源文件编译并生成resource.arsc文件,并放入.ap_文件中(./app/build/intermediates/processed_res/release/out/resources-release.ap_)
> Task :app:compileReleaseSources

> Task :app:lintVitalRelease

//dex工具将.class文件编程传.dex文件
> Task :app:dexBuilderRelease

//合并非res/的资源文件及assets文件
> Task :app:mergeExtDexRelease
> Task :app:mergeReleaseShaders
> Task :app:compileReleaseShaders NO-SOURCE
> Task :app:generateReleaseAssets UP-TO-DATE
> Task :app:mergeReleaseAssets
> Task :app:processReleaseJavaRes NO-SOURCE
> Task :app:collectReleaseDependencies
> Task :app:sdkReleaseDependencyData
> Task :app:mergeReleaseJniLibFolders
> Task :app:mergeReleaseNativeLibs
> Task :app:stripReleaseDebugSymbols NO-SOURCE
> Task :app:mergeReleaseJavaResource

//合并.dex文件
> Task :app:mergeDexRelease

//将.dex文件、.ap_打包进以及非res资源文件打包进.apk文件中并签名
> Task :app:packageRelease

使用zipalign对apk进行体积优化
> Task :app:assembleRelease

On dit que " abandonner la construction ", pourquoi n'avez-vous pas encore abandonné? Nous avons appris que le processus de construction, abandonnant maintenant l' apk de construction automatisée, utilise le manuel pour construire apk. Procédez comme suit:

    1. Compilez les fichiers de ressources res dans le projet (à l'exception des actifs), générez les fichiers de ressources binaires correspondants et compilez ces fichiers binaires dans le fichier res.zip.

$aapt2 compile -o build/res.zip --dir ./app/src/main/res

    2. Connectez le fichier res.zip au SDK pour générer des fichiers .ap_ (y compris des fichiers de ressources compilés, des fichiers manifestes et des fichiers arsc) et des fichiers R.java,

$ aapt2 link build/res.zip -I $ANDROID_HOME/platforms/android-21/android.jar --java build --manifest ./app/src/main/AndroidManifest.xml -o build/app-debug.ap_

    3. Compilez le fichier java dans un fichier .class

javac -d build -cp $ANDROID_HOME/platforms/android-21/android.jar com/*/.java

    4. Compilez le fichier .class généré à l'étape précédente dans un fichier .dex

d8 --output build/ --lib $ANDROID_HOME/platforms/android-21/android.jar build/com/example/application/*.class

    5. Utilisez la commande zip pour empaqueter le fichier de ressources .ap_ à l'étape (2) et le fichier .dex à l'étape (4) dans un apk non signé

zip -j build/app-debug.ap_ build/classes.dex

    6. Modifiez .ap_ en .apk et utilisez apksigner pour signer l'apk

apksign -ks ~/.android/debug.keystore build/app-debug.apk

Certains étudiants peuvent avoir des questions: Quelle est la relation entre aapt, aidl, javac, dex, apkbuilder Jarsigner, zipalign et les tâches du plug-in Gradle?

Réponse: Le processus de construction automatique du plugin Gradle consiste à appeler directement ou indirectement les outils utilisés dans le processus d'empaquetage manuel dans la tâche.

Pour résumer

À ce stade, le processus de construction de l'APK a été essentiellement analysé et les lecteurs peuvent mieux comprendre les opérations spécifiques de l'emballage du plug-in gradle en fonction du code source du plug-in gradle.

Vous pouvez écrire le code suivant dans le fichier build.gradle, générer la classe correspondant à chaque tâche, puis afficher le travail spécifique de la tâche:

//build.gradle
gradle.taskGraph.whenReady {
    it.allTasks.each { task ->
        println("Task Name : ${task.name}")
        task.dependsOn.each{ t->
            println "-----${t.class}"
        }
        //def outputFileStr = task.outputs.files.getAsPath();
    	//def inputFileStr = task.inputs.files.getAsPath()
    }
}

dependencies {
    ...
    testImplementation "com.android.tools.build:gradle:4.0.0"
    ...
}

(Pour les erreurs et les lacunes dans l'article de la réserve de connaissances, veuillez commenter et laisser un message, discuter ensemble et progresser ensemble :-)

Je suppose que tu aimes

Origine blog.csdn.net/weixin_36570478/article/details/109018059
conseillé
Classement