likes
comments
collection
share

研究基于 Flutter Shorebird 热更新支持中国区域的问题

作者站长头像
站长
· 阅读数 11

研究基于 Flutter Shorebird 热更新支持中国区域的问题

最新进展

官方已经将谷歌的存储放在他们自身的 CDN github.com/shorebirdte…

所以这一篇文章所解决的问题不再存在了

问题如下

Shorebird 支持对于 iOS 和 android 平台的代码无感知的热更新,目前 iOS 还处于 Alpha 阶段,存在执行速度比 Android 慢 100 倍,但是对于一些方法执行只需要几毫秒,我觉得影响不大,只要能在线上紧急的处理一些重要的 BUG。

对于怎么集成 Shorebird 我就不过多的说明,大家可以自行前往 shorebird.dev 看说明文档。

目前我们的项目已经升级到 Flutter 3.13.2 版本,已经符合 Shorebird 支持的条件,我觉得重新拉取分支进行接入。

但是不幸的是对于中国区域不支持,比如执行 Shorebird 对于 FLUTTER_STORAGE_URL 不支持,这个问题不大我们可以开启代理,unset 这个参数即可。

目前主要的问题是,Shorebird 将补丁存在在谷歌存储,对于国内的用户无法下载,导致最后一步热更新的流程阻塞。

分析问题

对于之前的 Shorebird 版本可以在日志看到返回补丁的资源路径,可以在代理下载出来。我再想能否可以在开发完毕补丁之后,将补丁上传到 Shorebird 之后。再下载下来,之后上传到自己的服务器,将自己服务器的补丁下载在 App 目录下面,这样 Shorebird 就可以知道正常的加载补丁热更了。

但是不幸运的是,最新版本的 Shorebird 已经屏蔽了请求补丁日志的输出,我们无法获取到最新补丁的资源的路径,就在我准备放弃这个方案的时候,我在 Github 搜索到一个大神的一篇文章。

github.com/popeyelau/w…

我们可以通过下面的请求获取到补丁的地址

curl -X "POST" "https://api.shorebird.dev/api/v1/patches/check" \
     -H 'Content-Type: application/json; charset=utf-8' \
     -d $'{
  "platform": "ios", # 平台
  "arch": "aarch64", # 架构
  "release_version": "1.0.0+1697186586", # App 对应版本
  "app_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", # App Id
  "channel": "stable",
  "patch_number": 0 # 当前补丁号
}'

最后我们获取到下面的请求返回

{
    "patch_available": true,
    "patch": {
        "number": 1,
        "download_url": "https://storage.googleapis.com/shorebird_patch_artifacts/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/ios/aarch64/xxxxxx/dlc.vmcode",
        "hash": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    }
}

我们成功拿到了最新的补丁号和补丁的下载地址。

iOS 存放补丁相关文件在下面的路径 AppData/Library/Application\ Support/shorebird

没有加载任何补丁的的文件如下

研究基于 Flutter Shorebird 热更新支持中国区域的问题

// state.json
{
  "client_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "release_version": "1.0.0+1697186586", # 版本号
  "queued_events": []
}

手机开启代理,也不能直接下载谷歌的资源,目前不知道原因。但是竟然有一次成功了,成功加载补丁的文件如下。

研究基于 Flutter Shorebird 热更新支持中国区域的问题

其中 downloads/1 和 patches/1/dlc.vmcode 是同一个补丁文件。

// patches_state.json
{
  "last_booted_patch": {
    "number": 1, // 上一次补丁的版本号
    "size": 18434176 // 上一次补丁的大小
  },
  "next_boot_patch": {
    "number": 1, // 下一次补丁的版本号
    "size": 18434176 // 下一次补丁的大小
  },
  "highest_seen_patch_number": 1
}

这中间下载完毕的的文件我没有看到具体样子,中间的逻辑不是很清楚。但是我通过将上面的文件复制到导出的.xcappdata 里面,之后重新替换之后,我发现确实已经更新了最新了补丁。

为了验证我的猜想我,准备再打一个补丁 2,按照上面结构进行修改看看是否可以。

我修改上面的文件结构如下

研究基于 Flutter Shorebird 热更新支持中国区域的问题

之后修改 patches_state.json 的内容如下

{
  "last_booted_patch": {
    "number": 1,
    "size": 18434176
  },
  "next_boot_patch": {
    "number": 2,
    "size": 18454248
  },
  "highest_seen_patch_number": 2
}

最新文件的大小可以通过下面的方式获取(macOS)

研究基于 Flutter Shorebird 热更新支持中国区域的问题

这简介里面可以看到,之后我们将修改的Container 重新导入覆盖,重新打开 App 果然已经走最新的补丁了。

从此处的实验,我们可以可以得到了一个结论,我们可以通过这样的结论做到使用 Shorebird 在国内内容热更新服务。

上面只是我们人工走完了流程,但是整个还需要和后台配合,将资源下载放在后台,之后通过编写 Flutter 库操作 iOS 的文件做到这样的效果。

关于如何在国内使用 Shorebird 热更新服务的整套逻辑已经讲完了,剩下的就完善这中间的过程,写代码实现自动化的过程。