Flutter混编-Android集成

Flutter混编-Android集成

    • 创建Flutter module
    • 集成module到Android项目
      • 方案A-源码集成
      • 方案B-产物集成

Flutter可以集成到现有的Android应用中,可通过源码或者aar两种方式。

创建Flutter module

  1. 使用Android Studio
    Flutter混编-Android集成_第1张图片
  2. 使用命令行

command line 运行:

cd some/path/
flutter create --template module my_flutter

集成module到Android项目

方案A-源码集成

此方案要求在你的项目上工作的每个开发人员都必须在本地安装了Flutter SDK。源码集成方式比较简单,实现以下两步即可:

  1. 把Flutter module 当作子项目在settings.gradle配置:
//settings.gradle
setBinding(new Binding([gradle: this]))                                // new
evaluate(new File(                                                     // new
        settingsDir.parentFile,                                              // new
        'my_module/.android/include_flutter.groovy'                         // new
))
  1. 通过implementation添加Flutter module依赖
//app/build.gradle
dependencies {
    implementation project(':flutter')
}

方案B-产物集成

产物集成方案通过 flutter build aar ,再通过fat-aar方案把项目aar、flutter基础包aar、第三方插件aar整合到一个aar发布到远程仓库,现有android项目最后通过implementation引用即可,无需安装flutter环境

implementation 'com.study.test:myflutter:1.0.0@aar'

网上有大神专门写了个实用的shell脚本,执行就可以完成远程仓库发布,脚本目录结构配置如下:
Flutter混编-Android集成_第2张图片

  1. 在configs/gradle.properties中 配置远程仓库信息
org.gradle.jvmargs=-Xmx1536M
# 远程maven url和账号
MAVEN_URL=私仓路径
MAVEN_ACCOUNT_NAME=admin
MAVEN_ACCOUNT_PWD=admin

#0=>maven 1=>source
FLUTTER_SOURCE=0
#0=>clound 1=>local
CLOUND_MAVEN=0

GROUP=com.study.test
VERSION_NAME=1.0.0
ARTIFACT_ID=myflutter
  1. 执行 ./flutter.sh
#!/bin/bash
# This is flutter build

# 初始化记录项目pwd
projectDir=`pwd`

# 假如没有引用三方的flutter Plugin 设置false 即可 *************************
isPlugin=true

# 版本号 + 1
cd ${projectDir}
v=`grep VERSION_NAME configs/gradle.properties|cut -d'=' -f2`
echo 旧版本号$v
v1=`echo | awk '{split("'$v'",array,"."); print array[1]}'`
v2=`echo | awk '{split("'$v'",array,"."); print array[2]}'`
v3=`echo | awk '{split("'$v'",array,"."); print array[3]}'`
y=`expr $v3 + 1`

vv=$v1"."$v2"."$y
echo 新版本号$vv
# 更新配置文件
sed -i '' 's/VERSION_NAME='$v'/VERSION_NAME='$vv'/g' configs/gradle.properties
if [ $? -eq 0 ]; then
    echo ''
else
    echo '更新版本号失败...'
    exit
fi#!/bin/bash
# This is flutter build

# 初始化记录项目pwd
projectDir=`pwd`

# 假如没有引用三方的flutter Plugin 设置false 即可 *************************
isPlugin=true

# 版本号 + 1
cd ${projectDir}
v=`grep VERSION_NAME configs/gradle.properties|cut -d'=' -f2`
echo 旧版本号$v
v1=`echo | awk '{split("'$v'",array,"."); print array[1]}'`
v2=`echo | awk '{split("'$v'",array,"."); print array[2]}'`
v3=`echo | awk '{split("'$v'",array,"."); print array[3]}'`
y=`expr $v3 + 1`

vv=$v1"."$v2"."$y
echo 新版本号$vv
# 更新配置文件
sed -i '' 's/VERSION_NAME='$v'/VERSION_NAME='$vv'/g' configs/gradle.properties
if [ $? -eq 0 ]; then
    echo ''
else
    echo '更新版本号失败...'
    exit
fi

