一、工程目錄
AndroidStudio創(chuàng)建一個Flutter項目,F(xiàn)lutter工程的目錄結(jié)構(gòu)和普通Android工程是不同的,它是Google的跨平臺UI框架,包含android和ios目錄。


android目錄,android子工程,和普通android工程類似,包含app目錄,gradle目錄和gradle配置。
ios目錄,ios子工程。
lib目錄,dart源文件。
pubspec.yaml文件,F(xiàn)lutter配置文件,添加dart包packages依賴和包名。

二、android工程
1,頂級構(gòu)建settings.gradle文件,包含構(gòu)建模塊,app主模塊,動態(tài)include插件模塊。
include ':app'
//android工程目錄的父目錄,即example目錄
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
//讀取flutter工程根目錄下.flutter-plugin文件
def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists()) {
pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
}
//遍歷.flutter-plugin中每項插件,include引入每項插件模塊
plugins.each { name, path ->
def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
include ":$name"
project(":$name").projectDir = pluginDirectory
}
普通Flutter工程(非Flutter插件工程),不存在.flutter-plugins文件,可以只關注include :app引入,忽略settings.gradle文件其他內(nèi)容。
2,頂級構(gòu)建build.gradle文件,和普通android工程頂層build.gradle基本一致,配置倉儲庫位置。
####不同之處
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
rootProject是android工程目錄,設置build目錄是當前的父目錄,即Flutter工程目錄,因此,android工程的build產(chǎn)物在Flutter工程build目錄下。

android子模塊,每一個subprojects,子模塊build的輸出目錄,在Flutter工程的build目錄中,創(chuàng)建子模塊name的輸出目錄,例如,app主模塊。
如果新建mylibrary模塊,將輸出mylibrary的build目錄。

3,模塊級構(gòu)建build.gradle文件,app主模塊。
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
讀取android目錄,local.properties文件,該文件包括android sdk路徑,flutter sdk路徑,flutter版本,如果未配置flutter sdk路徑,拋出Flutter SDK not found異常。
普通工程local.properties文件只包含android sdk路徑。
apply plugin,app主模塊是一個application。
apply from,引入flutter.sdk路徑下的gradle文件flutter.gradle,flutterRoot是flutter sdk路徑。
先執(zhí)行flutter.gradle內(nèi)容,加入一些打包時的Flutter任務插件。
# local.properties文件
sdk.dir=/Users/xxx/Library/Android/sdk,//android sdk路徑
flutter.sdk=/Users/xxx/Documents/flutter,//flutter sdk路徑
flutter.buildMode=debug
flutter.versionName=1.0.0
flutter.versionCode=1
三、插件工程
AndroidStudio創(chuàng)建一個Flutter插件工程。

插件工程提供了dart訪問原生系統(tǒng)的功能,包括dart接口和原生api,dart接口在lib目錄,定義一個_channel.invokeMethod(),訪問原生方法。
原生api在android目錄,定義一個實現(xiàn)MethodCallHandler接口類。
example目錄,是一個完整的Flutter工程,測試插件。
測試插件的Flutter工程exmple目錄android子工程,頂層構(gòu)建settings.gradle文件,和普通Futter工程android目錄的構(gòu)建文件相同。
include ':app'
//android工程根目錄的父目錄,即flutter工程根目錄
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
//讀取flutter工程根目錄下.flutter-plugin文件
def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists()) {
pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
}
//遍歷.flutter-plugin中每項插件,include引入每項插件模塊
plugins.each { name, path ->
def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
include ":$name"
project(":$name").projectDir = pluginDirectory
}
flutterProjectRoot目錄,android目錄的父目錄,即example目錄,查找.flutter-plugins文件,保存插件name和路徑,include對應name模塊,每一個模塊,代表一個android插件原生api。

.flutter-plugins文件內(nèi)容,key是插件name,value是路徑。
在插件工程,example測試目錄下的android主模塊,引入example外層插件工程目錄android插件模塊,(和example平級)。
example目錄下lib的dart代碼,調(diào)用插件dart接口,(lib和example平級),提供的方法,獲取原生功能。
任重而道遠