Flutter - 混编项目集成Shorebird热更新🐦(安卓篇)

欢迎关注微信公众号:FSA全栈行动 👋

一、概述

目前我们的项目是按照 Flutter 官方文档 docs.flutter.dev/add-to-app/...,以源码依赖的方式集成到原生项目,在集成 Shorebird 实现热更新时,需要我们将源码依赖的方式调整成二进制依赖。

安卓端的改动还是很简单的,一路下来没怎么碰壁,接下来一起来看看如何操作吧

二、Shorebird 初始化

本文以 Mac 环境为例,如果你是 Windows 用户,请按官方文档去操作: docs.shorebird.dev

该部分内容只需要一开始没有环境和相应的文件时去操作一次

安装 CLI

打开终端,执行以下命令

shell 复制代码
curl --proto '=https' --tlsv1.2 https://raw.githubusercontent.com/shorebirdtech/install/main/install.sh -sSf | bash

重启终端,输入 shorebird 即可看到相应的命令输出

shell 复制代码
$ shorebird
The shorebird command-line tool

Usage: shorebird <command> [arguments]

Global options:
-h, --help            Print this usage information.
    --version         Print the current version.
-v, --[no-]verbose    Noisy logging, including all shell commands executed.

Available commands:
  cache      Manage the Shorebird cache.
  doctor     Show information about the installed tooling.
  flutter    Manage your Shorebird Flutter installation.
  init       Initialize Shorebird.
  login      Login as a new Shorebird user.
  login:ci   Login as a CI user.
  logout     Logout of the current Shorebird user
  patch      Manage patches for a specific release in Shorebird.
  preview    Preview a specific release on a device.
  release    Manage your Shorebird app releases.
  upgrade    Upgrade your copy of Shorebird.

Run "shorebird help <command>" for more information about a command.

你可以查看当前 Shorebird 支持哪些 Flutter 版本

shorebird flutter versions list
ruby 复制代码
$ shorebird flutter versions list
📦 Flutter Versions
✓ 3.13.9
  3.13.8
  3.13.7
  3.13.6
  3.13.5
  3.13.4
  3.13.3
  3.13.2
  3.13.1
  3.13.0
  3.10.7
  3.10.6
  3.10.5
  3.10.4
  3.10.3
  3.10.2
  3.10.1
  3.10.0

如我现在需要用到 Flutter 3.13.9 版本,则输入如下命令

shell 复制代码
$ shorebird flutter versions use 3.13.9

Flutter 模块初始化

在你的 Flutter 项目下执行如下命令

csharp 复制代码
shorebird init

该命令会生成在项目根目录生成 shorebird.yaml 文件

yaml 复制代码
# shorebird.ymal的内容
app_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx

# auto_update: false

以及修改 pubspec.yaml

yaml 复制代码
  assets:
    - shorebird.yaml

三、原生项目改造

以下的相关修改是以我们项目来写的(.kts),如果你的跟我的不一样,可以看一下文档:docs.shorebird.dev/guides/hybr...

build.gradle.kts

新增本地二进制依赖

diff 复制代码
buildscript {
    repositories {
        ...
            
+        // 本地依赖Flutter包
+        maven(url = "../../flutter_module/release")
+        maven(url = "https://download.shorebird.dev/download.flutter.io")
        
        ...
    }
}

allprojects {
    repositories {
        ...
            
+        // 本地依赖Flutter包
+        maven(url = "../../flutter_module/release")
+        maven(url = "https://download.shorebird.dev/download.flutter.io")
        
        ...
    }
}

settings.gradle.kts

注释掉本地源码依赖

diff 复制代码
- evaluate(new File(
-         settingsDir,
-         "../flutter_module/.android/include_flutter.groovy"
- ))
+ //evaluate(new File(
+ //        settingsDir,
+ //        "../flutter_module/.android/include_flutter.groovy"
+ //))

app/build.gradle.kts

注释掉本地源码依赖,新增本地二进制依赖

diff 复制代码
dependencies {
+    // Flutter源码依赖
-    implementation(project(LocalLib.flutter))    
+    // implementation(project(LocalLib.flutter))

+    // Flutter二进制依赖
+    releaseImplementation("com.lxf.flutter_modules:flutter_release:1.0")
}

四、创建 Shorebird Release

打发布包的时候操作,在 Flutter 工程目录下执行

shell 复制代码
cd xx/xx/flutter_modules

# 7.0.0+320: 大版本号+小版本号
shorebird release aar --release-version 7.0.0+320

该命令内部会去执行 flutter build aar --no-debug --no-profile ...,并且使用的是 Shorebird 魔改的 Flutter 引擎!

版本号可以在如下路径的文件中查看

