基于Jekins+GitLab的混合工程实现Flutter自动化打包方案

简介

Android项目想要依赖Flutter工程,存在两种依赖方式:1、直接采用项目工程依赖(需要组内成员配置flutter环境)2、通过aar工程产物的方式依赖,对原生侵入较小,组内其他成员无感知。

因此这里采用了方案二。

注意由于Flutter 1.22.x后,flutter版本有了较大的变化,其中flutter engine从flutter通过打包命令生成的aar剥离,因此直接依赖aar的方式并不能达到要求。

这是Android项目对Flutter项目的依赖主要分为三部分:flutter-release.aar,flutter engine,第三方plugins。

这里又有了两种处理方式:

  • 我们可以在项目的build.gradle中,将所有的依赖写上,但这显然会让项目的build.gradle 文件变得混乱。
  • 使用fat-aar的方式将所有的依赖装在到flutter-release.aar中,简化项目结构。

这里,采用方案二。

至此,大体的打包过程我们已经知悉,接下来,我们可以通过命令行,和修改配置文件的方式,手动打包成功。

将aar迁移到Android项目中,就可以正常运行了。

但是,作为一个成熟的项目,这样的人工打包方案自然是不能长久,因此gitlab+jekins的自动打包流程就需要建立起来了。

 

自动打包需求

1、在jekins界面可以一键完成flutter自动打包,Android依赖包更新。

2、支持flutter开发分支和master分支切换,来满足开发和发布的需求变更。

3、Android可以支持露出flutter的git commit id,来确认flutter的代码是否是最新代码。

自动化打包方案

方案一:dart脚本+maven仓库远程依赖方式,也是我最开始采用的方案。

步骤一:创建maven仓库,咨询了公司运维,得知还没有自己的maven私库后,找运维同学分配了主机,通过nexus创建了maven私库。

               创建成功后界面如下:

基于Jekins+GitLab的混合工程实现Flutter自动化打包方案_第1张图片

 

其中maven-release,为版本发布的aar仓库依赖,maven-snapshot为开发阶段的快照aar依赖。

步骤二:

通过脚本修改.adroid下的部分配置文件,打包生成aar。

基于Jekins+GitLab的混合工程实现Flutter自动化打包方案_第2张图片

 

具体的脚本逻辑可以自己查看,主要参考了http://jsshou.cn/blog/flutter/flutter_build_android.html#%E8%84%9A%E6%9C%AC%E5%BC%80%E5%8F%91

 

步骤三:通过dart脚本上传aar到maven仓库。

将上述的文件配置完成后,就可以执行命令了,其中上传maven库时,要尤其主要地址和artifact-id的问题。

步骤四:在项目中通过类似其他网络库的依赖方式进行依赖:

基于Jekins+GitLab的混合工程实现Flutter自动化打包方案_第3张图片

 

方案二:shell脚本+jekins打包机文件迁移

方案一提供了一个很好地版本管理和快照的maven仓库方式,但是并没有和jekins很好地结合,例如无法获取flutter项目的commint_id,动态依赖不同的flutter分支,因此这里采用了第二种方式。

区别点主要在两点:

  1. 修改dart命令为shell命令,剥离整体对flutter的项目依赖,直接通过shell命令修改flutter代码中的build文件。
  2. 不再执行上传操作,直接在打包机中将生成的aar迁移到android的lib目录下依赖。
  3. 同时生成commit文件,迁移到android项目的assets目录下。

 

综上:采用了方案二来完成打包的逻辑。

打包实现逻辑

1、分支选择及路径配置

 

#!/bin/bash
#初始化默认值
build_configuration="release"
flutter_git="stable"

while [ "$1" != "" ]; do
  case $1 in
  -b | --build_configuration)
    shift
    build_configuration=("$1")
    ;;
  -f | --flutter_git)
    shift
    flutter_git="$1"
    ;;
  esac
  shift
done

  if [ "$build_configuration" = "daily" ]; then
    flutter_git="dev"
  elif [ "$build_configuration" = "daily_new" ]; then
    flutter_git="dev"
  elif [ "$build_configuration" = "debug" ]; then
    flutter_git="dev"
  else
    flutter_git="stable"
  fi
echo "${build_configuration} 当前选择 git 分支 ${flutter_git}"

work_path=${PWD}
cd ${work_path} # 当前位置跳到脚本位置
echo "work_path == ${work_path}"
flutter_path="${work_path}/stock_flutter/.android/Flutter/build/outputs/aar"
echo "flutter_path == ${flutter_path}"
target_path="${work_path}/libcommon/libs"
echo "target_path == ${target_path}"
target_asset_path="${work_path}/libcommon/src/main/assets/"

function moveArchiveFile() {
  # echo "moveFile ${build_configuration}"
  if [ $build_configuration = "Debug" ]; then
    echo "done =="
    exit
  fi

  filesPath="${flutter_path}/"
  cd $filesPath
  files=$(ls ${PWD})
  length=0
  for filename in $files; do
    let length=length+1
  done
  limitedLength=0
  echo "length == ${length}"

  if [[ $length -gt $limitedLength ]]; then
    for filename in $files; do
      #       echo "file1 == ${target_path}${filename}"
      #       echo "file2 == ${filesPath}${filename}"
      echo "file $filename"
         moveArrFile $filename
      echo "flutter 依赖包移动成功"
    done
  else
    echo "flutter 资源打包失败"
  fi
}
function moveArrFile() {
if [ ! -d ${target_asset_path} ];then
  mkdir ${target_asset_path}
else
  echo "文件夹已经存在"
fi
 if [[ $1 == *"txt"* ]]; then
    echo "txt"
      rm -rf "${target_asset_path}$1"
      mv -f "${filesPath}$1" "${target_asset_path}"
    else
      rm -rf "${target_path}$1"
      mv -f "${filesPath}$1" "${target_path}"
fi

}


