expo-updates 0.27.3 → 0.27.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -10,6 +10,12 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 0.27.4 — 2025-03-18
14
+
15
+ ### 🎉 New features
16
+
17
+ - Support brownfield apps with EX_UPDATES_CUSTOM_INIT flag. ([#35391](https://github.com/expo/expo/pull/35391) by [@douglowder](https://github.com/douglowder))
18
+
13
19
  ## 0.27.3 — 2025-03-11
14
20
 
15
21
  ### 🐛 Bug fixes
@@ -16,7 +16,7 @@ apply plugin: 'com.android.library'
16
16
  apply plugin: 'com.google.devtools.ksp'
17
17
 
18
18
  group = 'host.exp.exponent'
19
- version = '0.27.3'
19
+ version = '0.27.4'
20
20
 
21
21
  def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
22
22
  apply from: expoModulesCorePlugin
@@ -49,6 +49,10 @@ def getBoolStringFromPropOrEnv(String name, Boolean defaultValue) {
49
49
  // debug builds. (default false)
50
50
  def exUpdatesNativeDebug = getBoolStringFromPropOrEnv("EX_UPDATES_NATIVE_DEBUG", false)
51
51
 
52
+ // If true, app is using custom code to initialize expo-updates, so default initialization code
53
+ // will be disabled.
54
+ def exUpdatesCustomInit = getBoolStringFromPropOrEnv("EX_UPDATES_CUSTOM_INIT", false)
55
+
52
56
  // If true, code will run that delays app loading until updates is initialized, to prevent ANR issues.
53
57
  // (default true)
54
58
  def exUpdatesAndroidDelayLoadApp = getBoolStringFromPropOrEnv("EX_UPDATES_ANDROID_DELAY_LOAD_APP", true)
@@ -63,11 +67,12 @@ android {
63
67
  namespace "expo.modules.updates"
64
68
  defaultConfig {
65
69
  versionCode 31
66
- versionName '0.27.3'
70
+ versionName '0.27.4'
67
71
  consumerProguardFiles("proguard-rules.pro")
68
72
  testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
69
73
 
70
74
  buildConfigField("boolean", "EX_UPDATES_NATIVE_DEBUG", exUpdatesNativeDebug)
75
+ buildConfigField("boolean", "EX_UPDATES_CUSTOM_INIT", exUpdatesCustomInit)
71
76
  buildConfigField("boolean", "EX_UPDATES_ANDROID_DELAY_LOAD_APP", exUpdatesAndroidDelayLoadApp)
72
77
  buildConfigField("boolean", "USE_DEV_CLIENT", useDevClient.toString())
73
78
  }
@@ -108,7 +108,7 @@ interface IUpdatesController {
108
108
  this["runtimeVersion"] = runtimeVersion ?: ""
109
109
  this["checkAutomatically"] = checkOnLaunch.toJSString()
110
110
  this["channel"] = requestHeaders["expo-channel-name"] ?: ""
111
- this["shouldDeferToNativeForAPIMethodAvailabilityInDevelopment"] = shouldDeferToNativeForAPIMethodAvailabilityInDevelopment || BuildConfig.EX_UPDATES_NATIVE_DEBUG
111
+ this["shouldDeferToNativeForAPIMethodAvailabilityInDevelopment"] = shouldDeferToNativeForAPIMethodAvailabilityInDevelopment || UpdatesPackage.isUsingNativeDebug
112
112
  this["initialContext"] = initialContext.bundle
113
113
 
114
114
  if (launchedUpdate != null) {
@@ -33,7 +33,7 @@ class UpdatesController {
33
33
  return
34
34
  }
35
35
  val useDeveloperSupport = (context as? ReactApplication)?.reactNativeHost?.useDeveloperSupport ?: false
36
- if (useDeveloperSupport && !BuildConfig.EX_UPDATES_NATIVE_DEBUG) {
36
+ if (useDeveloperSupport && !UpdatesPackage.isUsingNativeDebug) {
37
37
  if (BuildConfig.USE_DEV_CLIENT) {
38
38
  val devLauncherController = initializeAsDevLauncherWithoutStarting(context)
39
39
  singletonInstance = devLauncherController
@@ -22,7 +22,6 @@ import kotlinx.coroutines.withContext
22
22
  * applicable environments.
23
23
  */
24
24
  class UpdatesPackage : Package {
25
- private val useNativeDebug = BuildConfig.EX_UPDATES_NATIVE_DEBUG
26
25
 
27
26
  override fun createReactNativeHostHandlers(context: Context): List<ReactNativeHostHandler> {
28
27
  val handler: ReactNativeHostHandler = object : ReactNativeHostHandler {
@@ -57,12 +56,12 @@ class UpdatesPackage : Package {
57
56
  override fun createReactActivityHandlers(activityContext: Context): List<ReactActivityHandler> {
58
57
  val handler = object : ReactActivityHandler {
59
58
  override fun getDelayLoadAppHandler(activity: ReactActivity, reactNativeHost: ReactNativeHost): ReactActivityHandler.DelayLoadAppHandler? {
60
- if (!BuildConfig.EX_UPDATES_ANDROID_DELAY_LOAD_APP) {
59
+ if (!BuildConfig.EX_UPDATES_ANDROID_DELAY_LOAD_APP || isUsingCustomInit) {
61
60
  return null
62
61
  }
63
62
  val context = activity.applicationContext
64
63
  val useDeveloperSupport = reactNativeHost.useDeveloperSupport
65
- if (!useDeveloperSupport || BuildConfig.EX_UPDATES_NATIVE_DEBUG) {
64
+ if (!useDeveloperSupport || isUsingNativeDebug) {
66
65
  return ReactActivityHandler.DelayLoadAppHandler { whenReadyRunnable ->
67
66
  CoroutineScope(Dispatchers.IO).launch {
68
67
  startUpdatesController(context)
@@ -76,9 +75,11 @@ class UpdatesPackage : Package {
76
75
  @WorkerThread
77
76
  private suspend fun startUpdatesController(context: Context) {
78
77
  withContext(Dispatchers.IO) {
79
- UpdatesController.initialize(context)
80
- // Call the synchronous `launchAssetFile()` function to wait for updates ready
81
- UpdatesController.instance.launchAssetFile
78
+ if (!UpdatesPackage.isUsingCustomInit) {
79
+ UpdatesController.initialize(context)
80
+ // Call the synchronous `launchAssetFile()` function to wait for updates ready
81
+ UpdatesController.instance.launchAssetFile
82
+ }
82
83
  }
83
84
  }
84
85
 
@@ -119,5 +120,7 @@ class UpdatesPackage : Package {
119
120
 
120
121
  companion object {
121
122
  private val TAG = UpdatesPackage::class.java.simpleName
123
+ val isUsingNativeDebug = BuildConfig.EX_UPDATES_NATIVE_DEBUG
124
+ internal val isUsingCustomInit = BuildConfig.EX_UPDATES_CUSTOM_INIT
122
125
  }
123
126
  }
@@ -24,9 +24,6 @@
24
24
  },
25
25
  "updates_testing_debug": {
26
26
  "extends": "base",
27
- "env": {
28
- "EX_UPDATES_NATIVE_DEBUG": "1"
29
- },
30
27
  "android": {
31
28
  "applicationArchivePath": "eas.json",
32
29
  "gradleCommand": ":app:assembleDebug :app:assembleAndroidTest -DtestBuildType=debug",
@@ -42,9 +39,6 @@
42
39
  },
43
40
  "updates_testing_release": {
44
41
  "extends": "base",
45
- "env": {
46
- "EX_UPDATES_NATIVE_DEBUG": "1"
47
- },
48
42
  "android": {
49
43
  "gradleCommand": ":app:assembleRelease :app:assembleAndroidTest -DtestBuildType=release",
50
44
  "withoutCredentials": true
@@ -757,7 +757,6 @@ export async function initAsync(
757
757
  await spawnAsync(localCliBin, ['prebuild', '--no-install', '--template', localTemplatePathName], {
758
758
  env: {
759
759
  ...process.env,
760
- EX_UPDATES_NATIVE_DEBUG: '1',
761
760
  EXPO_DEBUG: '1',
762
761
  CI: '1',
763
762
  },
@@ -784,7 +783,7 @@ export async function initAsync(
784
783
  // enable proguard on Android
785
784
  await fs.appendFile(
786
785
  path.join(projectRoot, 'android', 'gradle.properties'),
787
- '\nandroid.enableProguardInReleaseBuilds=true\nEXPO_UPDATES_NATIVE_DEBUG=true',
786
+ '\nandroid.enableProguardInReleaseBuilds=true\nEX_UPDATES_NATIVE_DEBUG=true',
788
787
  'utf-8'
789
788
  );
790
789
 
@@ -804,6 +803,18 @@ export async function initAsync(
804
803
  ].join('\n'),
805
804
  'utf-8'
806
805
  );
806
+
807
+ // Add native debug to iOS Podfile.properties.json
808
+ const podfilePropertiesJsonPath = path.join(projectRoot, 'ios', 'Podfile.properties.json');
809
+ const podfilePropertiesJsonString = await fs.readFile(podfilePropertiesJsonPath, {
810
+ encoding: 'utf-8',
811
+ });
812
+ const podfilePropertiesJson: any = JSON.parse(podfilePropertiesJsonString);
813
+ podfilePropertiesJson.updatesNativeDebug = 'true';
814
+ await fs.writeFile(podfilePropertiesJsonPath, JSON.stringify(podfilePropertiesJson, null, 2), {
815
+ encoding: 'utf-8',
816
+ });
817
+
807
818
  await fs.appendFile(
808
819
  path.join(projectRoot, 'android', 'app', 'build.gradle'),
809
820
  [
@@ -16,6 +16,7 @@ import org.slf4j.LoggerFactory
16
16
  import java.io.ByteArrayOutputStream
17
17
  import java.io.File
18
18
  import java.util.Locale
19
+ import java.util.Properties
19
20
 
20
21
  abstract class ExpoUpdatesPlugin : Plugin<Project> {
21
22
  override fun apply(project: Project) {
@@ -26,7 +27,7 @@ abstract class ExpoUpdatesPlugin : Plugin<Project> {
26
27
  val entryFile = detectedEntryFile(reactExtension)
27
28
  val androidComponents = project.extensions.getByType(AndroidComponentsExtension::class.java)
28
29
 
29
- if (System.getenv("EX_UPDATES_NATIVE_DEBUG") == "1") {
30
+ if (isNativeDebuggingEnabled(project)) {
30
31
  logger.warn("Disable all react.debuggableVariants because EX_UPDATES_NATIVE_DEBUG=1")
31
32
  reactExtension.debuggableVariants.set(listOf())
32
33
  }
@@ -126,3 +127,10 @@ private fun detectedEntryFile(config: ReactExtension): File {
126
127
  else -> File(reactRoot, "index.js")
127
128
  }
128
129
  }
130
+
131
+ private fun isNativeDebuggingEnabled(project: Project): Boolean {
132
+ if (System.getenv("EX_UPDATES_NATIVE_DEBUG") == "1") {
133
+ return true
134
+ }
135
+ return project.findProperty("EX_UPDATES_NATIVE_DEBUG") == "true"
136
+ }
@@ -22,6 +22,10 @@ public final class ExpoUpdatesReactDelegateHandler: ExpoReactDelegateHandler, Ap
22
22
  initialProperties: [AnyHashable: Any]?,
23
23
  launchOptions: [UIApplication.LaunchOptionsKey: Any]?
24
24
  ) -> UIView? {
25
+ if UpdatesUtils.isUsingCustomInitialization() {
26
+ return nil
27
+ }
28
+
25
29
  AppController.initializeWithoutStarting()
26
30
  let controller = AppController.sharedInstance
27
31
  if !controller.isActiveController {
@@ -59,6 +63,9 @@ public final class ExpoUpdatesReactDelegateHandler: ExpoReactDelegateHandler, Ap
59
63
  // MARK: AppControllerDelegate implementations
60
64
 
61
65
  public func appController(_ appController: AppControllerInterface, didStartWithSuccess success: Bool) {
66
+ if UpdatesUtils.isUsingCustomInitialization() {
67
+ return
68
+ }
62
69
  guard let reactDelegate = self.reactDelegate else {
63
70
  fatalError("`reactDelegate` should not be nil")
64
71
  }
@@ -133,7 +133,7 @@ public final class UpdatesUtils: NSObject {
133
133
  }
134
134
  }
135
135
 
136
- internal static func isNativeDebuggingEnabled() -> Bool {
136
+ public static func isNativeDebuggingEnabled() -> Bool {
137
137
  #if EX_UPDATES_NATIVE_DEBUG
138
138
  return true
139
139
  #else
@@ -141,6 +141,14 @@ public final class UpdatesUtils: NSObject {
141
141
  #endif
142
142
  }
143
143
 
144
+ internal static func isUsingCustomInitialization() -> Bool {
145
+ #if EX_UPDATES_CUSTOM_INIT
146
+ return true
147
+ #else
148
+ return false
149
+ #endif
150
+ }
151
+
144
152
  internal static func runBlockOnMainThread(_ block: @escaping () -> Void) {
145
153
  if Thread.isMainThread {
146
154
  block()
@@ -3,9 +3,19 @@ require 'json'
3
3
  package = JSON.parse(File.read(File.join(__dir__, '..', 'package.json')))
4
4
  podfile_properties = JSON.parse(File.read("#{Pod::Config.instance.installation_root}/Podfile.properties.json")) rescue {}
5
5
 
6
+ if ENV['EX_UPDATES_NATIVE_DEBUG'] != '1'
7
+ ENV['EX_UPDATES_NATIVE_DEBUG'] = podfile_properties['updatesNativeDebug'] == 'true' ? '1' : '0'
8
+ end
9
+ if ENV['EX_UPDATES_CUSTOM_INIT'] != '1'
10
+ ENV['EX_UPDATES_CUSTOM_INIT'] = podfile_properties['updatesCustomInit'] == 'true' ? '1' : '0'
11
+ end
12
+
6
13
  use_dev_client = false
7
14
  begin
8
- use_dev_client = `node --print "require('expo-dev-client/package.json').version" 2>/dev/null`.length > 0
15
+ # No dev client if we are using native debug
16
+ if ENV['EX_UPDATES_NATIVE_DEBUG'] != '1'
17
+ use_dev_client = `node --print "require('expo-dev-client/package.json').version" 2>/dev/null`.length > 0
18
+ end
9
19
  rescue
10
20
  use_dev_client = false
11
21
  end
@@ -43,17 +53,26 @@ Pod::Spec.new do |s|
43
53
  end
44
54
  install_modules_dependencies(s)
45
55
 
46
- other_c_flags = '$(inherited)'
47
- other_swift_flags = '$(inherited)'
56
+ other_debug_c_flags = '$(inherited)'
57
+ other_debug_swift_flags = '$(inherited)'
58
+ other_release_c_flags = '$(inherited)'
59
+ other_release_swift_flags = '$(inherited)'
48
60
 
49
61
  ex_updates_native_debug = ENV['EX_UPDATES_NATIVE_DEBUG'] == '1'
62
+ ex_updates_custom_init = ENV['EX_UPDATES_CUSTOM_INIT'] == '1'
50
63
  if ex_updates_native_debug
51
- other_c_flags << ' -DEX_UPDATES_NATIVE_DEBUG=1'
52
- other_swift_flags << ' -DEX_UPDATES_NATIVE_DEBUG'
64
+ other_debug_c_flags << ' -DEX_UPDATES_NATIVE_DEBUG=1'
65
+ other_debug_swift_flags << ' -DEX_UPDATES_NATIVE_DEBUG'
66
+ end
67
+ if ex_updates_custom_init
68
+ other_debug_c_flags << ' -DEX_UPDATES_CUSTOM_INIT=1'
69
+ other_debug_swift_flags << ' -DEX_UPDATES_CUSTOM_INIT'
70
+ other_release_c_flags << ' -DEX_UPDATES_CUSTOM_INIT=1'
71
+ other_release_swift_flags << ' -DEX_UPDATES_CUSTOM_INIT'
53
72
  end
54
73
  if use_dev_client
55
- other_c_flags << ' -DUSE_DEV_CLIENT=1'
56
- other_swift_flags << ' -DUSE_DEV_CLIENT'
74
+ other_debug_c_flags << ' -DUSE_DEV_CLIENT=1'
75
+ other_debug_swift_flags << ' -DUSE_DEV_CLIENT'
57
76
  end
58
77
 
59
78
  s.pod_target_xcconfig = {
@@ -61,8 +80,10 @@ Pod::Spec.new do |s|
61
80
  'GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS' => 'YES',
62
81
  'DEFINES_MODULE' => 'YES',
63
82
  'SWIFT_COMPILATION_MODE' => 'wholemodule',
64
- 'OTHER_CFLAGS[config=*Debug*]' => other_c_flags,
65
- 'OTHER_SWIFT_FLAGS[config=*Debug*]' => other_swift_flags
83
+ 'OTHER_CFLAGS[config=*Debug*]' => other_debug_c_flags,
84
+ 'OTHER_SWIFT_FLAGS[config=*Debug*]' => other_debug_swift_flags,
85
+ 'OTHER_CFLAGS[config=*Release*]' => other_release_c_flags,
86
+ 'OTHER_SWIFT_FLAGS[config=*Release*]' => other_release_swift_flags
66
87
  }
67
88
  s.user_target_xcconfig = {
68
89
  'HEADER_SEARCH_PATHS' => '"${PODS_CONFIGURATION_BUILD_DIR}/EXUpdates/Swift Compatibility Header"',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-updates",
3
- "version": "0.27.3",
3
+ "version": "0.27.4",
4
4
  "description": "Fetches and manages remotely-hosted assets and updates to your app's JS bundle.",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -67,5 +67,5 @@
67
67
  "expo": "*",
68
68
  "react": "*"
69
69
  },
70
- "gitHead": "bf63b042785a27b713485db0171eb0500abfa582"
70
+ "gitHead": "3d777be5908ef1cfd1aab88e9807a6b0295ae96b"
71
71
  }