Can't disable OTA updates on Android for detached Expokit app

Basically having the same problem as Disabling over the air updates for expokit apps(expo detached app). I have a React Native detached Expokit app using Expo SDK 32. We are building binaries on both iOS and Android. I have set expo.updates.enabled:false in app.json, but the Android build still picks up OTA updates whereas the iOS build does not.

Yes, I did re-build the APK and do a clean install of that APK after setting enabled:false but it still picked up the JS bundle from the build that came after it.

Advice on how to disable OTA updates on detached Android would be appreciated. Would rather not have to use the workaround of publishing to a different release channel for each build. Thanks.

Hey @terri,

Sorry to hear youā€™re running into this. Can you let me know what SDK version you are using?

Also, can you take a look at the ExpoKit note under this section of the docs? It may be whatā€™s going on here.

Cheers,
Adam

Hi Adam, Iā€™m running SDK 32.
I totally missed seeing this note though:
ExpoKit : To change the value of enabled , edit ios/<PROJECT-NAME>/Supporting/EXShell.plist and android/app/src/main/java/host/exp/exponent/generated/AppConstants.java . All other properties are set at runtime.

Thank you for pointing it out. I had only set it in app.json. Let me try that and see if it works!

@adamjnav,

Iā€™m guessing that for AppConstants.java, I need to set this line:
public static boolean ARE_REMOTE_UPDATES_ENABLED = false;

But for EXShell.plist, Iā€™m not sure what key to set. Here is my EXShell.plist below. Could you please advise on what key to set? thx

<dict>
	<key>isManifestVerificationBypassed</key>
	<true/>
	<key>isShell</key>
	<true/>
	<key>manifestUrl</key>
	<string>exp://exp.host/@ourUsername/ourProjectName</string>
	<key>releaseChannel</key>
	<string>default</string>
</dict>

Hello @adamjnav. I set
public static boolean ARE_REMOTE_UPDATES_ENABLED = false;
in AppConstants.java and did a build, but now the app will not launch. I get this exception

Uncaught Error: java.lang.Exception: Could not load embedded manifest. Are you sure this experience has been published?

So I would much appreciate advice on what to update in AppConstants.java as well as EXShell.plist. (Frankly Iā€™m not too worried about EXShell.plist because my iOS builds do not pick up OTA updates)

I was having the same problem and I saw your answer and solved it. Thank you. The problem is you have to run ā€˜expo publishā€™ at least once before you make the APK.

I donā€™t know how to change the iOS file.

Thanks @taeeh but I already run expo publish before each build. So not sure what else is wrong in my configuration.

Iā€™m still stuck on this problem and would appreciate help very much. Could the Expo team please provide more detail in https://docs.expo.io/versions/v32.0.0/workflow/configuration/#updates on how to update AppConstants.java?

Hereā€™s my app.json

{
  "expo": {
    "name": "FluAtHome",
    "version": "0.3.0",
    "description": "App for flu@home project",
    "icon": "./assets/images/app-icon.png",
    "slug": "FluAtHomeAU",
    "sdkVersion": "32.0.0",
    "updates": {
      "enabled": false
    },
    "ios": {
      "bundleIdentifier": "org.auderenow.fluathome-au",
      "buildNumber": "1",
      "supportsTablet": false,
      "isTabletOnly": false,
      "config": {
        "usesNonExemptEncryption": false
      },
      "publishBundlePath": "ios/fluathome/Supporting/shell-app.bundle",
      "publishManifestPath": "ios/fluathome/Supporting/shell-app-manifest.json"
    },
    "android": {
      "package": "org.auderenow.fluathome_au",
      "publishBundlePath": "android/app/src/main/assets/shell-app.bundle",
      "publishManifestPath": "android/app/src/main/assets/shell-app-manifest.json"
    },
    "androidStatusBar": {
      "backgroundColor": "#ffffff"
    },
    "assetBundlePatterns": ["assets/images/*"],
    "orientation": "portrait",
    "isDetached": true,
    "detach": {
      "iosExpoViewUrl": "https://s3.amazonaws.com/exp-exponent-view-code/ios-v2.9.0-sdk31.0.0-250a3991-b623-4f9c-b07f-0b9ed7e8c4c9.tar.gz",
      "androidExpoViewUrl": "https://s3.amazonaws.com/exp-exponent-view-code/android-v2.9.2-sdk31.0.0-d1776f37-d524-4fee-872d-6807b0fd83ff.tar.gz"
    },
    "scheme": "expdcd6f73fcd53486284683e2a09a2d545"
  }
}

