With the booming development of mobile smart devices, a mobile multi-terminal development framework has become a general trend. Download the Flutter Analysis and Practice: Evolution and Innovation of Xianyu Technologies eBook for step-by-step analyses based on real-life problems, as well as clear explanations of the important concepts of Flutter.
1) If the Flutter project structure is directly used for daily development, native project developers also need to set up the Flutter environment and understand the Flutter technology, which increases costs.
2) Currently, Alibaba Group's building system does not support direct building of Flutter projects. This requires Xianyu to remove native project dependencies on Flutter.
From this perspective, Xianyu wants to design a module to extract Flutter dependencies as a Flutter dependency library and publish it to the remote repository for reference by native projects, as shown in Figure 1-16.
Figure 1-16
Based on Flutter project analysis, native projects depend on Flutter as follows:
Major Flutter dependency files are extracted from the app packages of Android and iOS, as shown in Figure 1-17.
Figure 1-17
1) Flutter dependency files for Android
icudtl.dat
, libflutter.so
, and some class files. They are all encapsulated in flutter.jar
, which is in flutter/bin/cache/artifacts/engine
in the Flutter library directory.isolate_snapshot_data
, isolate_snapshot_instr
, vm_snapshot_data
, vm_snapshot_instr
, and flutter_assets
.isolate_snapshot_data
(app data segments), isolate_snapshot_instr
(app instruction segments), vm_snapshot_data
(virtual machine data segments), and vm_snapshot_instr
(virtual machine instruction segments.)2) Flutter dependency files for iOS
The compilation results need to be extracted and packaged into a Software Development Kit (SDK) dependency for the native project, which removes native project dependencies on the Flutter project.
1) Analyze the Flutter compilation task on Android
Android packaging of the Flutter project is to insert a flutter.gradle
task to the Android Gradle task. The flutter.gradle
task (this file can be found in the flutter/packages/flutter_tools/gradle
directory in the Flutter library) implements the following operations:
flutter.jar
dependency.isolate_snapshot
files, two vm_snapshots
files, and the flutter_assets
folder. Copy the compiled project to mergeAssets.outputDir
and then save it to the assets directory of the Android Package Kit (APK.)2) Implement Flutter dependency extraction on Android
Perform the following steps:
(a) Compile a Flutter project.
This aims to compile Flutter's Dart code and resources by running the ahead-of-time (AOT) and Bundle commands.
echo "Clean old build"
find . -d -name "build" | xargs rm -rf
./flutter/bin/flutter clean
echo "Get packages"
./flutter/bin/flutter packages get
echo "Build release AOT"
./flutter/bin/flutter build aot --release --preview-dart-2 --output-dir= build/flutteroutput/aot
echo "Build release Bundle"
./flutter/bin/flutter build bundle --precompiled --preview-dart-2 --asset-dir=build/flutteroutput/flutter_assets
(b) Package flutter.jar
and the output of the Flutter project into an AAR file.
This aims to encapsulate flutter.jar
and the output compiled in step 1 into an AAR file.
Add the flutter.jar
dependency.
project.android.buildTypes.each {
addFlutterJarImplementationDependency(project, releaseFlutterJar)
}
project.android.buildTypes.whenObjectAdded {
addFlutterJarImplementationDependency(project, releaseFlutterJar)
}
private static void addFlutterJarImplementationDependency(Project project, releaseFlutterJar) {
project.dependencies {
String configuration
if (project.getConfigurations().findByName("api")) {
configuration = "api"
} else {
configuration = "compile"
}
add(configuration, project.files {
releaseFlutterJar
})
}
}
Merge the output of the Flutter project into assets.
// 合并 flutter assets
def allertAsset ="${project.projectDir.getAbsolutePath()}/flutter/assets/ release"
Task mergeFlutterAssets = project.tasks.create(name: "mergeFlutterAssets${variant.name.capitalize()}", type: Copy) {
dependsOn mergeFlutterMD5Assets
from (allertAsset){
include "flutter_assets/**"
include "vm_snapshot_data"
include "vm_snapshot_instr"
include "isolate_snapshot_data"
include "isolate_snapshot_instr"
}
into variant.mergeAssets.outputDir
}
variant.outputs[0].processResources.dependsOn(mergeFlutterAssets)
(c) Publish the output AAR file and the AAR file compiled by Flutter plug-ins to the Maven repository.
Publish the AAR file of the Flutter project output.
echo 'Clean packflutter input(flutter build)'
rm -f -r android/packflutter/flutter/
# 拷贝flutter.jar
echo 'Copy flutter jar'
mkdir -p android/packflutter/flutter/flutter/android-arm-release && cp flutter/bin/cache/artifacts/engine/android-arm-release/flutter.jar "$_"
# 拷贝asset
echo 'Copy flutter asset'
mkdir -p android/packflutter/flutter/assets/release && cp -r build/ flutteroutput/aot/* "$_"
mkdir -p android/packflutter/flutter/assets/release/flutter_assets && cp -r build/flutteroutput/flutter_assets/* "$_"
# 将Flutter库和flutter_app打成AAR文件,同时发布到Ali-maven
echo 'Build and publish idlefish flutter to aar'
cd android
if [ -n "$1" ]
then
./gradlew :packflutter:clean :packflutter:publish -PAAR_VERSION=$1
else
./gradlew :packflutter:clean :packflutter:publish
fi
cd ../
Publish the AAR file of Flutter plug-ins.
# 将Plugin发布到Ali-maven
echo "Start publish flutter-plugins"
for line in $(cat .flutter-plugins)
do
plugin_name=${line%%=*}
echo 'Build and publish plugin:' ${plugin_name}
cd android
if [ -n "$1" ]
then
./gradlew :${plugin_name}:clean :${plugin_name}:publish -PAAR_VERSION =$1
else
./gradlew :${plugin_name}:clean :${plugin_name}:publish
fi
cd ../
done
(d) Native projects only need to depend on the AAR files published to the Maven repository.
During the development, the latest AAR files are required in real time. Therefore, the snapshot version is used.
configurations.all {
resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
}
ext {
flutter_aar_version = '6.0.2-SNAPSHOT'
}
dependencies {
//Flutter主工程依赖:包含基于Flutter开发的功能、Flutter引擎lib
compile("com.taobao.fleamarket:IdleFishFlutter:${getFlutterAarVersion(project)}") {
changing = true
}
//其他依赖
}
static def getFlutterAarVersion(project) {
def resultVersion = project.flutter_aar_version
if (project.hasProperty('FLUTTER_AAR_VERSION')) {
resultVersion = project.FLUTTER_AAR_VERSION
}
return resultVersion
}
Run the flutter build ios command. The Flutter compilation script xcode_backend.sh
is finally run to:
Obtain various parameters, such as project_path
, target_path
, and build_mode
, which are defined in Generated.xcconfig
.
Delete the App.framework
and app.flx
files from the Flutter directory.
Compare Flutter/Flutter.framework
with Flutter.framework
in the FLUTTER_ROOT/bin/cache/artifacts/engine {artifact_variant}
directory. If they are different, use Flutter.framework
in the directory to overwrite the former.
Obtain the parameters for generating App.framework
, including build_dir
, local_engine_flag
, preview_dart_2_flag
, and aot_flags
.
Generate the App.framework
file and replicate it and the AppFrameworkInfo.plist
file to the Flutter directory of the Xcode project.
Compile the Flutter project to generate the App.framework
file.
echo "===清理flutter历史编译==="
./flutter/bin/flutter clean
echo "===重新生成plugin索引==="
./flutter/bin/flutter packages get
echo "===生成App.framework和flutter_assets==="
./flutter/bin/flutter build ios --release
Package all plug-ins as static libraries: Package the plug-ins into a binary library file, and then package the registration portals of the plug-ins into a binary library file.
echo "===生成各个插件的二进制库文件==="
cd ios/Pods
#/usr/bin/env xcrun xcodebuild clean
#/usr/bin/env xcrun xcodebuild build -configuration Release ARCHS='arm64 armv7' BUILD_AOT_ONLY=YES VERBOSE_SCRIPT_LOGGING=YES -workspace Runner.xcworkspace -scheme Runner BUILD_DIR=../build/ios -sdk iphoneos
for plugin_name in ${plugin_arr}
do
echo "生成lib${plugin_name}.a..."
/usr/bin/env xcrun xcodebuild build -configuration Release ARCHS='arm64 armv7' -target ${plugin_name} BUILD_DIR=../../build/ios -sdk iphoneos -quiet
/usr/bin/env xcrun xcodebuild build -configuration Debug ARCHS='x86_64' -target ${plugin_name} BUILD_DIR=../../build/ios -sdk iphonesimulator -quiet
echo "合并lib${plugin_name}.a..."
lipo -create "../../build/ios/Debug-iphonesimulator/${plugin_name}/lib${plugin_name}.a" "../../build/ios/Release-iphoneos/${plugin_name}/lib${plugin_name}.a" -o "../../build/ios/Release-iphoneos/${plugin_name}/lib${plugin_name}.a"
done
echo "===生成注册入口的二进制库文件==="
for reg_enter_name in "flutter_plugin_entrance" "flutter_service_register"
do
echo "生成lib${reg_enter_name}.a..."
/usr/bin/env xcrun xcodebuild build -configuration Release ARCHS='arm64 armv7' -target ${reg_enter_name} BUILD_DIR=../../build/ios -sdk iphoneos
/usr/bin/env xcrun xcodebuild build -configuration Debug ARCHS='x86_64' -target ${reg_enter_name} BUILD_DIR=../../build/ios -sdk iphonesimulator
echo "合并lib${reg_enter_name}.a..."
lipo -create "../../build/ios/Debug-iphonesimulator/${reg_enter_name}/lib${reg_enter_name}.a" "../../build/ios/Release-iphoneos/${reg_enter_name}/lib${reg_enter_name}.a" -o "../../build/ios/Release-iphoneos/${reg_enter_name}/lib${reg_enter_name}.a"
done
Upload these files to the remote repository and generate new tags. Update pod dependencies for native projects.
The following problems still exist in daily development:
Therefore, Xianyu has introduced the automatic framework of CI to solve these problems. It reduces the labor cost and manual errors through automation. In addition, it implements auto versioning.
First, before a native project is built each time, the remote library of the Flutter project is automatically compiled and released, without any manual intervention throughout the process. Second, during development and testing, five-digit version numbers in A.B.C.D.X format are used, with the last digit incremented automatically. This ensures that all versions of the Flutter library developed in parallel do not conflict with each other. Finally, in the publishing phase, three-digit (A.B.C) or four-digit (A.B.C.D) version numbers are used to match the app version number, which facilitates tracing of subsequent issues.
Figure 1-18 shows the entire process.
Figure 1-18
Flutter Analysis and Practice: Hybrid Project Transformation
Flutter Analysis and Practice: Quick Building of Hybrid Projects
56 posts | 4 followers
FollowXianYu Tech - September 2, 2020
XianYu Tech - September 2, 2020
XianYu Tech - September 2, 2020
XianYu Tech - September 3, 2020
XianYu Tech - September 7, 2020
XianYu Tech - September 11, 2020
56 posts | 4 followers
FollowHelp enterprises build high-quality, stable mobile apps
Learn MoreAn enterprise-level continuous delivery tool.
Learn MoreProvides comprehensive quality assurance for the release of your apps.
Learn MoreAlibaba Cloud (in partnership with Whale Cloud) helps telcos build an all-in-one telecommunication and digital lifestyle platform based on DingTalk.
Learn MoreMore Posts by XianYu Tech