概要概要
APKの構築プロセスには、プロジェクトをAndroidアプリケーションパッケージ(APK)に変換するための多くのツールとプロセスが含まれます。ビルドプロセスは非常に柔軟であるため、その基礎となる動作原理のいくつかを理解しておくと役立ちます。
詳細なAPK構築プロセスはもう少し複雑です。この記事は、浅いものから深いものまでの4つのステップに分かれており、読者は構築プロセスを詳細に分析します。
- 最初のステップ:ビルドを見る
- ステップ2:建設を再検討する
- 3番目のステップ:詳細な構築
- ステップ4:ビルドを中止する
ファーストサイトビルド
まず、「構造を見る」、このステップでは、最初に構造の詳細を無視して、最初に主要なプロセスの一般的な理解を得ることができます。
上の図に示すように(四角:ファイルを示し、ひし形:操作を示します):
1、全体の構成は2つの主要な操作に分けられます:コンパイル(コンパイル)、パッキング(APKパッケージ)
2.コンパイラ:コンパイラは、ソースコード、AIDLファイル、リソースファイル、および依存パッケージをコンパイルし、最後にDexファイルとコンパイルされたリソースファイルを生成します。
3.パッケージ化:パッケージャー(APK Packager)は、署名ファイル(KeyStore)、前のコンパイルプロセスで生成されたDexファイル、およびコンパイルされたリソースファイルを使用して最終的なAPKファイルにパッケージ化します。
建設を再考する
前のステップ「FirstSeeConstruction」では、APKパッケージングプロセスの一般的な理解がありました。もう少し詳しく見ていきましょう。
(四角:ファイルを示し、楕円:ツールと操作を示します)
上の写真は、より詳細な建設プロセスを示しています。破線で囲まれた最初の部分は、パッケージ化プロセスの後半で説明されているコンパイルプロセスを説明しています。
ビルドフローの次の特定の分析は、7つのステップ(コンパイル1〜4、パッケージ5〜7)に分かれています。
1. __aapt__ツールを使用してres/
ファイルをコンパイルし、コンパイルされたバイナリリソースファイル(.ap_ファイル)とR.javaファイルを生成します。(現在、新しいバージョンはaapt2ツールを使用しており、R.javaもR.jarに置き換えられています)
2. __aidl__ツールを使用して、aidlファイルに基づいて対応するJavaインターフェースファイルを生成します。
3. __Javaコンパイラ__ツール、Javaコンパイラ(一般にjavacとして知られている)を使用して、R.java、プロジェクト内のコード、およびAidlインターフェイスファイルを.classファイルにコンパイルします。
4. __dex__ツールを使用して、前の手順で生成された.classファイルとサードパーティの依存関係の.classを.dexファイルにコンパイルします。(現在、新しいバージョンはd8ツールを使用しています)
5. __apkbuilder__ツールを使用して、コンパイルされたリソース(.ap_ファイル)、dexファイル、およびその他のリソースファイル(例:soファイル)を.apkファイルに圧縮します。
6. __Jarsigner__ツールを使用して署名ファイルを読み取り、前の手順で生成されたapkファイルに署名し、署名されたapkファイルを生成します。
7. __zipalign__ツールを使用して、署名されたapkファイルのボリュームを最適化します(この手順はv1署名でのみ使用可能であり、v2署名付きapkはzipalign後に破損します)。
3分間休んで消化しましょう。
深く構築する
建設プロセスに深く入り込む準備ができているので、絵は複雑に見えますが、絵を読むスキルがあります。
このフローチャートは、「建設の再考」に示されている写真を参照することで解釈できます。
楕円(ツールと操作)を手がかりとして、前述の構築プロセスに従ってこの図を理解してください。aapt、aidl、javac、dex、apkbuilder
Jarsigner、およびzipalignはおなじみですか?
左側の大きなブロックは、Render Scriptとndkのコンパイルに関するものです。当面は無視できます(この記事を読んだ後で無視しなければ、自分で分析できると思います)。.soが提供されていることを知っておいてください。ファイルとパーツJavaファイル。
まず、左下隅を見てください。楕円形の操作は、Gradleプラグイン(タスクごとに完了する)、ビルドツール、JDKの3つのタイプに分けられます。
例としてaaptを取り上げ、より詳細な建設プロセスの詳細な分析を行います。
aaptの前に、Gradleプラグインのさまざまなマージタスクは、マニフェスト、解像度、アセットをマージします。これらのマージされたリソースは、内部プロジェクト、android.jar、arrなどのサードパーティから提供される場合があります。これらのマージされたファイルは入力ファイルとして使用されます。apptがコンパイルされた後、コンパイルされたリソースファイル、R.javaファイル、およびaaptは、さまざまな難読化されたファイルのマージも担当します。
さらに、javac操作とdex操作の間にproguard(難読化)があります。Proguardは.classファイルを読み取り、難読化された.classファイルを生成して、dex(またはd8)に渡します。
建物をあきらめる
非常に強力で、Androidビルドプロセスの理解はほとんどの開発者を上回っています(私は推測します:-))。
しかし、それはまだ少し練習にはほど遠いです。クリックして実行するときに、gradleが上記のビルドプロセスをどのように実装するかを考えてみてください。パック
するassembleRelease
コマンドを実行すると、ハァッ?この文字列は何ですか?上記の分析プロセスに直面して、あなたはそれが何であるかを知るでしょう。
解釈バージョン:
//以下两个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
「工事を断念する」と言われていますが、なぜまだ諦めていませんか?ビルドプロセスは、自動ビルドapkを放棄し、マニュアルを使用してapkをビルドすることを学びました。次のように実行します。
1.プロジェクト内のresリソースファイル(アセットを除く)をコンパイルし、対応するバイナリリソースファイルを生成し、これらのバイナリファイルをres.zipファイルにパックします。
$aapt2 compile -o build/res.zip --dir ./app/src/main/res
2. res.zipファイルをSDKに接続して、.ap_ファイル(コンパイル済みリソースファイル、マニフェストファイル、arscファイルを含む)と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.javaファイルを.classファイルにコンパイルします
javac -d build -cp $ANDROID_HOME/platforms/android-21/android.jar com/*/.java
4.前の手順で生成された.classファイルを.dexファイルにコンパイルします
d8 --output build/ --lib $ANDROID_HOME/platforms/android-21/android.jar build/com/example/application/*.class
5. zipコマンドを使用して、手順(2)の.ap_リソースファイルと手順(4)の.dexファイルを署名されていないapkにパッケージ化します。
zip -j build/app-debug.ap_ build/classes.dex
6. .ap_を.apkに変更し、apksignerを使用してapkに署名します
apksign -ks ~/.android/debug.keystore build/app-debug.apk
一部の学生は質問があるかもしれません.aapt、aidl、javac、dex、apkbuilder Jarsigner、zipalignとGradleプラグインのタスクとの関係は何ですか?
回答:Gradleプラグインの自動ビルドプロセスは、タスクの手動パッケージングプロセスで使用されるツールを直接または間接的に呼び出すことです。
総括する
この時点で、APKの構築プロセスは基本的に分析されており、読者は、gradleプラグインのソースコードに従って、gradleプラグインパッケージの特定の操作をさらに理解できます。
build.gradleファイルに次のコードを記述し、各タスクに対応するクラスを出力してから、タスクの特定の作業を表示できます。
//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"
...
}
(ナレッジリザーブ記事の間違いや欠陥については、コメントしてメッセージを残し、一緒に話し合い、一緒に進歩してください:-)