and this is my AppConstants.java

package host.exp.exponent.generated;

import com.facebook.common.internal.DoNotStrip;

import java.util.ArrayList;
import java.util.List;

import host.exp.exponent.BuildConfig;
import host.exp.exponent.Constants;

@DoNotStrip
public class AppConstants {

  public static final String VERSION_NAME = "2.9.2";
  public static String INITIAL_URL = "exp://exp.host/@audere/FluAtHomeAU";
  public static final boolean IS_DETACHED = true;
  public static final String SHELL_APP_SCHEME = "expdcd6f73fcd53486284683e2a09a2d545";
  public static final String RELEASE_CHANNEL = "default";
  public static boolean SHOW_LOADING_VIEW_IN_SHELL_APP = false;
  public static boolean ARE_REMOTE_UPDATES_ENABLED = true;
  public static final List<Constants.EmbeddedResponse> EMBEDDED_RESPONSES;
  public static boolean FCM_ENABLED = false;

  static {
    List<Constants.EmbeddedResponse> embeddedResponses = new ArrayList<>();

        // ADD EMBEDDED RESPONSES HERE
        // START EMBEDDED RESPONSES
        embeddedResponses.add(new Constants.EmbeddedResponse("https://exp.host/@audere/FluAtHomeAU", "assets://shell-app-manifest.json", "application/json"));
        embeddedResponses.add(new Constants.EmbeddedResponse("https://d1wp6m56sqw74a.cloudfront.net/%40audere%2FFluAtHomeAU%2F0.3.0%2F3d2736f22d04260cfded31c8dc9ee245-32.0.0-android.js", "assets://shell-app.bundle", "application/javascript"));
        // END EMBEDDED RESPONSES
    EMBEDDED_RESPONSES = embeddedResponses;
  }

  // Called from expoview/Constants
  public static Constants.ExpoViewAppConstants get() {
    Constants.ExpoViewAppConstants constants = new Constants.ExpoViewAppConstants();
    constants.VERSION_NAME = VERSION_NAME;
    constants.INITIAL_URL = INITIAL_URL;
    constants.IS_DETACHED = IS_DETACHED;
    constants.SHELL_APP_SCHEME = SHELL_APP_SCHEME;
    constants.RELEASE_CHANNEL = RELEASE_CHANNEL;
    constants.SHOW_LOADING_VIEW_IN_SHELL_APP = SHOW_LOADING_VIEW_IN_SHELL_APP;
    constants.ARE_REMOTE_UPDATES_ENABLED = ARE_REMOTE_UPDATES_ENABLED;
    constants.EMBEDDED_RESPONSES = EMBEDDED_RESPONSES;
    constants.ANDROID_VERSION_CODE = BuildConfig.VERSION_CODE;
    constants.FCM_ENABLED = FCM_ENABLED;
    return constants;
  }
}

With this current setting, the Android build picks up OTA updates.
If I change ARE_REMOTE_UPDATES_ENABLED=false then do a new build (which includes expo publish) then the app shows the ā€œCould not load embedded manifestā€ error as mentioned above.

I have the same question about the iOS key to enable remote updatesā€¦ did you know what key name to use?

Sorry @joeb I do not know how to enable remote updates on iOS.

Thanks for responding @terri. I decided to call Updates.checkForUpdateAsync() on the most active screen in my app. Iā€™m checking in componentDidMount(). If an update is available, I prompt asking if the user wants to install the update, then call Updates.reload(). The settings in app.json and EXShell.plist are set to default. This is a manual method which works on iOS and Android.

I am using react-navigation. I also added a checkForUpdateAsync() call in the NavigationEvents onDidFocus() handler. The application can now be updated OTA.

@adamjnav I need your solution. How setting ios in EXShell.plist

@taeeh- The key you want to set in EXShell.plist is:

<key>areRemoteUpdatesEnabled</key>
	<false/>

I was desperate for it. @charliecruzan Thank you very much.

1 Like

Hello, I have a question

If I disable areRemoteUpdatesEnabled for iOS and Android - is it possible to install updates using Updates call?