# 删除 fat-aar 引用
function delFatAarConfig() {
    if [  ${isPlugin} == false  ]; then
        echo '删除 fat-aar 引用........未配置三方插件'
    else :
        cd ${projectDir} # 回到项目
        echo '删除 fat-aar 引用 ... '
        sed -i '' '$d
            ' .android/settings.gradle
        sed -i '' '$d
            ' .android/Flutter/build.gradle
        sed -i '' '$d
            ' .android/Flutter/build.gradle
        sed -i '' '11 d
            ' .android/build.gradle
    fi
}

# 引入fat-aar
function addFatAArConfig() {
     if [  ${isPlugin} == false  ]; then
        echo '引入fat-aar 配置........未配置三方插件'
     else :
        cd ${projectDir} # 回到项目

        cp configs/setting_gradle_plugin.gradle .android/config/setting_gradle_plugin.gradle

        if [ `grep -c 'setting_gradle_plugin.gradle' .android/settings.gradle` -eq '1' ]; then
            echo ".android/settings.gradle 中 已存在 !!!"
        else
            echo ".android/settings.gradle 中 不存在,去编辑"
            sed -i '' '$a\
            apply from: "./config/setting_gradle_plugin.gradle"
            ' .android/settings.gradle
        fi

        if [ $? -eq 0 ]; then
            echo '.android/settings.gradle 中 脚本插入 fat-aar 成功 !!!'
        else
            echo '.android/settings.gradle 中 脚本插入 fat-aar 出错 !!!'
            exit 1
        fi

        if [ `grep -c 'com.kezong:fat-aar' .android/build.gradle` -eq '1' ]; then
            echo "com.kezong:fat-aar:1.2.16 已存在 !!!"
        else
            echo "com.kezong:fat-aar:1.2.16 不存在,去添加"
            sed -i '' '10 a\
            classpath "com.kezong:fat-aar:1.2.16"
            ' .android/build.gradle
        fi

        # flutter/build.gradle 中添加fat-aar 依赖 和 dependencies_gradle_plugin
        if [ `grep -c "com.kezong.fat-aar" .android/Flutter/build.gradle` -eq '1' ]; then
            echo "Flutter/build.gradle 中 com.kezong:fat-aar 已存在 !!!"
        else
            echo "Flutter/build.gradle 中 com.kezong:fat-aar 不存在,去添加"
            sed -i '' '$a\
            apply plugin: "com.kezong.fat-aar"
            ' .android/Flutter/build.gradle
        fi

        cp configs/dependencies_gradle_plugin.gradle .android/config/dependencies_gradle_plugin.gradle
        if [ `grep -c 'dependencies_gradle_plugin' .android/Flutter/build.gradle` -eq '1' ]; then
            echo "Flutter/build.gradle 中 dependencies_gradle_plugin.gradle 已存在 !!!"
        else
            echo "Flutter/build.gradle 中 dependencies_gradle_plugin.gradle 不存在,去添加"
            sed -i '' '$a\
            apply from: "../config/dependencies_gradle_plugin.gradle"
            ' .android/Flutter/build.gradle
        fi
      fi
}


# step1 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

# step3 脚本补充:因为.android是自动编译的,所以内部的配置文件和脚本不可控,所以需要将configs内的脚本自动复制到 .android 内部
echo 'copy configs/uploadArchives.gradle to .android/config/... ,    copy configs/gradle.properties to Flutter/gradle.properties'
if [  -d '.android/config/' ]; then
   echo '.android/config 文件夹已存在'
else :
   mkdir .android/config
fi

if [  -f ".android/config/uploadArchives.gradle" ];then
    echo '.android/config/uploadArchives.gradle 已存在'
else :
    cp configs/uploadArchives.gradle .android/config/uploadArchives.gradle
fi

cp configs/gradle.properties .android/Flutter/gradle.properties

# step 4  脚本补充:同时在Flutter 的gradle中插入引用  apply from: "../uploadArchives.gradle"
echo '在Flutter 的gradle中插入引用  apply from: "../uploadArchives.gradle"'
if [ `grep -c 'uploadArchives.gradle' .android/Flutter/build.gradle` -eq '1' ]; then
    echo "Found!"