xml 复制代码
# 路径: app/src/main/AndroidManifest.xml
# 小版本号: android:versionCode
# 大版本号: android:versionName

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.lxf.flutter_modules"
    android:versionCode="320"
    android:versionName="7.0.0">
...
</manifest>

ShoreBird 的内部逻辑会去以这个版本号组合,向服务器请求判断是否存在相应版本的相关补丁!

执行完成后,在 Shorebird 控制台上可以看到相应的项

在命令执行前,请确保不存在 7.0.0+320Release,如果有的话,请先删除

五、创建 Shorebird Patch

紧急修复线上包的bug时操作,在 Flutter 工程目录下执行

shell 复制代码
shorebird patch aar --release-version 7.0.0+320

注:版本号与上述的 release 命令中使用的要保持一致!

执行完成后,在 Shorebird 控制台上点击对应的 Release 项,进去后可以看到相应的补丁

六、热更新验证

  1. 未打 patch 时,请以 release 模式运行原生工程(在 Active Build Variant 的下拉选项中选择 release
  2. 关闭 App
  3. patch 后,重新打开 App,关闭 App 再打开 App,即可看到变化

如果补丁没有生效,可以在 Logcat 内检测相关输出,成功还是失败可以直接看后两句,如下两种情况的输出:

成功:

shell 复制代码
[INFO:shorebird.cc(109)] Shorebird updater: no active patch.
[INFO:shorebird.cc(113)] Starting Shorebird update
updater::network: Sending patch check request: PatchCheckRequest { app_id: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx", channel: "stable", release_version: "7.0.0+320", patch_number: None, platform: "android", arch: "aarch64" }
updater::updater: Patch 1 successfully installed.
updater::updater: Update thread finished with status: Update installed

失败:

shell 复制代码
[INFO:shorebird.cc(109)] Shorebird updater: no active patch.
[INFO:shorebird.cc(113)] Starting Shorebird update
updater::network: Sending patch check request: PatchCheckRequest { app_id: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx", channel: "stable", release_version: "7.0.0+320", patch_number: None, platform: "android", arch: "aarch64" }
updater::updater: Update failed: failed to fill whole buffer
updater::updater: Update thread finished with status: Update had error

失败的时候,看一下 PatchCheckRequest 后面的请求参数输出,一般失败都是因为这里的参数错误才导致。

七、脚本

由于我们日常研发还是使用的是源码依赖的方式,只会在打最终测试包时才需要去做上述的调整操作,所以这里用我比较熟悉的 Python 去制作了简易的脚本,并结合 Jenkins 来辅助完成这种万年不变的无聊步骤

脚本已上传至 Github: github.com/LinXunFeng/...

看官可自取修改~

switch_flutter_integrate.py

切换 Flutter 项目的集成方式

shell 复制代码
# 二进制依赖
python switch_flutter_integrate.py -p '原生工程路径' -m 'binary' -f 'android'

# 源码依赖
python switch_flutter_integrate.py -p '原生工程路径' -m 'source' -f 'android' 

shorebird.py

自动获取版本号,并执行 Shorebird 相关命令

shell 复制代码
# release
python shorebird.py -p '原生工程路径' -s 'Flutter工程路径' -m release -f android

# patch
python shorebird.py -p '原生工程路径' -s 'Flutter工程路径' -m patch -f android

八、最后

本篇到此结束,感谢大家的支持,我们下次再见! 👋

如果文章对您有所帮助, 请不吝点击关注一下我的微信公众号:FSA全栈行动, 这将是对我最大的激励. 公众号不仅有 iOS 技术,还有 AndroidFlutterPython 等文章, 可能有你想要了解的技能知识点哦~

相关推荐
余生H14 分钟前
前端的全栈混合之路Meteor篇:关于前后端分离及与各框架的对比
前端·javascript·node.js·全栈
程序员-珍17 分钟前
使用openapi生成前端请求文件报错 ‘Token “Integer“ does not exist.‘
java·前端·spring boot·后端·restful·个人开发
axihaihai22 分钟前
网站开发的发展(后端路由/前后端分离/前端路由)
前端
流烟默34 分钟前
Vue中watch监听属性的一些应用总结
前端·javascript·vue.js·watch
2401_8572979144 分钟前
招联金融2025校招内推
java·前端·算法·金融·求职招聘
茶卡盐佑星_1 小时前
meta标签作用/SEO优化
前端·javascript·html
与衫1 小时前
掌握嵌套子查询:复杂 SQL 中 * 列的准确表列关系
android·javascript·sql
Ink1 小时前
从底层看 path.resolve 实现
前端·node.js
金灰1 小时前
HTML5--裸体回顾
java·开发语言·前端·javascript·html·html5
茶卡盐佑星_1 小时前
说说你对es6中promise的理解?
前端·ecmascript·es6