clone flutter仓库代码

echo "*************************  更新本地文件 Flutter  *************************"

cd ${work_path}
#exit

echo "*************************  开始下载、打包 flutter 资源  *************************"

export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn

echo "remove cache data"
rm -rf "${work_path}/stock_flutter"

git clone ssh://[email protected]:2222/long-bridge-frontend/stock_flutter.git stock_flutter -b master

cd stock_flutter
git checkout -f ${flutter_git}
git pull

#git submodule update --init
git submodule update --force --recursive --init --remote

#read commit id
git_commit_id=$(git rev-parse --short HEAD)
echo "commit id = ${git_commit_id}"

echo "./flutterw clean"
./flutterw clean
./flutterw doctor
./flutterw pub get

修改flutter 打包的配置文件

由于需要区分google和普通release,主要是v7和v8的不同。

其中主要是

  1. .android下的build.gradle  .android/Flutter/build.gradle 版本修改。
  2. .android/gradle/wrapper/gradle.properties 版本修改,这里修改是由于我们项目的打包机上gradle版本问题,只能和android项目的保持一致。

 

echo "*************************  开始修改flutter-build相关文件  *************************"
#这里可以使用shell命令来修改文件
#${work_path}/stock_flutter/.flutter/bin/dart ${work_path}/stock_flutter/configs/build_android.dart
googleGradlePlugin="
  dependencies {\n
   embed \"io.flutter:flutter_embedding_release:1.0.0-a1440ca392ca23e874a105c5f3248b495bd0e247\"\n
    embed \"io.flutter:arm64_v8a_release:1.0.0-a1440ca392ca23e874a105c5f3248b495bd0e247\"\n
    embed \"io.flutter:armeabi_v7a_release:1.0.0-a1440ca392ca23e874a105c5f3248b495bd0e247\"\n
    def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()\n
    def plugins = new Properties()\n
    def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')\n
    if (pluginsFile.exists()) {\n
        pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }\n
    }\n
    plugins.each { name, path->\n
        File editableAndroidProject = new File(path, 'android' + File.separator + 'build.gradle')\n
        println name\n
        if (editableAndroidProject.exists()) {\n
            embed project(path: \":\$name\", configuration: 'default')\n
        }\n
    }\n
}"
gradlePlugin="
  dependencies {\n
   embed \"io.flutter:flutter_embedding_release:1.0.0-a1440ca392ca23e874a105c5f3248b495bd0e247\"\n
    embed \"io.flutter:armeabi_v7a_release:1.0.0-a1440ca392ca23e874a105c5f3248b495bd0e247\"\n
    def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()\n
    def plugins = new Properties()\n
    def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')\n
    if (pluginsFile.exists()) {\n
        pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }\n
    }\n
    plugins.each { name, path->\n
        File editableAndroidProject = new File(path, 'android' + File.separator + 'build.gradle')\n
        println name\n
        if (editableAndroidProject.exists()) {\n
            embed project(path: \":\$name\", configuration: 'default')\n
        }\n
    }\n
}
"
cd .android
sed -ig 's/3.5.0/3.4.0/' build.gradle
sed -i '' '10a\'$'\nclasspath "com.kezong:fat-aar:1.2.5"\n' build.gradle
cd Flutter
sed -i '' '$a\'$'\napply plugin: "com.kezong.fat-aar"\n' build.gradle
sed -i '' '$a\'$'\napply from: "../config/dependencies_gradle_plugin.gradle"\n' build.gradle
cd ..
mkdir "config"
cd config
touch dependencies_gradle_plugin.gradle
if [ "$build_configuration" = "google" ];then
  echo  ${googleGradlePlugin} > dependencies_gradle_plugin.gradle
else
echo  ${gradlePlugin} > dependencies_gradle_plugin.gradle
fi
cd ..
cd gradle
cd wrapper
sed -ig 's/5.6.2/5.6.4/' gradle-wrapper.properties
echo "*************************   结束修改flutter-build相关文件  *************************"

打包生成aar文件 迁移aar文件

 

echo "*************************  开始打包 flutter 资源  *************************"
cd ${work_path}
cd stock_flutter
if [ "$build_configuration" = "google" ];then
  ./flutterw build aar --no-debug --no-profile --target-platform android-arm64
else
   ./flutterw build aar --no-debug --no-profile --target-platform android-arm
fi

cd ${flutter_path}
echo "commit id=${git_commit_id}" >flutter_version.txt
ls
moveArchiveFile
sleep 5
cd ${work_path}

远程打包方式

远程打包通过jekins配置,主要需要配置的点在于

 

--build_configuration 后的配置区别:

  1. 不配置,对应 flutter分支为stable,主要用于项目发版
  2. daily ,对应 flutter分支为dev,主要用于Android  daily开发中需要更新最新的flutter代码。
  3. google,对应 flutter分支为stable,但是对应架构为v8,主要用于google市场上架。

基于Jekins+GitLab的混合工程实现Flutter自动化打包方案_第4张图片

 

你可能感兴趣的:(Android技术前瞻,android,java)