使用Shorebird实现Flutter静默更新:从入门到精通

本文详细介绍了如何使用Shorebird为Flutter应用实现静默更新,包括安装配置、核心工作流程、应用内更新逻辑、强制更新策略以及生产环境最佳实践,帮助开发者快速修复关键bug而无需经过应用商店审核。

使用Shorebird在Flutter中推送静默更新

想象一下,你刚刚发布了一个主要功能。你的应用正在排行榜上攀升,但随后第一个错误报告出现了。这是一个关键支付验证错误。修复只需要一行Dart代码,但现在你面临 dreaded 应用商店审核队列,数小时甚至数天的延迟,而你的用户和收入都受到影响。

如果你能绕过商店,在几分钟内直接将修复推送给用户呢?这就是Shorebird为你的Flutter工作流程带来的力量。这不仅仅是速度的问题,更是关于控制、可靠性和提供卓越用户体验的问题。

本指南将带你从新手到专家,涵盖从设置Shorebird到使用upgrader包实现健壮的生产级更新策略的所有内容。

目录

  • 先决条件
  • 什么是Shorebird?
    1. “为什么”:何时修补 vs 何时发布
    1. 入门:安装和项目设置
    1. 核心工作流程:发布和修补
    1. 掌控:Flutter中的应用内更新逻辑
    1. 核选项:使用upgrader强制更新
    1. 实战手册:结合Shorebird、Upgrader和远程配置
    1. 生产级最佳实践
    1. 安全性、成本和限制
  • 参考资料

先决条件

在深入之前,请确保你具备以下知识和工具设置。这将帮助你顺利跟随指南并避免常见的设置问题。

知识和技能

  • 基础Flutter知识:你应该熟悉创建Flutter项目、使用pubspec.yaml管理包,并理解基本的widget生命周期。本指南假设你有一个现有的Flutter应用程序可供使用。
  • 命令行熟练度:你需要熟悉使用终端(如macOS/Linux上的Terminal或Windows上的PowerShell),因为Shorebird主要是一个命令行界面(CLI)工具。这包括导航目录和执行命令。
  • 基础Git和版本控制:理解提交、分支(main、hotfix)和检出代码等概念对于管理发布、从特定代码状态创建补丁以及实现回滚策略至关重要。

工具和环境

  • 可用的Flutter开发环境
    • 最新稳定版本的Flutter SDK。
    • 配置用于Flutter的IDE,如VS Code或Android Studio。
  • Shorebird账户
    • 你需要在Shorebird网站上注册一个免费账户。shorebird login命令需要这个。
  • 平台特定构建工具
    • 对于Android:
      • 安装Android Studio和相应的Android SDK。
      • 为你的项目配置签名密钥库(key.jks)和key.properties文件。Shorebird需要这个来创建签名的、生产就绪的发布版本(AABs)。
    • 对于iOS:
      • 安装Xcode的macOS计算机。在Windows或Linux上无法构建iOS应用。
      • 需要活跃的Apple开发者计划成员资格来代码签名和发布iOS应用。

可选(但推荐用于完整策略)

  • Firebase项目:要实现涉及强制更新和远程功能标志的完整实战策略,你将需要:
    • 链接到你的Flutter应用的Firebase项目。
    • 启用的Firebase远程配置服务。
    • 添加到pubspec.yaml的firebase_core和firebase_remote_config包。

什么是Shorebird?

Shorebird是一个专门为Flutter应用程序设计的代码推送服务。它允许开发者直接向用户设备提供小的关键错误修复甚至新功能,绕过传统的应用商店审核过程。本质上,它实现了Flutter应用的"空中"(OTA)更新。

这意味着,与其等待数小时或数天获得应用商店对简单修复的批准,你几乎可以立即部署更改,确保对问题的响应更快,用户停机时间减少,对收入的影响最小。它让你对应用的部署生命周期有更大的控制,并有助于维持更流畅、更可靠的用户体验。

1. “为什么”:何时修补 vs 何时发布

在深入"如何"之前,理解"何时/为什么"至关重要。并非所有更新都是平等的。为工作使用正确的工具是稳定高效开发周期的关键。

使用shorebird patch用于:

  • 关键错误修复:Dart代码中的逻辑错误(例如,计算错误、空指针异常、不正确的状态管理)。
  • 次要UI调整:更改颜色、文本或布局逻辑而不添加新资源。
  • 功能标志切换:推送代码更改以启用或禁用你已经构建和部署的功能。
  • 性能改进:优化算法或Dart级渲染逻辑。

使用完整商店发布用于:

  • 原生代码更改:对android或ios目录的任何修改。
  • 插件/依赖更新:在pubspec.yaml中添加新包或升级现有包,因为这通常会更改原生代码或包含预编译的二进制文件。
  • 资源更改:添加新图像、字体、JSON文件或任何其他资源。
  • 主要功能发布:当应用的功能或UI发生显著变化时,最佳实践(并且通常由商店政策要求)是通过完整审核。