else
    echo "not found , 去修改"
    sed -i '' '2i\
    apply from: "../config/uploadArchives.gradle"' .android/Flutter/build.gradle
fi

# setp 5 脚本补充:引入fat-aar 相关脚本
# 在 settings.gradle 中 插入 , 注意 sed 命令换行 在mac下 是 \'$'\n

addFatAArConfig

# step 6 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
#gradle clean flutter:assembleRelease uploadArchives --info

if [ $? -eq 0 ]; then
    echo 'uploadArchives 成功!!!'
else
    echo 'uploadArchives 出错 !!!'
    delFatAarConfig
    exit 1
fi

# step 7 remove unused files
echo 'remove assets/lib'
cd ${projectDir}/.android/Flutter/src/main/
rm -rf assets
rm -rf lib
delFatAarConfig

echo '<<<<<<<<<<<<<<<<<<<<<<<<<< 结束 >>>>>>>>>>>>>>>>>>>>>>>>>'
echo '打包成功 : flutter-release-'${vv}'.aar...................! '
exit

# 删除 fat-aar 引用
function delFatAarConfig() {
    if [  ${isPlugin} == false  ]; then
        echo '删除 fat-aar 引用........未配置三方插件'
    else :
        cd ${projectDir} # 回到项目
        echo '删除 fat-aar 引用 ... '
        sed -i '' '$d
            ' .android/settings.gradle
        sed -i '' '$d
            ' .android/Flutter/build.gradle
        sed -i '' '$d
            ' .android/Flutter/build.gradle
        sed -i '' '11 d
            ' .android/build.gradle
    fi
}

# 引入fat-aar
function addFatAArConfig() {
     if [  ${isPlugin} == false  ]; then
        echo '引入fat-aar 配置........未配置三方插件'
     else :
        cd ${projectDir} # 回到项目

        cp configs/setting_gradle_plugin.gradle .android/config/setting_gradle_plugin.gradle

        if [ `grep -c 'setting_gradle_plugin.gradle' .android/settings.gradle` -eq '1' ]; then
            echo ".android/settings.gradle 中 已存在 !!!"
        else
            echo ".android/settings.gradle 中 不存在,去编辑"
            sed -i '' '$a\
            apply from: "./config/setting_gradle_plugin.gradle"
            ' .android/settings.gradle
        fi

        if [ $? -eq 0 ]; then
            echo '.android/settings.gradle 中 脚本插入 fat-aar 成功 !!!'
        else
            echo '.android/settings.gradle 中 脚本插入 fat-aar 出错 !!!'
            exit 1
        fi

        if [ `grep -c 'com.kezong:fat-aar' .android/build.gradle` -eq '1' ]; then
            echo "com.kezong:fat-aar:1.2.16 已存在 !!!"
        else
            echo "com.kezong:fat-aar:1.2.16 不存在,去添加"
            sed -i '' '10 a\
            classpath "com.kezong:fat-aar:1.2.16"
            ' .android/build.gradle
        fi

        # flutter/build.gradle 中添加fat-aar 依赖 和 dependencies_gradle_plugin
        if [ `grep -c "com.kezong.fat-aar" .android/Flutter/build.gradle` -eq '1' ]; then
            echo "Flutter/build.gradle 中 com.kezong:fat-aar 已存在 !!!"
        else
            echo "Flutter/build.gradle 中 com.kezong:fat-aar 不存在,去添加"
            sed -i '' '$a\
            apply plugin: "com.kezong.fat-aar"
            ' .android/Flutter/build.gradle
        fi

        cp configs/dependencies_gradle_plugin.gradle .android/config/dependencies_gradle_plugin.gradle
        if [ `grep -c 'dependencies_gradle_plugin' .android/Flutter/build.gradle` -eq '1' ]; then
            echo "Flutter/build.gradle 中 dependencies_gradle_plugin.gradle 已存在 !!!"
        else
            echo "Flutter/build.gradle 中 dependencies_gradle_plugin.gradle 不存在,去添加"
            sed -i '' '$a\
            apply from: "../config/dependencies_gradle_plugin.gradle"
            ' .android/Flutter/build.gradle
        fi
      fi
}


