Android Expo Updates Issues

We’ve been building a bare workflow app for release and have faced some issues with expo-updates@0.2.2 and assets management on Android.

Runtime Version
The first weird thing was that in the docs it specified that runtimeVersion should be an “An object with keys ios and android whose corresponding values are the runtime version this update is compatible with.”

So, in our app.json we had something like this:

"runtimeVersion": {
   "ios": "1",
   "android": "1"
}

Having the json structured this way made expo-updates consistently fail to find the update on android (Updates.manifest = {}), and we had an error in cli saying that runtimeVersion should be a string.

When we set "runtimeVersion": "1" and Updates.manifest started to be populated again.

We had a look into the expo-updates Android code and found out that there are 3 types of manifest; bare, legacy and new (expo-cli@3.20.9).

The manifest we generate seems to match the legacyManifest, in fact in the function that parses the json it tries to handle both string and object for runtimeVersion. Code for this is here:

if (runtimeVersionObject != null) {
      if (runtimeVersionObject instanceof String) {
        runtimeVersion = (String)runtimeVersionObject;
      } else if (runtimeVersionObject instanceof JSONObject) {
        runtimeVersion = ((JSONObject)runtimeVersionObject).optString(“android”, runtimeVersion);
      }
    }

But it also seems that a legacyManifest should match this config:

expo.modules.updates.EXPO_LEGACY_MANIFEST

Questions

  1. However we do not set this parameter, so how does this work?
  2. Why don’t we have a bareManifest, when in a bare workflow?

assetUrlOverride Not Constructed Correctly

With the above fix and the manifest being parsed correctly, the update still fails due to wrong asset urls when using assetUrlOverride to set an absolute path for the assets. With this our hosted android-index.json would contain:

"assetUrlOverride": "https://xxx.cloudfront.net/yyy/3dd28fbbf/native/bare/assets",

This has always worked fine for iOS, however on android the update fails because it looks for assets and appends assetUrlOverride to the updates host url. We are setting the EXPO_UPDATE_URL with:

 <meta-data android:name=“expo.modules.updates.EXPO_UPDATE_URL” android:value=“https://xxx.com/pocket/jkTTiukljhe12kl2sF2d3/android-index.json” />

This results in something like:

https://xxx.com/pocket/jkTTiukljhe12kl2sF2d3/https%3A%2F%2Fxxx.cloudfront.net%yyy%2F055d780a0%2Fnative%2Fbare%2Fassets/0ec7d3a4f6643fca50b88f4e2efd5898

We also noticed the URL is only partially encoded.

To resolve this issue we have patched this code.

  1. In order to have the builder to get instantiated as empty: Uri.Builder assetsBaseUrlBuilder = new Uri.Builder();
  2. Properly handle the encoded path: assetsBaseUrlBuilder.encodedPath(assetsPath);

The resulting code looks like:

if (mAssetsUrlBase == null) {
          // use manifest url as the base
          String assetsPath = getRawManifestJson().optString("assetUrlOverride", "assets");
          Uri.Builder assetsBaseUrlBuilder = new Uri.Builder();
          List<String> segments = manifestUrl.getPathSegments();
          assetsBaseUrlBuilder.path("");
          for (int i = 0; i < segments.size() - 1; i++) {
            assetsBaseUrlBuilder.appendPath(segments.get(i));
          }
          assetsBaseUrlBuilder.encodedPath(assetsPath);
          mAssetsUrlBase = assetsBaseUrlBuilder.build();
        }

Questions
3. How is this intended to work?

With all of the above we now have expo-updates working on Android, hosted on our own server with an assetUrlOverride set. Has anyone else managed to get this working without the above?

3 Likes

Yes, it’s a bug for sure, please see the attached screenshot of the network traffic generated by Android App.

@notbrent do you recommend the above fix so we can use this fix till the proper fix get released?

@mdcuk34 I have applied your fix and it’s working fine :slight_smile: Also network requests goes to the right place.

2 Likes