きっかけ
ビルド終わったあとに処理を差し込むプラグイン作りたいです。apkの前回との差分をチェックするみたいなプラグインが作りたいです。(誰かスマートなやり方を知っていたら教えて下さい。)
Android Studioのビルドを追えばきっとその近いところまでいけるはずです。
読み違えているところなどあればご指摘お願いします。
調べてみる
Android Studioが利用している、Android関連の実装が入っているAndroid Pluginのソースコードはどうやらここにおいてあるようです(http://tools.android.com/build/studio より)
https://android.googlesource.com/platform/tools/adt/idea/+/studio-master-dev
ここに公式のAndroid Studioが実行するまでの流れなどのドキュメントが置いてあります。
このドキュメントを見ながら読んでみました。
https://android.googlesource.com/platform/tools/adt/idea/+/studio-master-dev/android/src/com/android/tools/idea/run/README.md
Android Applicationの設定が追加されるまで
Android Pluginのplugin.xml(AndroidManifestみたいなもの)がこれになります。
https://android.googlesource.com/platform/tools/adt/idea/+/studio-master-dev/android/src/META-INF/plugin.xml
plugin.xmlで宣言されているconfigurationTypeが以下になります。
<configurationType implementation="com.android.tools.idea.run.AndroidRunConfigurationType"/>
<configurationType implementation="com.android.tools.idea.run.testing.AndroidTestRunConfigurationType"/>
ConfigrationTypeとはこの"Android Application"と"Android Tests"のことです。
com.android.tools.idea.run.AndroidRunConfigurationTypeクラスが以下になります。
https://android.googlesource.com/platform/tools/adt/idea/+/studio-master-dev/android/src/com/android/tools/idea/run/AndroidRunConfigurationType.java
AndroidRunConfigurationFactoryよりnew AndroidRunConfiguration(project, this);
され、AndroidRunConfigurationが利用されます。
AndroidRunConfigurationクラスが以下になります。
https://android.googlesource.com/platform/tools/adt/idea/+/studio-master-dev/android/src/com/android/tools/idea/run/AndroidRunConfiguration.java
ビルドされるまで
この記述がplugin.xmlにあるこれが端末にインストールされたり、起動される前に実行される。
ここでビルドを行う。
<stepsBeforeRunProvider implementation="com.android.tools.idea.gradle.run.MakeBeforeRunTaskProvider" />
MakeBeforeRunTaskProviderで以下のようにGradleTaskRunnerを呼び出す。createBuilder()してbuilderを作る。
BeforeRunBuilder builder =
createBuilder(env, getModules(myProject, context, configuration), configuration, runConfigContext, task.getGoal());
try {
boolean success = builder.build(GradleTaskRunner.newRunner(myProject), cmdLineArgs);
LOG.info("Gradle invocation complete, success = " + success);
return success;
}
createBuilder()で作ったのはこういう感じで、BuildMode.ASSEMBLEなどが入っている。
return new DefaultGradleBuilder(gradleTasksProvider.getTasksFor(BuildMode.ASSEMBLE, testCompileType), BuildMode.ASSEMBLE);
GradleTaskRunnerでGradleInvokerが実行される。
gradleInvoker.addAfterGradleInvocationTask(afterTask);
gradleInvoker.executeTasks(tasks, buildMode, args);
あとはInvokerでよしなにGradleタスクを作って実行しているみたい。
stepsBeforeRunProviderに代わりに自分の実装を差し込むと、Google Compute Engineでビルドさせるなどビルドの部分だけ差し替えができるみたい。(すごい)
https://github.com/nonylene/GradleExternalBuildPlugin
起動されるまで
先ほど書いたAndroidRunConfigurationBaseはgetStateを継承していて、Android Studio側からgetStateが呼ばれるので、AndroidRunStateを返す。
AndroidRunStateではexecute()が実行され、AndroidLaunchTasksProviderを使ってLaunchTaskを取得します。
https://android.googlesource.com/platform/tools/adt/idea/+/studio-master-dev/android/src/com/android/tools/idea/run/AndroidRunState.java#68
AndroidLaunchTasksProviderではDeployApkTaskを返します。
return new DeployApkTask(myFacet, myLaunchOptions, myApkProvider, instantRunAware);
DeployApkTaskではアップロードやインストールを行う
String pkgName = apk.getApplicationId();
if (!installer.uploadAndInstallApk(device, pkgName, apk.getFile(), launchStatus)) {
return false;
}
まとめ
読めなくはなかったです。
stepsBeforeRunProviderで自分で差し替えるハックはすごい。
ビルド終わったあとに処理を差し込みたいが、stepsBeforeRunProvider
のafter版みたいな奴はなかったので、どうしたものか、、