一怠噪、引入flutter.gradle文件
基于flutter1.9.1版本区赵。
Flutter項目android工程app主模塊愉烙,引入flutter.gradle配置文件减牺,該文件在flutter sdk的flutter/packages/flutter_tools/gradle/目錄下页徐,目的是在普通android工程的編譯打包流程中插入一些Flutter任務(wù)苏潜。
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
app主模塊,當(dāng)Gradle運行到apply from時变勇,進入flutter.gradle執(zhí)行恤左,代碼流程。
在flutter.gradle文件搀绣,首先執(zhí)行buildscript代碼塊飞袋,然后順序執(zhí)行,代碼結(jié)構(gòu)链患。
定義一個FlutterPlugin插件巧鸭,實現(xiàn)接口Plugin<Project>的apply方法,Gradle運行到apply plugin: FlutterPlugin
語句時麻捻,去執(zhí)行apply方法(插入任務(wù))纲仍,執(zhí)行結(jié)束回到app主模塊,繼續(xù)主模塊Gradle文件后面的代碼芯肤。
FlutterTask任務(wù)類、FlutterPluginTask任務(wù)類压鉴。
引入flutter.gradle的配置文件僅執(zhí)行buildscript代碼塊和FlutterPlugin插件的apply方法崖咨,目的是插入Flutter任務(wù)。
二油吭、插件
定義FlutterPlugin插件击蹲,實現(xiàn)接口Plugin<Project>,apply方法婉宰。
@Override
void apply(Project project) {
}
Project代表android工程的app模塊歌豺,project.getName()
是app。
project.afterEvaluate this.&addFlutterTasks
afterEvaluate心包,當(dāng)apply()方法結(jié)束类咧,project(app模塊)的Gradle完成,再添加Flutter任務(wù)蟹腾,調(diào)用addFlutterTasks()方法痕惋。
String flutterRootPath = resolveProperty(project, "flutter.sdk", System.env.FLUTTER_ROOT)
查找父目錄下的local.properties
文件,即(工程根目錄)娃殖,獲取flutter.sdk路徑和bin目錄下可執(zhí)行文件值戳。
String flutterExecutableName = Os.isFamily(Os.FAMILY_WINDOWS) ? "flutter.bat" : "flutter"
flutterExecutable = Paths.get(flutterRoot.absolutePath, "bin", flutterExecutableName).toFile();
根據(jù)不同平臺去加載可執(zhí)行文件。
# basePlatform目標(biāo)平臺默認:android-arm64
String basePlatformArch = getBasePlatform(project)
Path baseEnginePath = Paths.get(flutterRoot.absolutePath, "bin", "cache", "artifacts", "engine")
File debugJar = baseEnginePath.resolve("${basePlatformArch}").resolve("flutter.jar").toFile()
baseJar["debug"] = debugJar
baseJar["profile"] = baseEnginePath.resolve("${basePlatformArch}-profile").resolve("flutter.jar").toFile()
baseJar["release"] = baseEnginePath.resolve("${basePlatformArch}-release").resolve("flutter.jar").toFile()
從sdk的/bin/cache/artifacts/engine/
路徑炉爆,創(chuàng)建flutter.jar文件的Flie堕虹,三種構(gòu)建模式debug卧晓,profile和release,從android-arm64-xxx對應(yīng)目錄加載赴捞。
project.android.buildTypes.each {
def buildMode = buildModeFor(it)
println "each buildTypes 構(gòu)建類型: $buildMode 添加flutter.jar依賴"
addApiDependencies(project, it.name, project.files {
baseJar[buildMode]
})
}
遍歷構(gòu)建模式逼裆,通過project.dependencies.add()
方法,添加android主模塊對flutter.jar的依賴螟炫,project是android工程的app模塊波附。
if (project.getConfigurations().findByName("api")) {
configuration = "${variantName}Api";
} else {
configuration = "${variantName}Compile";
}
project.dependencies.add(configuration, dependency, config)
構(gòu)建類型XxxApi,依賴文件昼钻。
三掸屡、任務(wù)
插件apply()完成,afterEvaluate設(shè)置addFlutterTasks()任務(wù)添加方法執(zhí)行然评。
private void addFlutterTasks(Project project) {
}
通過project.tasks.create()
方法添加仅财。
## 目標(biāo)平臺:[android-arm, android-arm64]
def targetPlatforms = getTargetPlatforms(project)
默認平臺是arm和arm64。
1碗淌,編譯任務(wù)
FlutterTask compileTask = project.tasks.create(name: taskName, type: FlutterTask) {
}
任務(wù)名:compileFlutterDebug構(gòu)建模式+平臺盏求,類型是FlutterTask類,自定義任務(wù)類亿眠。
compileFlutterBuildXxxArm碎罚,compileFlutterBuildXxxArm64
構(gòu)建模式:Debug,Profile纳像,Release
abi平臺:Arm(32)和Arm64
addFlutterTasks方法僅將任務(wù)添加到Gradle的構(gòu)建流程中荆烈,運行在編譯過程中觸發(fā)。
FlutterTask類build方法竟趾,父類DefaultTask的buildBundle()方法憔购。
@TaskAction
void build() {
buildBundle()
}
編譯任務(wù)生成Dart產(chǎn)物build目錄:intermediates/flutter/xxx/平臺/。在平臺目錄下岔帽,產(chǎn)物debug和release模式不同玫鸟,
debug模式:flutter_assets目錄下kernel_blob.bin,vm_snapshot_data犀勒,isolate_snapshot_data屎飘。
releass模式:flutter_assets目錄+app.so。
2贾费,lib任務(wù)
Task packFlutterSnapshotsAndLibsTask = project.tasks.create(name:
"packLibs${FLUTTER_BUILD_PREFIX}${variant.name.capitalize()}", type: Jar) {
}
任務(wù)名:packLibsflutterBuild構(gòu)建模式枚碗,類型是Jar類,Gradle內(nèi)置任務(wù)類铸本,將sdk中對應(yīng)平臺libflutter.so文件寫入libs.jar壓縮包肮雨。
packLibsflutterBuildXxx,依賴對應(yīng)編譯任務(wù)
構(gòu)建模式:Debug箱玷,Profile怨规,Release
abi平臺:依賴編譯任務(wù)生成的目標(biāo)平臺
debug模式陌宿,增加兩個平臺。
if (flutterBuildMode == 'debug') {
libFlutterPlatforms.add('android-x86')
libFlutterPlatforms.add('android-x64')
}
在build/intermediates/flutter/xxx目錄波丰,定義一個libs.jar文件壳坪,將sdk的engine平臺flutter.jar中l(wèi)ib目錄下的so文件(lib/**)復(fù)制到壓縮包libs.jar,當(dāng)debug模式掰烟,多復(fù)制x86和x64平臺的libflutter.so文件爽蝴。其他模式,復(fù)制android-arm-xxx(32位)目錄中的文件纫骑。
將intermediates/flutter/release/android-arm和64的so文件(app.so)蝎亚,release模式編譯過程,Dart產(chǎn)物包括so文件先馆,重命名libapp.so发框,拷貝到libs.jar壓縮包文件。
// 包含so產(chǎn)物的intermediates/flutter/平臺/煤墙,release和profile
compileTasks.each { compileTask ->
from(compileTask.intermediateDir) {
include '*.so'
rename { String filename ->
println "rename:"+compileTask.intermediateDir
return "lib/${compileTask.abi}/lib${filename}"
}
}
}
3梅惯,拷貝任務(wù)
Task copyFlutterAssetsTask = project.tasks.create(name:
"copyFlutterAssets${variant.name.capitalize()}", type: Copy) {
}
任務(wù)名:copyFlutterAssets構(gòu)建模式,類型是Copy類仿野,Gradle內(nèi)置任務(wù)類铣减,
copyFlutterAssetsXxx,依賴對應(yīng)編譯任務(wù)和packLibsflutterBuild任務(wù)
構(gòu)建類模式:Debug脚作,Profile葫哗,Release
abi平臺:依賴編譯任務(wù)生成的目標(biāo)平臺
依賴cleanMergeXxxAssets,mergeXxxAssets
# clean動作先執(zhí)行
variant.mergeAssets.mustRunAfter("clean${variant.mergeAssets.name.capitalize()}")
拷貝是從intermediates的flutter目錄到merged_assets目錄下鳖枕。
/build/intermediates/merged_assets/release/mergeReleaseAssets/out
拷貝內(nèi)容是flutter_assets文件夾目錄下/*魄梯。
addApiDependencies(project, variant.name, project.files {
packFlutterSnapshotsAndLibsTask
})
依賴packLibsflutterBuild任務(wù)桨螺。
## 運行拷貝任務(wù)
> Task :app:cleanMergeDebugAssets UP-TO-DATE
> Task :app:compileFlutterBuildDebugArm
> Task :app:compileFlutterBuildDebugArm64
> Task :app:mergeDebugShaders
> Task :app:compileDebugShaders
> Task :app:generateDebugAssets
> Task :app:packLibsflutterBuildDebug UP-TO-DATE
> Task :app:mergeDebugAssets
> Task :app:copyFlutterAssetsDebug
8 actionable tasks: 6 executed, 2 up-to-date
11:42:04: Task execution finished 'copyFlutterAssetsDebug'.
4宾符,構(gòu)建順序
Debug模式,Gradle順序灭翔。
四魏烫、Dart編譯命令
BaseFlutterTask基類的buildBundle()方法,調(diào)用Flutter構(gòu)建命令肝箱,生成Futter產(chǎn)物哄褒。
sourceDir目錄,即根目錄中煌张,包含lib/main.dart文件的目錄呐赡,添加任務(wù)時,構(gòu)建目錄默認是lib/main.dart骏融,通過project.exec {..}
方法链嘀,執(zhí)行命令萌狂。
void buildBundle() {
intermediateDir.mkdirs()
if (buildMode == "profile" || buildMode == "release") {
project.exec {
executable flutterExecutable.absolutePath
workingDir sourceDir
args "build", "aot"
args "--target", targetPath
args "--output-dir", "${intermediateDir}"
...//args參數(shù)
}
}
project.exec {
executable flutterExecutable.absolutePath
workingDir sourceDir
args "build", "bundle"
args "--target", targetPath
args "--target-platform", "${targetPlatform}"
...//args參數(shù)
args "--asset-dir", "${intermediateDir}/flutter_assets"
if (buildMode == "debug") {
args "--debug"
}
if (buildMode == "profile") {
args "--profile"
}
if (buildMode == "release") {
args "--release"
}
}
}
release和profile構(gòu)建模式,兩次命令怀泊,第一個project.exec茫藏。
flutter build aot --suppress-analytics --quiet --target lib/main.dart --target-platform android-arm --output-dir build/app/intermediates/flutter/release --release
輸出目錄是intermediates/flutter/release/平臺/,產(chǎn)物是app.so文件霹琼,不支持debug構(gòu)建模式务傲。
所有構(gòu)建模式,第二個project.exec枣申。
flutter build bundle --suppress-analytics --target lib/main.dart --precompiled --asset-dir build/app/intermediates/flutter/release/flutter_assets --release
build bundle售葡,產(chǎn)物是flutter_assets目錄。
任重而道遠