Color Mode


    Language

Introducing Shorebird, code push service for Flutter apps

November 7, 2024

Update Flutter apps without store review

What is Shorebird?

Shorebird is a service that allows Flutter apps to be updated directly at runtime. Removing the need to build and submit a new app version to Apple Store Connect or Play Console for review for every app update.

Flutter already comes with hot reload/restart that allows developers to quickly test code changes during development. Shorebird is similarly used for changes in production apps already in the hands of end-users.

Why?

Enabling production code to be updated without needing to go through the usual store review process, which greatly reduces the time required to release a critical bug fix. With finer control over app updates it would also let us develop mobile apps with smaller release windows and flexibility similar to web site deployments.

How?

Shorebird uses a modified version of the Flutter engine that allows updated code changes to be run at runtime using the Dart Virtual Machine. Since running code in the Virtual Machine is a lot slower then regular compiled code, Shorebird is smart enough to detect only the changed code parts to minimize its usage.

Broadly there are two main concepts.
Release: A full app binary containing the whole Flutter app, the same as you would normally build when releasing an app. With the difference it also contains a custom Flutter engine modified to run code in a virtual machine and functionality to check for updates. The release app needs to be reviewed and distributed through app stores as usual.

Patch: The patch only contains the code changes required for a Shorebird code push update. It's created by comparing the changes to the targeted release binary.

Both are created using the Shorebird CLI tool with the shorebird release and shorebird patch commands respectively. Behind the scenes this wraps the usual flutter build command.

Simple usage flow

  1. Install Shorebird CLI tools
  2. Register your Flutter app with Shorebird, using the shorebird init command
  3. Create a new app release with the shorebird release command
  4. Distribute the shorebird release app to app stores (or applicable distribution channels)
  5. Modify some dart code in the app (adding new functionality/fixing a bug)
  6. Create a patch with the shorebird patch command
  7. After the patch has been uploaded to Shorebird servers, on the next app start the patch will be downloaded and applied.

By default the app will check for any new patches and update the app at startup. The update check can also be done programmatically for more advanced use cases.

Example demo

For this example we will be following the Getting Started guide from the Shorebird documentation. In short we will be adding Shorebird to the Flutter counter example app, change some code and push a patch to the app.

  1. First we need to install the Shorebird CLI tools by using the handy install script.
curl --proto '=https' --tlsv1.2 https://raw.githubusercontent.com/shorebirdtech/install/main/install.sh -sSf | bash

For this demo I'm using a Mac setup but there are also instructions for Windows environments in the documentation. See the Getting Started link above.

  1. After the CLI tools have been installed we now have to set up the Flutter project to use Shorebird using the shorebird init command. You will also be prompted to select a name for your app. It's only used to manage your app in the Shorebird console and won't be shown to end-users.
user@my-mac shorebird_test % shorebird init
✓ No product flavors detected. (19.2s)
? How should we refer to this app? (shorebird_test) shorebird_test

🐦 Shorebird initialized successfully!

✅ A shorebird app has been created.
✅ A "shorebird.yaml" has been created.
✅ The "pubspec.yaml" has been updated to include "shorebird.yaml" as an asset.

Reference the following commands to get started:

📦 To create a new release use: "shorebird release".
🚀 To push an update use: "shorebird patch".
👀 To preview a release use: "shorebird preview".

For more information about Shorebird, visit https://shorebird.dev
✓ Shorebird is up-to-date (1.4s)
✓ Flutter install is correct (15.4s)
✓ AndroidManifest.xml files contain INTERNET permission (1 fix applied) (83ms)
✓ Has access to storage.googleapis.com (0.2s)
✓ shorebird.yaml found in pubspec.yaml assets (9ms)

Checking the Shorebird console we can see our app has been added.

The shorebird_test app has been registered in the Shorebird console
  1. Now we can create our first Shorebird supported release binary using the shorebird release command. Creating an apk file for Android only just to simplify things. This would need to be run again for the iOS app.
user@my-mac shorebird_test % shorebird release android --artifact apk
✓ Downloading patch... (0.4s)
✓ Extracting patch... (0.6s)
✓ Downloading bundletool.jar... (0.7s)
✓ Extracting bundletool.jar... (1.9s)
✓ Downloading aot-tools.dill... (0.2s)
✓ Extracting aot-tools.dill... (1.5s)
✓ Fetching apps (0.4s)
✓ Building app bundle with Flutter 3.24.1 (3f7041c5e9) (75.8s)
✓ Release version: 1.0.0+1 (1.3s)
✓ Fetching releases (0.4s)

🚀 Ready to create a new release!

📱 App: shorebird_test (ab486a37-ft3d-472d-l520-ba1h7e3c3801)
📦 Release Version: 1.0.0+1
🕹️  Platform: android
🐦 Flutter Version: 3.24.1 (3f7041c5e9)

Would you like to continue? (y/N) Yes
✓ Fetching releases (0.9s)
✓ Creating release (0.7s)
✓ Updating release status (0.3s)
✓ Creating artifacts (9.0s)
✓ Updating release status (1.8s)

✅ Published Release 1.0.0+1!
Your next step is to upload the app bundle to the Play Store:
/Users/christofer_henriksson/shorebird_test/build/app/outputs/bundle/release/app-release.aab

For information on uploading to the Play Store, see:
https://support.google.com/googleplay/android-developer/answer/9859152?hl=en

To create a patch for this release, run shorebird patch --platforms=android --release-version=1.0.0+1

Note: shorebird patch --platforms=android without the --release-version option will patch the current version of the app.
Release added to Shorebird console
  1. Installing and running the release shows the default counter example as expected.
The default Flutter counter example app
  1. Now let's make some small changes to the app.