# step1 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

# step3 脚本补充:因为.android是自动编译的,所以内部的配置文件和脚本不可控,所以需要将configs内的脚本自动复制到 .android 内部
echo 'copy configs/uploadArchives.gradle to .android/config/... ,    copy configs/gradle.properties to Flutter/gradle.properties'
if [  -d '.android/config/' ]; then
   echo '.android/config 文件夹已存在'
else :
   mkdir .android/config
fi

if [  -f ".android/config/uploadArchives.gradle" ];then
    echo '.android/config/uploadArchives.gradle 已存在'
else :
    cp configs/uploadArchives.gradle .android/config/uploadArchives.gradle
fi

cp configs/gradle.properties .android/Flutter/gradle.properties

# step 4  脚本补充:同时在Flutter 的gradle中插入引用  apply from: "../uploadArchives.gradle"
echo '在Flutter 的gradle中插入引用  apply from: "../uploadArchives.gradle"'
if [ `grep -c 'uploadArchives.gradle' .android/Flutter/build.gradle` -eq '1' ]; then
    echo "Found!"
else
    echo "not found , 去修改"
    sed -i '' '2i\
    apply from: "../config/uploadArchives.gradle"' .android/Flutter/build.gradle
fi

# setp 5 脚本补充:引入fat-aar 相关脚本
# 在 settings.gradle 中 插入 , 注意 sed 命令换行 在mac下 是 \'$'\n

addFatAArConfig

# step 6 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
#gradle clean flutter:assembleRelease uploadArchives --info

if [ $? -eq 0 ]; then
    echo 'uploadArchives 成功!!!'
else
    echo 'uploadArchives 出错 !!!'
    delFatAarConfig
    exit 1
fi

# step 7 remove unused files
echo 'remove assets/lib'
cd ${projectDir}/.android/Flutter/src/main/
rm -rf assets
rm -rf lib
delFatAarConfig

echo '<<<<<<<<<<<<<<<<<<<<<<<<<< 结束 >>>>>>>>>>>>>>>>>>>>>>>>>'
echo '打包成功 : flutter-release-'${vv}'.aar...................! '
exit


  1. 其他configs下的文件内容如下:
//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
        if (!(name.endsWith('web') || name.endsWith('macos') || name.endsWith('linux'))) {
            println name
            embed project(path: ":$name", configuration: 'default')
        }
    }
    embed "io.flutter:flutter_embedding_release:1.0.0-d1bc06f032f9d6c148ea6b96b48261d6f545004f"
    embed "io.flutter:armeabi_v7a_release:1.0.0-d1bc06f032f9d6c148ea6b96b48261d6f545004f"
    embed "io.flutter:arm64_v8a_release:1.0.0-d1bc06f032f9d6c148ea6b96b48261d6f545004f"
}
//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'

// 这里不需要artifacts,uploadArchives命令会自动生成并上传./build/outputs/flutter-release.aar,不然出现下面错误
// A POM cannot have multiple artifacts with the same type and classifier
//artifacts {
//    archives file('./build/outputs/flutter-release.aar')
//}

final def localMaven = "1".equals(CLOUND_MAVEN) //true: 发布到本地maven仓库, false: 发布到maven私服

final def artGroupId = GROUP
final def artVersion = VERSION_NAME
final def artifactId = ARTIFACT_ID

uploadArchives {
    repositories {
        mavenDeployer {
            println "==maven url: ${artGroupId}:${artifactId}:${artVersion}"

            if (localMaven) {
                repository(url: uri(project.rootProject.projectDir.absolutePath + '/repo-local'))
            } else {
                repository(url: MAVEN_URL) {
                    authentication(userName: MAVEN_ACCOUNT_NAME, password: MAVEN_ACCOUNT_PWD)
                }
            }

            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,Flutter)