研究基于 Flutter Shorebird 热更新支持中国区域的问题
在写这一篇文章之前,我并不知道结果,我现在想把过程写出来。
问题如下
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 搜索到一个大神的一篇文章。
我们可以通过下面的请求获取到补丁的地址
json
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 # 当前补丁号
}'
最后我们获取到下面的请求返回
json
{
"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
没有加载任何补丁的的文件如下
json
// state.json
{
"client_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"release_version": "1.0.0+1697186586", # 版本号
"queued_events": []
}
手机开启代理,也不能直接下载谷歌的资源,目前不知道原因。但是竟然有一次成功了,成功加载补丁的文件如下。
其中 downloads/1 和 patches/1/dlc.vmcode 是同一个补丁文件。
json
// patches_state.json
{
"last_booted_patch": {
"number": 1, // 上一次补丁的版本号
"size": 18434176 // 上一次补丁的大小
},
"next_boot_patch": {
"number": 1, // 下一次补丁的版本号
"size": 18434176 // 下一次补丁的大小
},
"highest_seen_patch_number": 1
}
这中间下载完毕的的文件我没有看到具体样子,中间的逻辑不是很清楚。但是我通过将上面的文件复制到导出的.xcappdata 里面,之后重新替换之后,我发现确实已经更新了最新了补丁。
为了验证我的猜想我,准备再打一个补丁 2,按照上面结构进行修改看看是否可以。
我修改上面的文件结构如下
之后修改 patches_state.json 的内容如下
json
{
"last_booted_patch": {
"number": 1,
"size": 18434176
},
"next_boot_patch": {
"number": 2,
"size": 18454248
},
"highest_seen_patch_number": 2
}
最新文件的大小可以通过下面的方式获取(macOS)
这简介里面可以看到,之后我们将修改的Container 重新导入覆盖,重新打开 App 果然已经走最新的补丁了。
从此处的实验,我们可以可以得到了一个结论,我们可以通过这样的结论做到使用 Shorebird 在国内内容热更新服务。
上面只是我们人工走完了流程,但是整个还需要和后台配合,将资源下载放在后台,之后通过编写 Flutter 库操作 iOS 的文件做到这样的效果。
关于如何在国内使用 Shorebird 热更新服务的整套逻辑已经讲完了,剩下的就完善这中间的过程,写代码实现自动化的过程。