可以这样想:如果更改只在你的.dart文件中且不触及pubspec.yaml,那么它很可能是可修补的。

2. 入门:安装和项目设置

让我们准备好你的环境和项目以使用Shorebird。

步骤1:安装Shorebird CLI

打开终端并运行官方安装脚本:

1
curl https://raw.githubusercontent.com/shorebirdtech/shorebird/main/install.sh -sSf | bash

步骤2:将Shorebird添加到你的PATH

要从任何地方使用shorebird命令,将其添加到你的shell配置文件(.zshrc、.bashrc、.bash_profile等)。

1
export PATH="$HOME/.shorebird/bin:$PATH"

重新启动终端或运行source ~/.zshrc(或你的相应文件)以使更改生效。

步骤3:验证和登录

确认安装成功并登录到你的Shorebird账户。

1
2
shorebird --version
shorebird login

这将打开一个浏览器窗口以验证你的CLI与Shorebird服务。

步骤4:在你的Flutter项目中初始化Shorebird

导航到你的Flutter项目的根目录并运行:

1
shorebird init

此命令是你的项目进入Shorebird生态系统的入口点。以下是它在幕后所做的:

  • 创建shorebird.yaml:此文件存储你的唯一应用ID。将其提交到版本控制。
  • 修改pubspec.yaml:它自动添加shorebird_code_push包,这是应用与Shorebird服务器通信所必需的。
  • 更新.gitignore:添加.shorebird/目录以防止临时构建工件被提交。

3. 核心工作流程:发布和修补

Shorebird的工作流程建立在一个简单的概念上:你创建一个基础发布,然后对其应用补丁。

步骤1:创建完整发布

在修补任何内容之前,你需要一个使用Shorebird构建的完整版本的应用。此发布将提交到App Store和Play Store。

1
2
3
4
5
# 对于Android
shorebird release android

# 对于iOS
shorebird release ios

此命令编译你的应用,将必要的符号上传到Shorebird的服务器以便以后构建补丁,并生成发布工件(AAB/IPA)供你上传到商店。

步骤2:创建和发布补丁

在修复错误或调整Dart代码后,你可以创建补丁。Shorebird将比较你的更改与原始发布,并创建一个小的、高效的二进制差异。

1
2
3
4
5
# 修补最新的Android发布
shorebird patch android

# 修补最新的iOS发布
shorebird patch ios

此补丁立即可用于安装了相应基础发布的用户。

步骤3:用户体验

当你推送补丁时,该过程设计为无缝:

  • 静默下载:在下次应用启动时,shorebird_code_push SDK检查新补丁。如果找到,它会在后台静默下载。
  • 下次重新启动时应用:下载的补丁被暂存,并在用户关闭并重新打开应用时自动应用。这确保他们当前的会话不会中断。

4. 掌控:Flutter中的应用内更新逻辑

为了更受控的体验,你可以使用shorebird_code_push包来管理应用内的更新过程。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import 'package:shorebird_code_push/shorebird_code_push.dart';

final _shorebirdCodePush = ShorebirdCodePush();

// 在应用启动时检查新补丁。
void checkForUpdate() async {
  // 检查是否有新补丁可用。
  final isUpdateAvailable = await _shorebirdCodePush.isNewPatchAvailableForDownload();

  if (isUpdateAvailable) {
    // 可选地,你可以在这里向用户显示对话框。
    // 例如,"有一个快速更新可用。它将在下次重启时应用。"

    // 下载新补丁。
    await _shorebirdCodePush.downloadUpdateIfAvailable();
  }
}

// 对于关键更新,你可以强制立即重启。
void forceRestart() async {
  // 确保补丁已下载并准备好安装。
  if (await _shorebirdCodePush.isNewPatchReadyToInstall()) {
    // 这将强制应用关闭并使用新补丁重新启动。
    // 谨慎使用,因为它是一种破坏性的用户体验。
    await _shorebirdCodePush.installUpdateAndRestart();
  }
}

在你的main()函数或主屏幕的initState中调用checkForUpdate()。

5. 核选项:使用upgrader强制更新

有时,Shorebird补丁不够。对于涉及原生代码、新资源的关键更新,或者如果你需要确保每个用户立即使用最新版本,你需要一个阻塞更新屏幕。upgrader包非常适合这一点。

步骤1:添加依赖

1
2
dependencies:
  upgrader: ^7.0.0

步骤2:实现阻塞UI

用UpgradeAlert widget包装你的MaterialApp,创建一个无法解除的阻塞对话框。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import 'package:flutter/material.dart';
import 'package:upgrader/upgrader.dart';

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // 此配置创建一个阻塞的"必须更新"屏幕。
    final upgrader = Upgrader(
      showIgnore: false,
      showLater: false,
      canDismissDialog: false,
      dialogStyle: UpgradeDialogStyle.material,
      shouldPopScope: () => false, // 防止返回导航
    );

    return MaterialApp(
      home: UpgradeAlert(
        upgrader: upgrader,
        child: HomeScreen(), // 你的应用主屏幕
      ),
    );
  }
}

