打包步骤
1、Google推荐的打包AAR方式:将flutter module打包成aar
官方文档:
中文 flutter.cn/docs/development/add-to-app/android/project-setup
英文 docs.flutter.dev/add-to-app/android/project-setup
2、fat-aar打包Flutter工程(开源的Android打包AAR插件)
2.1 修改settings.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
}
2.2 修改.android/build.gradle文件
引入依赖:com.github.kezong:fat-aar:1.3.6
buildscript {
ext.kotlin_version = '1.7.10'
repositories {
mavenCentral()
maven { url 'https://maven.aliyun.com/nexus/content/groups/public'}
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://maven.aliyun.com/repository/jcenter' }
}
dependencies {
classpath 'com.android.tools.build:gradle:7.1.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// 增加此配置
classpath "com.github.kezong:fat-aar:1.3.6"
}
}
allprojects {
repositories {
mavenCentral()
maven { url 'https://maven.aliyun.com/nexus/content/groups/public' }
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://maven.aliyun.com/repository/jcenter' }
}
}
ext {
minSdkVersion = 21
targetSdkVersion = 28
compileSdkVersion = 31
buildToolsVersion = '28.0.3'
multidexVersion = '2.0.1'
timberVersion = '4.7.0'
rxjavaVersion = '2.2.16'
rxandroidVersion = '2.1.1'
zxingEmbeddedVersion = '3.5.0'
gsonVersion = '2.8.5'
okhttpVersion = '3.12.0'
ossVersion = '2.9.3'
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}
2.3 修改 .android/app/build.gradle
//新增: 是否作为依赖
def isAarLibrary = true
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 FileNotFoundException("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'
}
//新增:当需要打包aar时,修改项目为library模式
if (isAarLibrary) {
apply plugin: 'com.android.library'
} else {
apply plugin: 'com.android.application'
}
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
//新增:引入fat-aar
if (isAarLibrary) {
apply plugin: 'com.kezong.fat-aar'
}
static def buildTime() {
return new Date().format("yyyyMMdd_HHmmss", TimeZone.getDefault());
}
android {
compileSdkVersion 33
ndkVersion flutter.ndkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
//新增:需要打包aar时候,不能有applicationId
if (!isAarLibrary){
applicationId "com.xx.xx.xx"
}
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
minSdkVersion flutter.minSdkVersion
targetSdkVersion flutter.targetSdkVersion
versionCode 9
versionName '1.0.18'
multiDexEnabled true
// 设置支持的SO库框架
if (isAarLibrary) {
ndk {
abiFilters 'armeabi', 'x86'
}
}
}
signingConfigs {
release_store {
storeFile file('../**.keystore')
storePassword '**'
keyAlias '**'
keyPassword '**'
v1SigningEnabled true
v2SigningEnabled true
}
}
buildTypes {
debug {
signingConfig signingConfigs.release_store
}
profile {
signingConfig signingConfigs.release_store
}
release {
// shrinkResources true
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release_store
}
}
}
flutter {
source '../..'
}
dependencies {
//添加fat-aar处理flutter打包成aar中三方依赖
if (isAarLibrary) {
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 ->
println name
embed project(path: ":$name", configuration: 'default')
}
}
}
2.4修改AndroidManifest.xml文件
项目作为子项目寄存于原生app中,不需要icon、label等属性,项目作为子项目寄存于原生app中,入口acitvity不需要配置LAUNCHER,不然应用集成到宿主app中,启动会在桌面上生成两个应用图标固删除以下内容:
2.5 最后在pubspec.yaml执行Packages get获取第三方包,再执行flutter clean,并通过Terminal命令进入到android目录下 cd android 并执行./gradlew assembleRelease,打包成aar 与 libapp.so(注:flutter更新功能后,libapp.so文件也需要实时更新至引入aar的项目中)
所在目录:
踩坑之旅
1、Flutter项目中引入插件后,打包过程中出现
原因:进到本地磁盘发现出现问题的库没有android目录。
很多web,linux,macos专用的flutter包,这些包内部并没有android文件夹,所以,打aar包的时候不识别它们。
解决方案:打包时过滤
dependencies {
//添加fat-aar处理flutter打包成aar中三方依赖
if (isAarLibrary) {
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 ->
println name
if (name.toString() != “platform_device_id_web”) {
embed project(path: ":$name", configuration: 'default')
}
}
}
}
2、Caused by: groovy.lang.MissingPropertyException: Could not get unknown property 'applicationVariants' for extension 'android' of type com.android.build.gradle.LibraryExtension.
解决方案:将错误指向的地方的applicationVariants改为libraryVariants
3、Resource shrinker cannot be used for libraries.
解决方案:
将shrinkResources改为false。
Android项目引入Flutter项目打包生成的aar文件
1、将生成的aar包拷贝到原生项目libs目录下,如下图:
2、在app/build.gradle文件里进行依赖,如下图:
注:implementation 'io.flutter:flutter_embedding_release:1.0.0-d1b9a6*********'中1.0.0-后面的版本号源于
2.1 采取Google推荐方式将flutter module打包成aar后,此版本号来源于 flutter_release-1.0.pom 文件如下图:
2.2 采用fat-aar方式将Flutter工程打包aar方式,此版本号来源于:
3、配置maven库
修改settings.gradle
pluginManagement {
// 新增
String storageUrl = System.env.FLUTTER_STORAGE_BASE_URL ?: "https://storage.googleapis.com"
repositories {
gradlePluginPortal()
// google()
mavenCentral()
maven { url 'https://maven.aliyun.com/nexus/content/groups/public' }
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://maven.aliyun.com/repository/jcenter' }
// 新增
maven {
url "$storageUrl/download.flutter.io"
}
flatDir {
dirs 'libs'
}
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
// 新增
String storageUrl = System.env.FLUTTER_STORAGE_BASE_URL ?: "https://storage.googleapis.com"
repositories {
mavenCentral()
maven { url 'https://maven.aliyun.com/nexus/content/groups/public' }
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://maven.aliyun.com/repository/jcenter' }
// 新增
maven {
url "$storageUrl/download.flutter.io"
}
}
}
rootProject.name = "FlutterAarTest"
include ':app'
4、再将Flutter项目打包出来apk,将打包好的.apk文件后缀改为.zip,解压后拿到arm64_v7a、arm64-v8a、x86_64文件下so库,如下图:
5、将libflutter.so与libapp.so库拷贝到原生项目的jniLibs文件夹下,如图所示:
5、在app/build.gradle中添加如下配置:
defaultConfig {
ndk { abiFilters "arm64-v8a", "armeabi-v7a","x86_64" }
}
5 修改AndroidManifest.xml
<activity
android:name="io.flutter.embedding.android.FlutterActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:exported="true"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize"
tools:ignore="MissingClass" />
6、跳转flutter页面
FlutterActivity.withNewEngine()
.backgroundMode(FlutterActivityLaunchConfigs.BackgroundMode.transparent)
//.initialRoute("/autoShopListLoginView")
.build(this)