开发集成环境

[✓] Flutter (Channel unknown, v1.12.13+hotfix.8, on Mac OS X 10.14.6 18G103, locale zh-Hans-CN)

谈到目前跨平台框架的应用,无非两种,一种使用纯跨平台技术开发的项目,一种是与原生进行混编的项目,当然这里所讲的是后者,后者相对前者稍微复杂些,而且目前大多数都是在原有项目中逐步插入跨平台技术,当然一些新项目除外。

一、简述Flutter集成到Android原生项目

二、Android原生以AAR形式集成Flutter项目

三、Flutter与原生的消息通信

四、Flutter中如何使用原生控件/组件

五、Flutter升级及开发中遇到的问题汇总

其实在Flutter官网上Add Flutter to existing app 就提供了两种将Flutter引入的方式。

方式一:

以Android Archive (AAR)形式引入Flutter依赖。

方式二:

一种方式是将Flutter作为module,然后native主工程将其引入进来。

这种方式适合参与人数比较少的项目,如果有多人协作开发的大型项目就不合适了,因为其他人首先要配置Flutter开发环境,而且团队里面其他人还要配置module的依赖,都要熟悉flutter,成本相对较高点。

这里主要介绍方式一通过以Android Archive (AAR)形式引入Flutter依赖,步骤如下:

在.android目录下的build.gradle目录下添加依赖:

buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.0'
classpath "com.kezong:fat-aar:1.2.8" //新增这行
}
}
allprojects {
repositories {
google()
jcenter()
...
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}

在 .android/settings.gradle 文件中添加如下代码:

// Generated file. Do not edit.
include ':app'
rootProject.name = 'android_generated'
setBinding(new Binding([gradle: this]))
evaluate(new File(settingsDir, 'include_flutter.groovy'))
//新增以下部分
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists()) {
pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
}
plugins.each { name, path ->
def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
include ":$name"
project(":$name").projectDir = pluginDirectory
}

在 .android/Flutter/build.gradle 文件中添加如下代码:

dependencies {
testImplementation 'junit:junit:4.12'
//新增以下部分
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists()) {
pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
}
plugins.each { name, _ ->
println name
embed project(path: ":$name", configuration: 'default')
}
}
apply plugin: "com.kezong.fat-aar"
apply plugin: 'maven'
final def localMaven = true // true:发布到本地maven仓库, false: 发布到maven私服
final def artGroupId = "com.cc.flutter"
final def artVersion = "1.0.1"
final def artifactId = "test-flutter"
final def mavenUrl = "http://10.181.xx.xx:8083/repository/repo/"
final def mavenAccountName = "admin"
final def mavenAccountPwd = "admin123"
final def localRepo = "../../repo-local" //在根目录创建repo-local文件夹
uploadArchives {
repositories {
mavenDeployer {
println "==maven url: ${artGroupId}:${artifactId}:${artVersion}"
println "==localMaven : ${localMaven}:${localRepo}"
if(localMaven) {
repository(url: uri(localRepo))
} else {
repository(url: mavenUrl) {
authentication(userName: mavenAccountName, password: mavenAccountPwd)
}
}
pom.groupId = artGroupId
pom.artifactId = artifactId
pom.version = artVersion
pom.project {
licenses {
license {
name 'The Apache Software License, artVersion 2.0'
url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
}
}
}
}
}
}

在项目根目录下创建打包脚本aar.sh,内容如下:

#!/bin/bash
# 初始化记录项目pwd
projectDir=`pwd`
# step 1 clean
echo 'clean old build'
find . -depth -name "build" | xargs rm -rf
cd ${projectDir} # 回到项目
rm -rf .android/Flutter/build
#flutter clean
# step 2 package get
echo 'packages get'
cd ${projectDir} # 回到项目
flutter packages get
# step 3 build aar,生成aar,然后上传到对应maven仓库
echo 'build aar'
cd ${projectDir}
flutter build apk
if [ $? -eq 0 ]; then
echo '打包成aar 成功!'
else
echo '打包成aar 失败!'
exit 1
fi
cd ${projectDir}/.android
./gradlew flutter:uploadArchives
if [ $? -eq 0 ]; then
echo 'uploadArchives 成功!'
else
echo 'uploadArchives 失败!'
exit 1
fi
echo '<<<<<<<<<<<<<<<<<<<<<<<<<< 打包成功,aar上传成功 >>>>>>>>>>>>>>>>>>>>>>>>>'
echo "打包成功 : flutter-release.aar, 本地仓库:${projectDir}/repo-local"
exit