6. 实战手册:结合Shorebird、Upgrader和远程配置

以下是如何将所有内容结合起来以实现防弹更新策略。让我们使用Firebase远程配置作为我们的远程"终止开关"。

场景:你的应用版本1.2.0有一个关键支付错误。

战术手册

  1. 修复错误:更正Dart代码中的错误。
  2. 推送Shorebird补丁
    1
    2
    
    shorebird patch android --release-version 1.2.0+10 
    # 使用--release-version以定位特定构建
    
    这快速且静默地将修复传递给活跃用户。
  3. 设置远程标志:在你的Firebase远程配置控制台中,创建一个参数如force_update_for_version,并将其值设置为"1.2.0"。
  4. 在应用中实现逻辑:在应用启动时,在显示主UI之前检查此标志。
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    
    import 'package:firebase_remote_config/firebase_remote_config.dart';
    import 'package:package_info_plus/package_info_plus.dart';
    
    Future<void> main() async {
      // ... 初始化代码 ...
    
      // 获取当前应用版本
      final packageInfo = await PackageInfo.fromPlatform();
      final currentVersion = packageInfo.version;
    
      // 获取远程配置
      final remoteConfig = FirebaseRemoteConfig.instance;
      await remoteConfig.fetchAndActivate();
      final forceUpdateVersion = remoteConfig.getString('force_update_for_version');
    
      // 检查此版本是否被标记为强制更新
      if (currentVersion == forceUpdateVersion) {
        // 这是一个"坏"版本。显示阻塞更新屏幕。
        runApp(ForcedUpdateApp());
      } else {
        // 此版本正常。运行正常应用并检查Shorebird补丁。
        checkForUpdate(); // 你的Shorebird检查函数
        runApp(MyApp());
      }
    }
    
    // 一个只显示upgrader屏幕的简单应用。
    class ForcedUpdateApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: UpgradeAlert(
            child: Scaffold(body: Center(child: Text('Checking for updates...'))),
          ),
        );
      }
    }
    

这种双重策略确保尚未收到Shorebird补丁的用户仍然被阻止使用有错误的版本,并被引导到商店。

7. 生产级最佳实践

在生产中点击"patch"之前,你应该像对待任何其他发布管道一样对待Shorebird:测试构建、分波次推出、关注崩溃指标,并自动化无聊的部分。以下是一些要遵循的最佳实践:

首先,始终测试补丁。在部署给用户之前,使用shorebird preview在本地设备或模拟器上测试你的补丁。

1
shorebird preview

使用带通道的分阶段推出。不要一次将关键补丁推送给100%的用户。Shorebird的"channels"功能让你首先部署到暂存受众。

1
2
3
4
5
# 将补丁推送给内部测试者
shorebird patch android --channel=staging

# 验证后,推广给所有用户
shorebird promote --channel=staging --release-version 1.2.0+10

你还应该有一个回滚计划,如果补丁使情况变得更糟。在这种情况下,最快的修复方法是向前修补。从Git检出最后一个已知良好的提交并再次运行shorebird patch。这个新补丁将覆盖坏的补丁。

并确保监控一切。为此,你可以使用Firebase Crashlytics或Sentry等工具来监控补丁发布后的崩溃率和应用稳定性。

最后,使用CI/CD自动化是有帮助的,你可以将Shorebird集成到你的CI/CD管道中(例如,GitHub Actions)。将SHOREBIRD_TOKEN存储为秘密,并使用命令如shorebird patch android –release-version –force来自动化部署。

8. 安全性、成本和限制

使用Shorebird时,你应该记住一些其他事项。

首先,与Shorebird服务器的所有通信都通过TLS。补丁是加密签名的,shorebird_code_push SDK在应用更新之前验证此签名,确保其未被篡改。

其次,Shorebird采用免费增值模式,提供慷慨的免费层级。付费计划基于月活跃用户(MAU)并解锁团队功能。你可以查看官方定价页面获取当前详细信息。

此外,请记住有一些我们已经提到过的限制:例如,Shorebird只修补Dart代码。你不能用补丁更新原生插件、添加/更改资源或修改原生代码(android/ios文件夹)。这些更改总是需要完整的商店发布。

总结

Shorebird对于任何认真的Flutter开发者来说都是一个变革性的工具。它将发布过程从单一的、缓慢的周期转变为动态的、响应式的周期。

通过将Shorebird的快速修补与使用upgrader和远程配置的健壮强制更新策略相结合,你获得了对生产应用程序前所未有的控制。你可以在几分钟内修复错误,降低风险,并保持用户满意——所有这些都无需等待应用商店。

参考资料

  1. Shorebird

  2. Upgrader包

  3. 支持工具和概念

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计