Skip to content

Code Push for Android add-to-app

This guide explains how to use Shorebird in an Android add-to-app scenario (that is, your app embeds Flutter UI in non-Flutter UI). If you are new to this pattern, see the Add Flutter to an existing app Flutter Concepts article first.

This guide assumes you already have an Android app and a Flutter module. The Android app will be named AddToAppDemo (in the sample’s AndroidAddToAppDemo directory) and the Flutter module will be named my_flutter_module.

This guide also assumes that you have created a Shorebird account. If you have not, see the Code Push guide for instructions.

The reference code for this guide is available at https://github.com/shorebirdtech/samples/tree/main/add_to_app.

First, run shorebird init in your Flutter module:

shorebird init

Create a Shorebird release for your Flutter module:

shorebird release aar --release-version 1.2.3+1

The release-version parameter needs to match the version of the Android app that uses this module (i.e., versionName+versionCode from the app’s app/build.gradle file).

Update your Android app to use the download.shorebird.dev Maven repository

Section titled “Update your Android app to use the download.shorebird.dev Maven repository”

In settings.gradle:

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
+        maven {
+           // This is a relative path from this settings.gradle file to the
+           // my_flutter_module/release directory.
+           url '../my_flutter_module/release'
+       }
+       maven {
-           url 'https://storage.googleapis.com/download.flutter.io'
+           url 'https://download.shorebird.dev/download.flutter.io'
+      }
    }
}

Update your Android app to use this version of the Flutter module

Section titled “Update your Android app to use this version of the Flutter module”

In app/build.gradle, add the following:

buildTypes {
    release {
        // ...
+        // libapp.so in the Flutter module's AAR is already stripped (by the Dart
+        // compiler before Flutter 3.44, by the module's own Android Gradle Plugin
+        // build from 3.44 on). Running llvm-strip on it again in this app can
+        // change its bytes, which confuses Shorebird tools. This line tells Gradle
+        // to skip that step for libapp.so, so the libapp.so Shorebird recorded is
+        // byte-identical to the one in your APK/AAB.
+        packaging.jniLibs.keepDebugSymbols.add("**/libapp.so")
        // ...
    }
}

dependencies {
    // ...
+    releaseImplementation 'com.example.my_flutter_module:flutter_release:1.0'
    // ...
}

Keep the keepDebugSymbols line on every Flutter version. The Flutter 3.44 advice to remove it is for a Flutter app’s android/app/build.gradle, not for your host app’s app/build.gradle.

In Android Studio, update the active build variant to release and run your app. Your app should work as before with no differences.

To set the active build variant to release, click on the “Build Variants” tab in the lower left corner of Android Studio. Then select “release” from the “Active Build Variant” dropdown.

Android Studio build variant set to release

Attempting to build with a non-release build variant will not be able to resolve Flutter symbols in your app.

This step isn’t covered in detail here, but this is where you would submit your app to the Play Store. For Code Push to work, it is important that you submit with the same aar generated by the release command above.

Verify that Shorebird is working with a patch

Section titled “Verify that Shorebird is working with a patch”

Make an edit to the code in your Flutter module. Then run:

shorebird patch aar --release-version 1.2.3+1

As with the release command, the release version should be the version of the Android app that uses this module.

Now relaunch the app, navigate to the Flutter screen, and verify that the patch is recognized and applied. In logcat, you should see output like the following:

[INFO:shorebird.cc(109)] Shorebird updater: no active patch.
[INFO:shorebird.cc(113)] Starting Shorebird update
updater::network: [shorebird] Sending patch check request: app_id: baad0583-6810-44a7-9034-6aadb8127f29, channel: stable, release_version: 1.0.0+8, platform: android, arch: aarch64, current_patch_number: None
updater::updater: [shorebird] Patch 1 successfully downloaded. It will be launched when the app next restarts.
updater::updater: [shorebird] Update thread finished with status: Update installed

To try a patch in a host app you build yourself before your users get it, see Test an add-to-app patch before publishing it.

To give QA a build of your host app that gets patches before your users do, see Give QA an add-to-app build, then promote it.

If your host app starts the module through more than one Dart entrypoint or engine, see Multiple Dart entrypoints and engines.