How devices get patches
You published a patch and want to know when a device will run it, or you’re writing code that checks for patches yourself. This page covers what the Shorebird updater in your app does on a device. If a patch isn’t arriving, read the device’s logs first: see Read device logs.
From publish to running
Section titled “From publish to running”- The app’s process starts (a cold start). It runs the patch already installed on the device, or the release’s own code if there isn’t one.
- Once the app is running, the updater checks Shorebird for the newest patch on
the
stabletrack for this release, on a background thread, so launch isn’t delayed. - If there’s a patch the device doesn’t have, the updater downloads it, checks it, and installs it on disk.
- The next time the process starts, the app runs the new patch.
So a device runs a new patch on the launch after the one that downloaded it. A patch is never swapped into an app that is already running.
When the automatic check runs
Section titled “When the automatic check runs”The updater checks once each time the app’s process starts. It doesn’t check again while the process is alive, and it doesn’t check when the app comes back from the background. Mobile operating systems end background apps often, so most users start a fresh process regularly. An app whose process stays alive, for example because of a foreground service, checks only when that process restarts; see the foreground service case in Patch not showing up.
The automatic check always asks for the stable track, except in a build
installed with shorebird preview --track, which checks the previewed track. To
use another track, see
Tracks.
The check can also tell the device that a patch was rolled back. The device removes that patch, and the next launch runs the previous patch or the release. See Roll back a patch.
To check at other times, such as when the app resumes or when a push
notification arrives, call package:shorebird_code_push from your code, as
described below.
Turning off the automatic check
Section titled “Turning off the automatic check”With auto_update: false in
shorebird.yaml, the app doesn’t check on launch. The device log shows:
The app still runs the patch already installed on the device. It doesn’t
download new patches or learn about rollbacks until your code calls
checkForUpdate() or update(). Read the caution in
Update strategies before you turn it
off.
Check for patches from your code
Section titled “Check for patches from your code”Add
package:shorebird_code_push to
your app with flutter pub add shorebird_code_push. This example checks the
stable track once the first frame is on its way, and downloads a new patch if
there is one:
To check a track other than stable, pass the same track to both calls, for
example checkForUpdate(track: UpdateTrack.beta) and
update(track: UpdateTrack.beta). See
Tracks. To run a
downloaded patch without waiting for the next launch, see
Restarting after an update.
The rest of this section describes shorebird_code_push 2.0.6 and newer.
What each call returns
Section titled “What each call returns”| Call | Returns |
|---|---|
isAvailable | false when the build doesn’t contain the updater: a debug or profile build, flutter run, a build made with flutter build rather than shorebird release or shorebird preview, or the web. Every other call then returns at once. |
checkForUpdate({track}) | An UpdateStatus (below). A check that fails, for example because the device is offline, doesn’t throw: it returns as if there were no new patch. |
update({track}) | Completes normally when it installs a patch, when there’s no newer patch, and when another update is already running. Throws UpdateException when the update fails (below). |
readCurrentPatch() | The patch this launch is running, or null for the release’s own code. If the updater can’t read its state, it logs the error and returns null. |
readNextPatch() | The patch the next launch will run, or null for the release’s own code. It’s the same as readCurrentPatch() until a new patch downloads or the running patch is rolled back. |
update() completing normally doesn’t mean a patch was installed. When the
automatic check is already downloading a patch, update() returns at once and
the download carries on. To find out whether a patch is waiting for the next
launch, compare readNextPatch() with readCurrentPatch().
Update statuses
Section titled “Update statuses”UpdateStatus | Meaning |
|---|---|
upToDate | There’s no newer patch on the track for this device to download, and nothing is waiting for a restart. |
outdated | The track has a patch this device hasn’t downloaded. Call update() to download it. |
restartRequired | The patch the next launch will run differs from the one running now: a new patch has downloaded, or the running patch was rolled back. Rollbacks report restartRequired on releases built with Flutter 3.41.9 and newer. |
unavailable | The build doesn’t contain the updater (see isAvailable). |
A patch this device has marked bad (see
Failed and rolled-back patches) isn’t
reported as outdated.
When update() throws
Section titled “When update() throws”update() throws an UpdateException. Its message says what went wrong, and
its reason is one of:
installFailed: the newest patch on the track is one this device has marked bad, so the device won’t install it. The message isUpdate available but previously failed to install. Not installing.unknown: any other failure, such as a patch check or download that couldn’t reach Shorebird, a refused patch check (for exampleRequest failed with status: 403when your organization reached its patch install limit), or a downloaded patch that failed its checks. The device tries again on the next check, except for a patch it has marked bad.
UpdateFailureReason also has noUpdate and downloadFailed, but 2.0.6 and
newer don’t throw them.
Failed and rolled-back patches
Section titled “Failed and rolled-back patches”- The download fails, for example because the device went offline: nothing changes on the device, and it tries again on the next check.
- The patch downloads but fails its checks, for example because the release’s build on the device isn’t the one Shorebird has (see Patches can’t install because the app isn’t the build Shorebird released). On releases built with Flutter 3.41.9 and newer, the device marks the patch bad and never tries it again. On older Flutter versions, it downloads the patch again on every check.
- The patch fails to load, including when the app’s process ends while the engine is still loading it: the device marks the patch bad and goes back to the previous patch or the release. Which Flutter versions do this, and what the app runs on that launch, is in Patch integrity and automatic rollback.
- You roll the patch back: devices remove it on their next check and run the previous patch, or the release, from the launch after that. See Roll back a patch.
A patch marked bad is bad only on that device, and only that patch number. Fix the problem and publish a new patch; devices install it as usual. Roll the bad patch back so devices that haven’t tried it yet don’t download it.