学前思考
build.gradle
里面的配置都有哪些属性Android Studio
点击运行图标,系统到底干了些啥,它如何把代码、资源这些东西整合成一个apk的?
由于一些老项目gradle
版本比较老,升级到最新的有难度,所以本篇还是以com.android.tools.build:gradle:4.1.3
为例讲讲项目的编译过程。
知识储备:
- Android Gradle学习(一)- 基本概念
- Android Gradle学习(二)- build.gradle结构
- Android Gradle学习(三)- 生命周期与构建过程
- Android Gradle学习(四)- gradle插件开发和调试
- Android Gradle学习(五)- gradle插件实战
1. build.gradle
属性配置
build.gradle
里面的android
,compileSdkVersion
这些配置都是哪里定义的?
之前做过gradle
插件的,可以看到gradle plugin
源码,没有的话就在app/build.gradle
手动加下依赖
arduino
dependencies {
implementation 'com.android.tools.build:gradle:4.1.3'
}
按照插件的引入规则,会有一个pluginid.properties
配置文件
groovy
classpath 'com.android.tools.build:gradle:4.1.3'
apply plugin: 'com.android.application'
所以插件的配置文件名称为com.android.application.properties
,此时根据该名称可以找到插件入口类AppPlugin
kotlin
class AppPlugin: BasePlugin() {
override fun apply(project: Project) {
super.apply(project)
project.apply(INTERNAL_PLUGIN_ID)
}
}
private val INTERNAL_PLUGIN_ID = mapOf("plugin" to "com.android.internal.application")
可以看到又引入了com.android.internal.application
插件,继续找到插件入口类AppPlugin
(注意这个类和上面的包名不一样)
AppPlugin.java
java
package com.android.build.gradle.internal.plugins;
public class AppPlugin
extends AbstractAppPlugin<ApplicationVariantImpl, ApplicationVariantPropertiesImpl> {
@Inject
public AppPlugin(
ToolingModelBuilderRegistry registry, SoftwareComponentFactory componentFactory) {
super(registry, componentFactory);
}
@Override
protected void pluginSpecificApply(@NonNull Project project) {
}
@Override
protected void registerModelBuilder(
@NonNull ToolingModelBuilderRegistry registry,
@NonNull GlobalScope globalScope,
@NonNull VariantModel variantModel,
@NonNull BaseExtension extension,
@NonNull ExtraModelInfo extraModelInfo) {
registry.register(
new AppModelBuilder(
globalScope,
variantModel,
(BaseAppModuleExtension) extension,
extraModelInfo,
projectServices.getIssueReporter(),
getProjectType()));
}
@Override
@NonNull
protected Class<? extends AppExtension> getExtensionClass() {
return BaseAppModuleExtension.class;
}
@NonNull
@Override
protected AppExtension createExtension(
@NonNull DslServices dslServices,
@NonNull GlobalScope globalScope,
@NonNull
DslContainerProvider<DefaultConfig, BuildType, ProductFlavor, SigningConfig>
dslContainers,
@NonNull NamedDomainObjectContainer<BaseVariantOutput> buildOutputs,
@NonNull ExtraModelInfo extraModelInfo) {
return project.getExtensions()
.create(
"android",
getExtensionClass(),
dslServices,
globalScope,
buildOutputs,
dslContainers.getSourceSetManager(),
extraModelInfo,
new ApplicationExtensionImpl(dslServices, dslContainers));
}
@NonNull
@Override
protected ApplicationTaskManager createTaskManager(
@NonNull List<ComponentInfo<ApplicationVariantImpl,
ApplicationVariantPropertiesImpl>> variants,
@NonNull List<ComponentInfo<TestComponentImpl<? extends TestComponentPropertiesImpl>,
TestComponentPropertiesImpl>> testComponents,
boolean hasFlavors,
@NonNull GlobalScope globalScope,
@NonNull BaseExtension extension,
@NonNull Recorder threadRecorder) {
return new ApplicationTaskManager(
variants, testComponents, hasFlavors, globalScope, extension, threadRecorder);
}
@NonNull
@Override
protected ApplicationVariantFactory createVariantFactory(
@NonNull ProjectServices projectServices, @NonNull GlobalScope globalScope) {
return new ApplicationVariantFactory(projectServices, globalScope);
}
}
可以看到createExtension
方法里面注册了额外参数android
,getExtensionClass()
返回了BaseAppModuleExtension.class
java
package com.android.build.gradle.internal.dsl
open class BaseAppModuleExtension(
dslServices: DslServices,
globalScope: GlobalScope,
buildOutputs: NamedDomainObjectContainer<BaseVariantOutput>,
sourceSetManager: SourceSetManager,
extraModelInfo: ExtraModelInfo,
private val publicExtensionImpl: ApplicationExtensionImpl
) : AppExtension(
dslServices,
globalScope,
buildOutputs,
sourceSetManager,
extraModelInfo,
true
), InternalApplicationExtension by publicExtensionImpl,
ActionableVariantObjectOperationsExecutor<ApplicationVariant<ApplicationVariantProperties>, ApplicationVariantProperties> by publicExtensionImpl {
// ...
}
BaseAppModuleExtension往上追溯,其实现了AndroidConfig
接口,每个属性都有注释,里面也有使用示例,建议去看看源码
java
package com.android.build.gradle
interface AndroidConfig {
/**
* Specifies the version of the
* [SDK Build Tools](https://developer.android.com/studio/releases/build-tools.html)
* to use when building your project.
*
* When using Android plugin 3.0.0 or later, configuring this property is optional. By
* default, the plugin uses the minimum version of the build tools required by the
* [version of the plugin](https://developer.android.com/studio/releases/gradle-plugin.html#revisions)
* you're using.
* To specify a different version of the build tools for the plugin to use,
* specify the version as follows:
*
* ```
* android {
* // Specifying this property is optional.
* buildToolsVersion "26.0.0"
* }
* ```
*
* For a list of build tools releases, read
* [the release notes](https://developer.android.com/studio/releases/build-tools.html#notes).
*
* Note that the value assigned to this property is parsed and stored in a normalized form,
* so reading it back may give a slightly different result.
*/
val buildToolsVersion: String
val compileSdkVersion: String?
val buildToolsRevision: Revision
val defaultPublishConfig: String
val variantFilter: Action<VariantFilter>?
val adbOptions: AdbOptions
val resourcePrefix: String?
val flavorDimensionList: List<String>
val generatePureSplits: Boolean
val defaultConfig: CoreProductFlavor
val aaptOptions: AaptOptions
val compileOptions: CompileOptions
val dexOptions: DexOptions
val jacoco: JacocoOptions
val lintOptions: LintOptions
val externalNativeBuild: CoreExternalNativeBuild
val packagingOptions: PackagingOptions
val splits: Splits
val testOptions: TestOptions
val deviceProviders: List<DeviceProvider>
val testServers: List<TestServer>
val transforms: List<Transform>
val transformsDependencies: List<List<Any>>
val productFlavors: Collection<CoreProductFlavor>
val buildTypes: Collection<CoreBuildType>
val signingConfigs: Collection<SigningConfig>
val sourceSets: NamedDomainObjectContainer<AndroidSourceSet>
val buildOutputs: Collection<BaseVariantOutput>
val aidlPackageWhiteList: MutableCollection<String>?
val libraryRequests: MutableCollection<LibraryRequest>
val dataBinding: DataBindingOptions
val baseFeature: Boolean?
val testBuildType: String?
val ndkVersion: String?
val bootClasspath: List<File>
}
而我们的build.gradle
配置如下
groovy
apply plugin: 'com.android.application'
apply plugin: 'com.kongge.common_plugin'
android {
compileSdkVersion 30
defaultConfig {
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
vectorDrawables.useSupportLibrary = true
applicationId 'com.kongge.demo'
}
sourceSets {
main {
java.srcDirs = ['src/main/java']
jniLibs.srcDirs = ['libs']
res.srcDirs = ['src/main/res']
}
}
buildTypes {
release {
debuggable false
minifyEnabled true
proguardFile file('proguard-rules.pro')
zipAlignEnabled false
multiDexEnabled true
}
debug {
minifyEnabled false
zipAlignEnabled false
multiDexEnabled true
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.aar'])
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
implementation project(':commonsdk')
}
commonParam {
enable = true
doubleClickTimeSpace = 600
}
可以看到build.gradle android
下的扩展配置在AndroidConfig.kt
里面都可以找到。
那么二级配置属性又是哪里定义的?比如defaultConfig
里的minSdkVersion
是哪里定义的,除了minSdkVersion
,defaultConfig
还支持哪些属性?
groovy
android {
compileSdkVersion 30
defaultConfig {
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
vectorDrawables.useSupportLibrary = true
applicationId 'com.kongge.demo'
}
}
首先在AndroidConfig.kt
里找到defaultConfig
并查看它的class
定义
kotlin
val defaultConfig: CoreProductFlavor
CoreProductFlavor.kt
kotlin
interface CoreProductFlavor : ProductFlavor, Named {
val ndkConfig: CoreNdkOptions
val externalNativeBuildOptions: CoreExternalNativeBuildOptions
val javaCompileOptions: JavaCompileOptions
val shaders: CoreShaderOptions
}
CoreProductFlavor
实现了接口ProductFlavor
kotlin
package com.android.builder.model
interface ProductFlavor : BaseConfig, DimensionAware {
override fun getName(): String
val applicationId: String?
val versionCode: Int?
val versionName: String?
val minSdkVersion: ApiVersion?
val targetSdkVersion: ApiVersion?
val maxSdkVersion: Int?
val renderscriptTargetApi: Int?
val renderscriptSupportModeEnabled: Boolean?
val renderscriptSupportModeBlasEnabled: Boolean?
val renderscriptNdkModeEnabled: Boolean?
val testApplicationId: String?
val testInstrumentationRunner: String?
val testInstrumentationRunnerArguments: Map<String, String>
val testHandleProfiling: Boolean?
val testFunctionalTest: Boolean?
val resourceConfigurations: Collection<String>
val signingConfig: SigningConfig?
val vectorDrawables: VectorDrawablesOptions
val wearAppUnbundled: Boolean?
}
ProductFlavor
又继承了接口BaseConfig
kotlin
package com.android.builder.model
import java.io.File
interface BaseConfig: Named {
override fun getName(): String
val applicationIdSuffix: String?
val versionNameSuffix: String?
val buildConfigFields: Map<String, ClassField>
val resValues: Map<String, ClassField>
val proguardFiles: Collection<File>
val consumerProguardFiles: Collection<File>
val testProguardFiles: Collection<File>
val manifestPlaceholders: Map<String, Any>
val multiDexEnabled: Boolean?
val multiDexKeepFile: File?
val multiDexKeepProguard: File?
}
此时便找到了defaultConfig
支持的属性
2. 任务构建
Android gradle plugin
本质上也是个gradle
插件,所以其也是有个入口pluginid.properties
配置文件和入口class
的,文章上面也介绍了。该插件会生成一些Task
,组建成一个有向无环图,最后依次执行这些Task。
此时回到插件入口AppPlugin.java
java
package com.android.build.gradle.internal.plugins;
public class AppPlugin
extends AbstractAppPlugin<ApplicationVariantImpl, ApplicationVariantPropertiesImpl> {
// ...
}
其apply
入口在父类BasePlugin.kt
kotlin
@Override
public final void apply(@NonNull Project project) {
CrashReporting.runAction(
() -> {
basePluginApply(project);
pluginSpecificApply(project);
});
}
private void basePluginApply(@NonNull Project project) {
// ...一些配置
// 配置
threadRecorder.record(
ExecutionType.BASE_PLUGIN_PROJECT_CONFIGURE,
project.getPath(),
null,
this::configureProject);
// 扩展参数,此处调用配置了android额外配置
threadRecorder.record(
ExecutionType.BASE_PLUGIN_PROJECT_BASE_EXTENSION_CREATION,
project.getPath(),
null,
this::configureExtension);
// 创建Tasks
threadRecorder.record(
ExecutionType.BASE_PLUGIN_PROJECT_TASKS_CREATION,
project.getPath(),
null,
this::createTasks);
}
creatTasks()
创建了所有的Task
less
private void createTasks() {
threadRecorder.record(
ExecutionType.TASK_MANAGER_CREATE_TASKS,
project.getPath(),
null,
() ->
TaskManager.createTasksBeforeEvaluate(
globalScope,
variantFactory.getVariantType(),
extension.getSourceSets()));
project.afterEvaluate(
CrashReporting.afterEvaluate(
p -> {
variantInputModel.getSourceSetManager().runBuildableArtifactsActions();
threadRecorder.record(
ExecutionType.BASE_PLUGIN_CREATE_ANDROID_TASKS,
project.getPath(),
null,
this::createAndroidTasks);
}));
}
任务创建分为两个阶段:beforeEvaluate
和afterEvaluate
beforeEvaluate
阶段创建Task
:TaskManager.kt
kotlin
public static void createTasksBeforeEvaluate(
@NonNull GlobalScope globalScope,
@NonNull VariantType variantType,
@NonNull Iterable<AndroidSourceSet> sourceSetContainer) {
final Project project = globalScope.getProject();
TaskFactoryImpl taskFactory = new TaskFactoryImpl(project.getTasks());
taskFactory.register(
UNINSTALL_ALL,
uninstallAllTask -> {
uninstallAllTask.setDescription("Uninstall all applications.");
uninstallAllTask.setGroup(INSTALL_GROUP);
});
taskFactory.register(
DEVICE_CHECK,
deviceCheckTask -> {
deviceCheckTask.setDescription(
"Runs all device checks using Device Providers and Test Servers.");
deviceCheckTask.setGroup(JavaBasePlugin.VERIFICATION_GROUP);
});
taskFactory.register(
CONNECTED_CHECK,
connectedCheckTask -> {
connectedCheckTask.setDescription(
"Runs all device checks on currently connected devices.");
connectedCheckTask.setGroup(JavaBasePlugin.VERIFICATION_GROUP);
});
// Make sure MAIN_PREBUILD runs first:
taskFactory.register(MAIN_PREBUILD);
taskFactory.register(new ExtractProguardFiles.CreationAction(globalScope))
.configure(it -> it.dependsOn(MAIN_PREBUILD));
taskFactory.register(new SourceSetsTask.CreationAction(sourceSetContainer));
taskFactory.register(
ASSEMBLE_ANDROID_TEST,
assembleAndroidTestTask -> {
assembleAndroidTestTask.setGroup(BasePlugin.BUILD_GROUP);
assembleAndroidTestTask.setDescription("Assembles all the Test applications.");
});
taskFactory.register(new LintCompile.CreationAction(globalScope));
if (!variantType.isForTesting()) {
taskFactory.register(LINT, LintGlobalTask.class, task -> {});
taskFactory.configure(JavaBasePlugin.CHECK_TASK_NAME, it -> it.dependsOn(LINT));
taskFactory.register(LINT_FIX, LintFixTask.class, task -> {});
}
// create a single configuration to point to a project or a local file that contains
// the lint.jar for this project.
// This is not the configuration that consumes lint.jar artifacts from normal dependencies,
// or publishes lint.jar to consumers. These are handled at the variant level.
globalScope.setLintChecks(createCustomLintChecksConfig(project));
globalScope.setLintPublish(createCustomLintPublishConfig(project));
globalScope.setAndroidJarConfig(createAndroidJarConfig(project));
taskFactory.register(new CleanBuildCache.CreationAction(globalScope));
// for testing only.
taskFactory.register("resolveConfigAttr", ConfigAttrTask.class, task -> task.resolvable = true);
taskFactory.register("consumeConfigAttr", ConfigAttrTask.class, task -> task.consumable = true);
// This needs to be resolved before tasks evaluation since it does some configuration inside
// By resolving it here we avoid configuration problems. The value returned will be cached
// and returned immediately later when this method is invoked.
Aapt2MavenUtils.getAapt2FromMavenAndVersion(globalScope);
createCoreLibraryDesugaringConfig(project);
}
可以看到创建的task
有uninstallAll
、preBuild
等,这些都是与渠道无关的,所以在一开始就可以创建。
还有一些task是需要在所有的task配置加载之后再创建的,现在看看createAndroidTasks()
kotlin
final void createAndroidTasks() {
// ...
if (hasCreatedTasks) {
return;
}
hasCreatedTasks = true;
extension.disableWrite();
variantManager.createVariants();
List<ComponentInfo<VariantT, VariantPropertiesT>> variants =
variantManager.getMainComponents();
TaskManager<VariantT, VariantPropertiesT> taskManager =
createTaskManager(
variants,
variantManager.getTestComponents(),
!variantInputModel.getProductFlavors().isEmpty(),
globalScope,
extension,
threadRecorder);
taskManager.createTasks();
taskManager.createPostApiTasks();
variantManager.setHasCreatedTasks(true);
GradleProperty.Companion.endOfEvaluation();
}
kotlin
public void createTasks() {
taskFactory.register(new PrepareLintJarForPublish.CreationAction(globalScope));
taskFactory.register(
COMPILE_LINT_CHECKS_TASK,
task -> task.dependsOn(globalScope.getLocalCustomLintChecks()));
// Create top level test tasks.
createTopLevelTestTasks();
// Create tasks for all variants (main and tests)
for (ComponentInfo<VariantT, VariantPropertiesT> variant : variants) {
createTasksForVariant(variant, variants);
}
for (ComponentInfo<TestComponentImpl<? extends TestComponentPropertiesImpl>,TestComponentPropertiesImpl> testComponent : testComponents) {
createTasksForTest(testComponent);
}
createReportTasks();
}
private void createTasksForVariant(
@NonNull ComponentInfo<VariantT, VariantPropertiesT> variant,
@NonNull List<ComponentInfo<VariantT, VariantPropertiesT>> variants) {
final VariantPropertiesT variantProperties = variant.getProperties();
final VariantType variantType = variantProperties.getVariantType();
VariantDependencies variantDependencies = variantProperties.getVariantDependencies();
// ...
createAssembleTask(variantProperties);
if (variantType.isBaseModule()) {
createBundleTask(variantProperties);
}
doCreateTasksForVariant(variant, variants);
}
终于看到了创建assemble task
的地方createAssembleTask
kotlin
public void createAssembleTask(@NonNull ComponentPropertiesImpl componentProperties) {
taskFactory.register(
componentProperties.computeTaskName("assemble"),
null /*preConfigAction*/,
task ->
task.setDescription(
"Assembles main output for variant "
+ componentProperties.getName()),
taskProvider ->
componentProperties.getTaskContainer().setAssembleTask(taskProvider));
}
其他任务创建继续跟进doCreateTasksForVariant(variant, variants)
,此处TaskManager
是ApplicationTaskManager
kotlin
override fun doCreateTasksForVariant(
variant: ComponentInfo<ApplicationVariantImpl, ApplicationVariantPropertiesImpl>,
allVariants: MutableList<ComponentInfo<ApplicationVariantImpl, ApplicationVariantPropertiesImpl>>
) {
createCommonTasks(variant, allVariants)
// ...
// Base feature specific tasks.
taskFactory.register(FeatureSetMetadataWriterTask.CreationAction(variantProperties))
createValidateSigningTask(variantProperties)
createDynamicBundleTask(variant)
}
kotlin
protected void createCommonTasks(
@NonNull ComponentInfo<VariantT, VariantPropertiesT> variant,
@NonNull List<ComponentInfo<VariantT, VariantPropertiesT>> allComponentsWithLint) {
VariantPropertiesT appVariantProperties = variant.getProperties();
ApkCreationConfig apkCreationConfig = (ApkCreationConfig) appVariantProperties;
createAnchorTasks(appVariantProperties);
taskFactory.register(new ExtractDeepLinksTask.CreationAction(appVariantProperties));
// Create all current streams (dependencies mostly at this point)
createDependencyStreams(appVariantProperties);
// Add a task to publish the applicationId.
// TODO remove case once TaskManager's type param is based on BaseCreationConfig
createApplicationIdWriterTask(apkCreationConfig);
// Add a task to check the manifest
taskFactory.register(new CheckManifest.CreationAction(appVariantProperties));
// Add a task to process the manifest(s)
createMergeApkManifestsTask(appVariantProperties);
// Add a task to create the res values
createGenerateResValuesTask(appVariantProperties);
// Add a task to compile renderscript files.
createRenderscriptTask(appVariantProperties);
// Add a task to merge the resource folders
createMergeResourcesTasks(appVariantProperties);
// Add tasks to compile shader
createShaderTask(appVariantProperties);
// Add a task to merge the asset folders
createMergeAssetsTask(appVariantProperties);
taskFactory.register(new CompressAssetsTask.CreationAction(apkCreationConfig));
// Add a task to create the BuildConfig class
createBuildConfigTask(appVariantProperties);
// Add a task to process the Android Resources and generate source files
createApkProcessResTask(appVariantProperties);
registerRClassTransformStream(appVariantProperties);
// Add a task to process the java resources
createProcessJavaResTask(appVariantProperties);
createAidlTask(appVariantProperties);
// Add external native build tasks
createExternalNativeBuildJsonGenerators(appVariantProperties);
createExternalNativeBuildTasks(appVariantProperties);
// Add a task to merge the jni libs folders
createMergeJniLibFoldersTasks(appVariantProperties);
// Add data binding tasks if enabled
createDataBindingTasksIfNecessary(appVariantProperties);
// Add a task to auto-generate classes for ML model files.
createMlkitTask(appVariantProperties);
// Add a compile task
createCompileTask(appVariantProperties);
taskFactory.register(new StripDebugSymbolsTask.CreationAction(appVariantProperties));
taskFactory.register(
new ExtractNativeDebugMetadataTask.FullCreationAction(appVariantProperties));
taskFactory.register(
new ExtractNativeDebugMetadataTask.SymbolTableCreationAction(appVariantProperties));
createPackagingTask(apkCreationConfig);
maybeCreateLintVitalTask(appVariantProperties, allComponentsWithLint);
// Create the lint tasks, if enabled
createLintTasks(appVariantProperties, allComponentsWithLint);
taskFactory.register(
new PackagedDependenciesWriterTask.CreationAction(appVariantProperties));
taskFactory.register(new ApkZipPackagingTask.CreationAction(appVariantProperties));
}
至此,大部分Task
的创建过程都找到了
3. 问题回顾
3.1 build.gradle
里面的配置都有哪些属性
可以查看Android gradle plugin
源码,找到AndroidConfig.kt
3.2 Android Studio
点击运行图标,系统到底干了些啥,它如何把代码、资源这些东西整合成一个apk的?
Android Studio
点击运行图标看到日志输入
ruby
Executing tasks: [:app:assembleDebug] in project E:\git\Demo2
> Configure project :app
----------CommonPlugin start----------
----------CommonPlugin end----------
enable=true
doubleClickTimeSpace=600
> Task :app:preBuild UP-TO-DATE
> Task :app:preDebugBuild UP-TO-DATE
可以看到实际上执行的是assembleDebug
任务,任务的概念可以看看Android Gradle学习(三)- 生命周期与构建过程,那么这个任务的生成过程,上面已经讲到了,下面是个小结
AppPlugin
: 插件入口BasePlugin
:AppPlugin
的父类,统一加载配置和创建Task
TaskManager
: 任务管理抽象类,其createTasksBeforeEvaluate
静态方法用于创建在gradle配置期间的Task
,比如uninstallAll
BasePlugin createAndroidTasks()
是在配置加载完成之后(afterInvaluate
)创建Android
相关的Task
TaskFactoryImpl
: 任务工厂,其内部管理了taskContainer
,用户保存Task
TaskManager createAssembleTask()
创建了assemble Task
ApplicationTaskManager createCommonTasks()
创建了Android
相关的Task
,比如检查Manifest,合并资源等等,顺带着构建了任务依赖树