Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I force an expo app to update

I have an app written in expo, and can't figure out how to push a new build. On the expo site if I run the app from the QR code the app is correct, but the native app from the app store doesn't update.

The steps I've been using are 1) exp build:android 2) exp publish

How do I make the app actually update?

like image 753
Joel Jackson Avatar asked Jul 03 '18 06:07

Joel Jackson


People also ask

How do I update the Expo app on Google Play?

If you haven't disabled OTA updates for your app you should be able to push an update to the existing app using expo publish command. Just run it in the directory of your project—the project will be built, uploaded to the servers and next time the app starts it will download the update.

Should I eject my Expo app?

You should not eject if:All you need is to distribute your app in the iTunes Store or Google Play. Expo can build binaries for you in that case. If you eject, we can't automatically build for you any more. You are uncomfortable writing native code.


2 Answers

TL;DR: OTA updates are enforced by default. App Store updates can be enforced by adding code to check your app version on startup and, if there's a new version, open the App Store on your app's page.

There's two ways of updating a standalone Expo app:

  1. OTA update using expo-cli publish
  2. Using Google Play/App Store

Both of these methods have advantages and shortcomings.

OTA Updates

This is the usual way an update is delivered to Expo apps. OTAs are done via the expo CLI tool and deliver new Javascript code based on your package.json settings. This option also offers the option to publish code using release channels, meaning you could push updates first to you staging environment, validate the update and then push it to production via CLI like so:

expo-cli publish -release-channel staging # pushes and update to the staging channel
expo-cli publish -release-channel production # pushes an update to the production channel

If you are publishing but your standalone app is not updating you might be pushing code to the wrong release channel. You can read more about release channels here.

OTAs are enforced by default:

By default, Expo will check for updates automatically when your app is launched and will try to fetch the latest published version. If a new bundle is available, Expo will attempt to download it before launching the experience.

However it's possible to disable this behavior by setting updates.enabled to false in app.json and then implement your own logic (or none at all), as per the example in their docs:

try {
  const update = await Expo.Updates.checkForUpdateAsync();
  if (update.isAvailable) {
    await Expo.Updates.fetchUpdateAsync();
    // ... notify user of update ...
    Expo.Updates.reloadFromCache();
  }
} catch (e) {
  // handle or log error
}

This system is really great for pushing new JS code to your users, it really helps with live testing since you can test your app with your user, find a flaw, fix it and publish new code which will be almost instantly available for download.

Yet this method has its limitations, for example: you can't update the Expo SDK version this way, you must build a new standalone app and distribute it through the app store (or whatever other method of your choosing).

App Stores

This is the most common way to distribute your .apk and .ipa files. These files can be created by using the expo-cli build:android and expo-cli build:ios for Android and iOS respectively.

It seems like there's an Android API being tested to enforce apps to be updated via this method (SO thread, article), but I don't think it's available yet.

One possible solution to enforce updates via this method is to check your app version on startup and, if there's a new version available in the store, open the app's store page via deep linking so the user is able download it. The example below should help you visualize what I mean.

componentDidMount {
   const hasNewVersion = isStoreUpdateAvailable(); // Checks the store for a new app update
   if (hasNewVersion) {
     Linking.openURL("market://details?id=<>"); // Opens the app's store page so the user can download the update
   }
}

Here's the docs about linking to Google Play.

Hope this answers all your questions, if not leave a comment and I'll edit the answer.

like image 70
Bruno Eduardo Avatar answered Sep 18 '22 17:09

Bruno Eduardo


UPDATED ANSWER

Since the accepted answer was posted, Expo made changes to the [Updates API][1].

Here's the breaking change.

Updates.reloadFromCache has been renamed to Updates.reloadAsync, and Updates.reload has been removed.

  import * as Updates from 'expo-updates' // Updates*

  try {
    const update = await Updates.checkForUpdateAsync()
    if (update.isAvailable) {
      await Updates.fetchUpdateAsync()
      // NOTIFY USER HERE
      Updates.reloadAsync()
    }
  } catch (e) {
      // HANDLE ERROR HERE
  }

For those wondering where to run this code, I advise to insert it in the componentDidMount/useEffect() method. [1]: https://docs.expo.io/guides/configuring-ota-updates/

like image 35
Gilson Viana Avatar answered Sep 20 '22 17:09

Gilson Viana