概要概要
APK構築プロセスには、プロジェクトをAndroidアプリケーションパッケージ(APK)に変換するための多くのツールとプロセスが含まれます。ビルドプロセスは非常に柔軟であるため、その基礎となる動作原理のいくつかを理解しておくと役立ちます。
詳細なAPK構築プロセスはもう少し複雑です。この記事は、浅いものから深いものまでの4つのステップに分かれており、読者は構築プロセスを詳細に分析します。
- 最初のステップ:ビルドを見る
- ステップ2:構造を再検討する
- ステップ3:詳細に構築する
- ステップ4:建物をあきらめる
ファーストサイトビルド
まず、「構造を見る」、このステップでは、構造の詳細を無視して、最初に主要なプロセスの一般的な理解を得ることができます。
上図に示すように(四角:ファイルを示し、ひし形:操作を示します):
1、全体の構成は2つの主要な操作に分けられます:コンパイル(コンパイル)、パッキング(APKパッケージ)
2.コンパイラ:コンパイラは、ソースコード、AIDLファイル、リソースファイル、および依存関係パッケージをコンパイルし、最後にDexファイルとコンパイルされたリソースファイルを生成します。
3.パッケージ化:パッケージャー(APK Packager)は、署名ファイル(KeyStore)、前のコンパイルプロセスで生成されたDexファイル、およびコンパイルされたリソースファイルを使用して最終的なAPKファイルにパッケージ化します。
建設を再考する
「FirstSeeingBuild」の前のステップでは、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はおなじみですか?左側の大きなブロックは、レンダリングスクリプトとndkのコンパイルに関するものです。当面は無視できます(この記事を読んだ後で無視しなくても、自分で分析できると思います)。.soファイルとパーツが提供されていることを知っておいてください。 Javaファイル。
まず、左下隅を見てください。楕円形の操作は3つのタイプに分けられます:Gradleプラグインが提供されます(タスクによって完了)、ビルドツールが提供されます、JDKには
例としてaaptを取り上げ、より詳細な構築プロセスの詳細な分析を行います。
aaptの前に、Gradleプラグインのさまざまなマージタスクは、Manifest、Res、およびAssetsをマージします。これらのマージされたリソースは、内部プロジェクト、android.jar、arrなどのサードパーティから提供される場合があります。これらのマージされたファイルは入力ファイルとして使用されます。apptがコンパイルされた後、コンパイルされたリソースファイル、R.javaファイル、およびaaptは、さまざまな難読化されたファイルのマージも担当します。
さらに、javac操作とdex操作の間にプロガード(難読化)があります。プロガードは.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"
...
}
(記事の間違いや欠陥については、コメントしてメッセージを残し、一緒に話し合い、一緒に進歩してください:-)