在根目录下打开命令行,执行打包脚本即可:

$ ./aar.sh

打包成功后可自动将打包的aar上传至对应的maven仓库,此处放在本地仓库根目录下的repo-local文件夹下。

将对应仓库中的aar文件引入原生项目中

在宿主项目根目录下的build文件中添加如下

allprojects {
repositories {
...
maven {
url 'http://download.flutter.io'
}
flatDir {
dirs 'libs'
}
maven { url "../repo-local" } //此处是本地仓库,如是远程私服换成对应远程地址即可
}
}

在app目录下的build.gradle 中添加远程依赖

implementation 'com.cc.flutter:test-flutter:1.0.1'

上述步骤即可对Flutter以AAR方式引入到原生Android中进行混合开发,后面会逐渐对打包流程进行优化,以下的优化迭代并不是最终方案(一步步来)。现在你可以进行创建一个demo然后集成到自己的项目中进行试手,体验以下Flutter。后期会逐步完善Dart语法相关笔记与Flutter相关笔记。

上述打包流程稍微有点繁琐,如果现有项目比较多,需要重复配置同样的信息,所以进行打包步骤优化通用配置:

在项目根目录下创建configs文件夹,里面分别创建dependencies_gradle_plugin.gradle 、 setting_gradle_plugin.gradle、uploadArchives.gradle 三个文件

dependencies_gradle_plugin.gradle 文件内容如下:

dependencies {
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists()) {
pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
}
plugins.each { name, _ ->
println name
embed project(path: ":$name", configuration: 'default')
}
}

setting_gradle_plugin.gradle文件内容如下:

def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists()) {
pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
}
plugins.each { name, path ->
def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
include ":$name"
project(":$name").projectDir = pluginDirectory
}

uploadArchives.gradle 文件内容如下:

apply plugin: 'maven'
final def localMaven = true //true: 发布到本地maven仓库, false: 发布到maven私服
final def artGroupId = "com.cc.flutter"
final def artVersion = "1.0.1"
final def artifactId = "test-flutter"
final def mavenUrl = "http://10.181.xx.xx:8083/repository/repo/"
final def mavenAccountName = "admin"
final def mavenAccountPwd = "admin123"
final def localRepo = "../../repo-local"
uploadArchives {
repositories {
mavenDeployer {
println "==maven url: ${artGroupId}:${artifactId}:${artVersion}"
println "==localMaven : ${localMaven}:${localRepo}"
if(localMaven) {
repository(url: uri(localRepo))
} else {
repository(url: mavenUrl) {
authentication(userName: mavenAccountName, password: mavenAccountPwd)
}
}
pom.groupId = artGroupId
pom.artifactId = artifactId
pom.version = artVersion
pom.project {
licenses {
license {
name 'The Apache Software License, artVersion 2.0'
url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
}
}
}
}
}
}

在.android目录下的build.gradle目录下添加依赖:

classpath "com.kezong:fat-aar:1.2.8" //新增这行
在.android/settings.gradle文件中添加如下代码:
apply from: "../configs/setting_gradle_plugin.gradle"

在.android/Flutter/build.gradle中添加如下代码:

apply from: "../../configs/uploadArchives.gradle"
...
//下面放在尾部
apply plugin: "com.kezong.fat-aar"
apply from: "../../configs/dependencies_gradle_plugin.gradle"

稍后的利用打包脚本执行打包上传相应仓库的步骤和引入到原生项目中的流程和上述一致。