Changing the colorScheme to green.

- colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
+ colorScheme: ColorScheme.fromSeed(seedColor: Colors.green),

Adding a decrement button

+  void _decrementCounter() {
+    if (_counter > 0) {
+      setState(() {
+        _counter--;
+      });
+    }
+  }
-      floatingActionButton: FloatingActionButton(
-        onPressed: _incrementCounter,
-        tooltip: 'Increment',
-        child: const Icon(Icons.add),
-      ),

+      floatingActionButton: Row(
+        mainAxisAlignment: MainAxisAlignment.end,
+        children: [
+          FloatingActionButton(
+            onPressed: _decrementCounter,
+            tooltip: 'Decrement',
+            child: const Icon(Icons.remove),
+          ),
+          const SizedBox(width: 8),
+          FloatingActionButton(
+            onPressed: _incrementCounter,
+            tooltip: 'Increment',
+            child: const Icon(Icons.add),
+          ),
+        ],
+      ),
  1. Next we will create the patch for the above changes with the shorebird patch command.
user@my-mac shorebird_test % shorebird patch android
✓ Fetching apps (0.5s)
✓ Fetching releases (0.3s)
Which release would you like to patch? 1.0.0+1
✓ Fetching aab artifact (0.3s)
✓ Downloading aab (2.2s)
✓ Building patch with Flutter 3.24.1 (3f7041c5e9) (41.2s)
✓ Verifying patch can be applied to release (28ms)
[WARN] Your app contains asset changes, which will not be included in the patch.
    Changed files:
        base/assets/flutter_assets/fonts/MaterialIcons-Regular.otf
Continue anyways? (y/N) Yes
✓ Fetching release artifacts (0.9s)
✓ Downloading release artifacts (4.0s)
✓ Creating patch artifacts (4.2s)

🚀 Ready to publish a new patch!

📱 App: shorebird_test (a1ac6a37-bc3d-459d-b820-bd1f4e3c5391)
📦 Release Version: 1.0.0+1
🕹️  Platform: android [arm32 (87.71 KB), arm64 (84.91 KB), x86_64 (89.81 KB)]
🟢 Track: Production

Would you like to continue? (y/N) Yes
✓ Creating patch (1.7s)
✓ Uploading artifacts (2.8s)
✓ Fetching channels (0.3s)
✓ Promoting patch to stable (0.3s)

✅ Published Patch 1!

The tool detected that we added a new Material icon that won't be included in the patch. For our demonstration we choose to continue anyways.

  1. Checking the Shorebird console we can see our first patch has been added.
Patch has been uploaded to Shorebird servers
  1. Restarting the app to download and apply the patch. After restarting the app we can confirm that the new changes have been remotely updated successfully.
Patched changes has been applied successfully

Note that the newly added button's icon is not showing. This is as expected since the Material icon asset is missing.

Limitations and considerations

  • Shorebird can only update Dart code. So native iOS (Objective-C/Swift) and Android (Java/Kotlin) code updates are not supported. For any native code changes like plugins we are still required to prepare a new release build as normal.

  • Currently assets like fonts or images are not supported but are planned to be added. Also some care needs to be considered when changing icons. Since icon assets are tree-shaken when the app is built, you can't patch an app to use a new icon that is not already used somewhere in your app.

  • For now Shorebird only supports Flutter mobile apps (iOS/Android). But Flutter desktop app support is also planned to be added later.

  • Shorebird is not a replacement for existing app stores or other side loading solutions. It is only a tool for making code updates more convenient. You still need to have the app released to your users through an app store or other distribution method.

  • Since new updates need to be downloaded from the Shorebird backend, apps that are exclusively offline are not supported. In fact the shorebird init command will add the required internet permissions to the Android manifest if it's missing.

  • Flutter versions cannot be updated through Shorebird. For example an app released using Flutter 3.24 cannot be patched to use another version of Flutter. Conversely, since Shorebird is using a customized version of Flutter, there might be a small delay until a new Flutter version has been prepared for Shorebird.

  • Both App Store and Play Console have both technical and policy rules that limit what a remote update is allowed to contain. Shorebird is built to comply with the technical limitations, but for policy rules it's up to the developers to make sure they are not broken. For example we are not allowed to "engage in deceptive behavior" via pushed updates. Like changing the original purpose of the app. Failing to follow the content policies can result in both your Shorebird account and developer account being terminated. More details can be found at the Shorebird’s Q&A here.

For more information I recommend checking out the official documentation and the helpful Discord server.

fluttershorebirdmobile appscode push

Author

Christofer Henriksson

Christofer Henriksson

Mobile Tech Lead

Flutter enthusiast

You may also like

May 27, 2024

Introducing UCL Max AltPlay, a turn-by-turn real-time Football simulation

At this year's MonstarHacks, our goal was to elevate the sports experience to the next level with cutting-edge AI and machine learning technologies. With that in mind, we designed a unique solution for football fans that will open up new dimensions for wa...

Rayhan NabiRokon UddinArman Morshed

Rayhan Nabi, Rokon Uddin, Arman Morshed

MonstarHacks

May 23, 2024

Agorametrics: Data democratisation from Sports Science for the benefit of all

As part of Monstarlab's 4th edition of the internal hackathon, MonstarHacks, the theme was to leverage cutting-edge technologies to innovate within the sports industry by developing solutions that enhance fan engagement, optimise athletic performance, and...

Ross DavidsonGraham Campbell

Ross Davidson, Graham Campbell

MonstarHacks

ServicesCasesAbout Us
CareersThought LeadershipContact
© 2022 Monstarlab
Information Security PolicyPrivacy PolicyTerms of Service