Shorebird: CodePush & Over-the-Air Updates for Flutter Apps
As we all know(even if we don't know), the Flutter framework does not support code push for iOS/Android app patching out of the box.
The Flutter team has announced that Flutter would not support code push/hot update functions in their engine. Surely they have their reasons. You can read the issue here to get a full gist of the situation.
Codepush is a common name for “Over the air update”, I guess originally taken from Codepush, an App Center cloud service enabling React Native developers to deploy mobile app updates directly to their users’ devices. For this article, I will be using OTA(Over the air update) more instead of codepush except when I am referring to the codepush service itself.
Over-the-air update(OTA) is the wireless delivery of new software to mobile devices. Normally when you want to update your app, you need first to build it and then send it to App Store or Google Play. A major drawback of this solution is the time needed for these stores to approve your update. Imagine a situation where an app with a critical error was published to users by mistake. In these cases, every second counts. And this is where Over The Air (OTA) may help us. OTA allows us to send updates directly to users without accepting them from the Apple store or Google Play store. We can almost immediately fix errors or push small updates (more on those later).
Originally, the Flutter framework does not support over-the-air updates. Developers asking for such service often make comparisons with React Native. Technically, the React Native framework itself does not support over-the-air updates. This is where the codepush service comes in. A third-party service different from the framework that allows over-the-air updates, adding small features that don’t require you to rebuild a binary or redistribute it through any public app stores. Enter shorebird.
Shorebird is codepush for Flutter. Shorebird is a third-party service that allows you to do over-the-air updates - add features or make fixes that don’t require you to rebuild a binary or redistribute it through public app stores. Shorebird is easy to use, push an update to any dart code, and is available to the Android platform with support for ios coming soon. Let's look at how it works by integrating Shorebird into our workflow.
Getting started
Setting up Shorebird involves the following process.
Installing the Shorebird command line interface (CLI)
Installing Shorebird CLI requires git
installed on your machine. Where you don't have git installed, ensure to install git
before you proceed. It should be noted that Shorebird is installed into ~/.shorebird/bin
and added to your PATH. It also installs a copy of Flutter and Dart inside ~/.shorebird/bin/cache/flutter
. The copy of Flutter is slightly modified to add Shorebird code push and is not intended to be added to your PATH. You can continue using the Flutter and Dart versions you already have installed.
Mac/Linux
curl --proto '=https' --tlsv1.2 https://raw.githubusercontent.com/shorebirdtech/install/main/install.sh -sSf | bash
Windows
powershell -exec bypass -c "(New-Object Net.WebClient).Proxy.Credentials=[Net.CredentialCache]::DefaultNetworkCredentials;iwr -UseBasicParsing 'https://raw.githubusercontent.com/shorebirdtech/install/main/install.ps1'|iex"
To look into how the installation works, you can check the installation scripts here. Once installation is complete, shorebird should be available in your terminal.
You should also run the shorebird doctor
command to ensure things are set up correctly. its a utility similar to flutter doctor
.
The doctor
tells me that the shorebird flutter version differs from what I have globally on my machine. This is not a problem for me as I manage multiple Flutter versions with fvm and have the exact Flutter version Shorebird uses.
Signup/Login
To use Shorebird to ship apps, one must create a Shorebird account from the terminal.
shorebird account create
This command is followed by the Google OAuth2 instructions. Please follow accordingly.
Users who just signed up are automatically logged in. However, existing users would have to log in to Shorebird using:
shorebird login
This command is followed by the Google OAuth2 instructions. Please follow accordingly.
Now that we are all set up, we can start shipping and patching our apps with Shorebird.
Building with shorebird
There are two ways we can build an app - Manually by using the flutter build
command or with a CI/CD platform like codemagic, GitHub actions etc. With Shorebird, it's a similar process. Either run the shorebird commands locally or set up a ci environment to do that. We will be covering how to build and patch from our local machines.
Performing OTA with Shorebird on your apps requires that you go through the following process:
- Initialize shorebird
- Shorebird run (optional)
- Shorebird release/patch/build, as the case may be
Initialize Shorebird
Shorebird Run
This is the equivalent of flutter run -- release
but with Shorebird’s fork of the flutter engine, including the Shorebird updater. You should run the shorebird run
command to be sure your app runs successfully. For passing command line arguments to the flutter SDK, you can pass these arguments to the shorebird run command using a separator --
and then the arguments as you would to the flutter run command. An example is shown below:
shorebird run -- --dart-define="API_KEY=SomeKey"
Release, Build, Patch
There are mainly 2 ways to build a release version of your app, including code push. Either you use the release command or the build command. Let’s take a look at what makes them different.
Shorebird Release
To publish a release, you need to use the shorebird release command. Using the release command on Android, generates an app bundle (aab). At the moment, there is no official announcement on iOS support. However, this is believed to be announced soon(The site says launching in July).
shorebird release android
Running Shorebird release creates a release build and submits your app to Shorebird. You can pass flavor and target arguments the same way you pass them to the flutter build command by running: shorebird release --target ./lib/main_dev.dart --flavor dev
. For every other argument, you can pass these arguments to the shorebird run command using a separator --
and then the arguments as you would to the flutter run command. An example is shown below:
shorebird release -- --dart-define="API_KEY=SomeKey"
Binary generated with shorebird release should be uploaded to their respective stores.
Shorebird Build
The build command is a lower-level command. With the build command, shorebird codepush is included in your app and you can specify the artefact you want to build, either apk or app bundle.
shorebird build appbundle
You can pass flavor and target arguments the same way you pass them to the flutter build command by running: shorebird build appbundle --target ./lib/main_dev.dart --flavor dev
. For every other argument, you can pass these arguments to the shorebird run command using the separator --
and then the arguments as you would to the flutter run command. An example is shown below:
shorebird build appbundle -- --dart-define="API_KEY=SomeKey"
Shorebird Patch
A patch is an update to a released version of an app. To publish updates to an already released app, run the shorebird patch command:
shorebird patch android
Running Shorebird patch builds the artifacts, downloads the corresponding release artifacts and generates a patch using the diff between the release and current changes. This patch is uploaded to the Shorebird backend and promoted to the stable channel.
When a user launches the app, the app is updated since the patch is the latest stable. You can pass flavor and target arguments the same way you pass them to the flutter build command by running: shorebird patch --target ./lib/main_dev.dart --flavor dev
. For every other argument, you can pass these arguments to the shorebird run command using a separator --
and then the arguments as you would to the flutter run command. An example is shown below:
shorebird patch -- --dart-define="API_KEY=SomeKey"
You don't need to update the version number of your app to push new patches. Multiple patches are also allowed since the latest patch would be uploaded to the Shorebird backend and promoted to stable.
Below is a summary of how to do codepush and over the air updates in Flutter (of course, excluding initialization and authentication):
- Shorebird release and upload to the store
- Make changes to dart code
- Shorebird patch android
Many, including myself, have eagerly anticipated the introduction of over-the-air updates to Flutter. I’ve closely followed the progress of this tool and have been using it firsthand. I must say, it has impressed me and functions exceptionally well. In Iron Man’s words: Handles like a dream.
With codepush and over-the-air updates, there is always the question of whether it aligns with the store guidelines. Well, codepush isn't a new service in the industry, as we've seen solutions available in other frameworks and tools like appcenter and expo. The team says Shorebird is designed to comply with the store guidelines. You could check what Shorebird have to say about that here.
Generally, the Shorebird docs are easy to navigate. It is written by engineers, for engineers. Who else can understand the needs of an engineer if not another engineer?
Shorebird currently supports all Android devices, with iOS support launching in July. This article will be updated when that happens to reflect the ios bit of Shorebird.
PS: I do not work for Shorebird, nor in any way affiliated with them. I am just another developer exploring a codepush solution for mobile products.
Resources
Getting started with shorebird
Codepush quick start
Releasing a code push app