expo-updates 0.27.4 → 0.28.0

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.
Files changed (105) hide show
  1. package/CHANGELOG.md +46 -19
  2. package/android/build.gradle +34 -17
  3. package/android/src/main/java/expo/modules/updates/DisabledUpdatesController.kt +1 -1
  4. package/android/src/main/java/expo/modules/updates/EnabledUpdatesController.kt +8 -5
  5. package/android/src/main/java/expo/modules/updates/UpdatesController.kt +128 -118
  6. package/android/src/main/java/expo/modules/updates/UpdatesDevLauncherController.kt +6 -3
  7. package/android/src/main/java/expo/modules/updates/UpdatesModule.kt +34 -14
  8. package/android/src/main/java/expo/modules/updates/errorrecovery/ErrorRecovery.kt +7 -9
  9. package/android/src/main/java/expo/modules/updates/launcher/NoDatabaseLauncher.kt +6 -3
  10. package/android/src/main/java/expo/modules/updates/loader/FileDownloader.kt +24 -23
  11. package/android/src/main/java/expo/modules/updates/loader/LoaderTask.kt +18 -16
  12. package/android/src/main/java/expo/modules/updates/logging/UpdatesLogReader.kt +3 -3
  13. package/android/src/main/java/expo/modules/updates/logging/UpdatesLogger.kt +8 -4
  14. package/android/src/main/java/expo/modules/updates/procedures/CheckForUpdateProcedure.kt +119 -121
  15. package/android/src/main/java/expo/modules/updates/procedures/FetchUpdateProcedure.kt +71 -74
  16. package/android/src/main/java/expo/modules/updates/procedures/RecreateReactContextProcedure.kt +2 -2
  17. package/android/src/main/java/expo/modules/updates/procedures/RelaunchProcedure.kt +10 -13
  18. package/android/src/main/java/expo/modules/updates/procedures/StartupProcedure.kt +5 -2
  19. package/android/src/main/java/expo/modules/updates/procedures/StateMachineProcedure.kt +4 -3
  20. package/android/src/main/java/expo/modules/updates/procedures/StateMachineSerialExecutorQueue.kt +57 -56
  21. package/android/src/main/java/expo/modules/updates/statemachine/UpdatesStateContext.kt +19 -2
  22. package/android/src/main/java/expo/modules/updates/statemachine/UpdatesStateEvent.kt +9 -7
  23. package/android/src/main/java/expo/modules/updates/statemachine/UpdatesStateEventType.kt +2 -0
  24. package/android/src/main/java/expo/modules/updates/statemachine/UpdatesStateMachine.kt +13 -5
  25. package/build/ExpoUpdates.web.d.ts.map +1 -1
  26. package/build/ExpoUpdates.web.js +2 -0
  27. package/build/ExpoUpdates.web.js.map +1 -1
  28. package/build/Updates.types.d.ts +2 -8
  29. package/build/Updates.types.d.ts.map +1 -1
  30. package/build/Updates.types.js.map +1 -1
  31. package/build/UpdatesEmitter.d.ts +5 -1
  32. package/build/UpdatesEmitter.d.ts.map +1 -1
  33. package/build/UpdatesEmitter.js +8 -4
  34. package/build/UpdatesEmitter.js.map +1 -1
  35. package/build/UseUpdates.d.ts.map +1 -1
  36. package/build/UseUpdates.js +1 -1
  37. package/build/UseUpdates.js.map +1 -1
  38. package/build/UseUpdates.types.d.ts +14 -5
  39. package/build/UseUpdates.types.d.ts.map +1 -1
  40. package/build/UseUpdates.types.js.map +1 -1
  41. package/build/UseUpdatesUtils.d.ts +2 -14
  42. package/build/UseUpdatesUtils.d.ts.map +1 -1
  43. package/build/UseUpdatesUtils.js +4 -1
  44. package/build/UseUpdatesUtils.js.map +1 -1
  45. package/cli/build/syncConfigurationToNativeAsync.js +6 -5
  46. package/cli/src/syncConfigurationToNativeAsync.ts +6 -5
  47. package/e2e/fixtures/App.tsx +18 -0
  48. package/e2e/fixtures/Updates-error-recovery.e2e.ts +2 -2
  49. package/e2e/fixtures/Updates-startup.e2e.ts +18 -3
  50. package/e2e/fixtures/Updates.e2e.ts +3 -0
  51. package/e2e/fixtures/custom_init/AppDelegate.swift +141 -0
  52. package/e2e/fixtures/custom_init/MainActivity.kt +49 -0
  53. package/e2e/fixtures/custom_init/MainApplication.kt +48 -0
  54. package/e2e/fixtures/project_files/eas.json +2 -1
  55. package/e2e/setup/create-eas-project-custom-init.ts +42 -0
  56. package/e2e/setup/project.ts +108 -21
  57. package/e2e-cli/jest.config.js +8 -0
  58. package/expo-module.config.json +1 -3
  59. package/expo-updates-gradle-plugin/build.gradle.kts +1 -1
  60. package/ios/EXUpdates/AppController.swift +6 -4
  61. package/ios/EXUpdates/AppLauncher/AppLauncherWithDatabase.swift +3 -3
  62. package/ios/EXUpdates/AppLoader/AppLoaderTask.swift +9 -11
  63. package/ios/EXUpdates/AppLoader/FileDownloader.swift +4 -4
  64. package/ios/EXUpdates/AppLoader/RemoteAppLoader.swift +1 -1
  65. package/ios/EXUpdates/Database/UpdatesDatabase.swift +2 -2
  66. package/ios/EXUpdates/Database/UpdatesDatabaseInitialization.swift +14 -6
  67. package/ios/EXUpdates/Database/UpdatesReaper.swift +4 -3
  68. package/ios/EXUpdates/DevLauncherAppController.swift +4 -2
  69. package/ios/EXUpdates/DisabledAppController.swift +5 -1
  70. package/ios/EXUpdates/EnabledAppController.swift +1 -5
  71. package/ios/EXUpdates/ErrorRecovery.swift +4 -2
  72. package/ios/EXUpdates/Logging/UpdatesLogger.swift +4 -2
  73. package/ios/EXUpdates/Procedures/CheckForUpdateProcedure.swift +11 -13
  74. package/ios/EXUpdates/Procedures/FetchUpdateProcedure.swift +6 -6
  75. package/ios/EXUpdates/Procedures/RecreateReactContextProcedure.swift +2 -2
  76. package/ios/EXUpdates/Procedures/RelaunchProcedure.swift +6 -4
  77. package/ios/EXUpdates/Procedures/StartupProcedure.swift +16 -14
  78. package/ios/EXUpdates/Procedures/StateMachineProcedure.swift +9 -9
  79. package/ios/EXUpdates/Procedures/StateMachineSerialExecutorQueue.swift +2 -2
  80. package/ios/EXUpdates/ReactDelegateHandler/ExpoUpdatesReactDelegateHandler.swift +6 -3
  81. package/ios/EXUpdates/UpdatesConfig.swift +1 -1
  82. package/ios/EXUpdates/UpdatesStateMachine.swift +126 -155
  83. package/ios/Tests/AppLauncherWithDatabaseSpec.swift +3 -2
  84. package/ios/Tests/DatabaseInitializationSpec.swift +37 -16
  85. package/ios/Tests/DatabaseIntegrityCheckSpec.swift +1 -1
  86. package/ios/Tests/ErrorRecoverySpec.swift +1 -1
  87. package/ios/Tests/FileDownloaderManifestParsingSpec.swift +24 -24
  88. package/ios/Tests/FileDownloaderSpec.swift +9 -9
  89. package/ios/Tests/UpdatesBuildDataSpec.swift +1 -1
  90. package/ios/Tests/UpdatesDatabaseSpec.swift +1 -1
  91. package/ios/Tests/UpdatesLoggerSpec.swift +29 -9
  92. package/ios/Tests/UpdatesStateMachineSpec.swift +69 -31
  93. package/package.json +12 -13
  94. package/src/ExpoUpdates.web.ts +2 -0
  95. package/src/Updates.types.ts +2 -10
  96. package/src/UpdatesEmitter.ts +13 -6
  97. package/src/UseUpdates.ts +1 -2
  98. package/src/UseUpdates.types.ts +14 -5
  99. package/src/UseUpdatesUtils.ts +10 -17
  100. package/utils/build/resolveRuntimeVersionAsync.js +3 -0
  101. package/utils/build/vcs.js +3 -3
  102. package/utils/build/workflow.js +2 -2
  103. package/utils/src/resolveRuntimeVersionAsync.ts +5 -0
  104. package/utils/src/vcs.ts +3 -3
  105. package/utils/src/workflow.ts +2 -2
package/CHANGELOG.md CHANGED
@@ -10,82 +10,109 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
- ## 0.27.4 — 2025-03-18
13
+ ## 0.28.0 — 2025-04-04
14
+
15
+ ### 🛠 Breaking changes
16
+
17
+ - upgrade RN to 0.78 ([#35050](https://github.com/expo/expo/pull/35050) by [@vonovak](https://github.com/vonovak))
18
+ - Remove a few long-deprecated typescript types. ([#34215](https://github.com/expo/expo/pull/34215) by [@wschurman](https://github.com/wschurman))
19
+
20
+ ### 🎉 New features
21
+
22
+ - Add new state machine context about startup procedure. ([#32433](https://github.com/expo/expo/pull/32433) by [@wschurman](https://github.com/wschurman))
23
+ - Support for updates.useNativeDebug. ([#35468](https://github.com/expo/expo/pull/35468) by [@douglowder](https://github.com/douglowder))
24
+
25
+ ### 🐛 Bug fixes
26
+
27
+ - [android] Use more robust mechanism for determining empty multipart bodies. ([#33977](https://github.com/expo/expo/pull/33977) by [@wschurman](https://github.com/wschurman))
28
+ - fix E2E tests in Detox debug build ([#32951](https://github.com/expo/expo/pull/32951) by [@matejkriz](https://github.com/matejkriz))
29
+ - Fix runtime version validation warning ([#35188](https://github.com/expo/expo/pull/35188) by [@gabrieldonadel](https://github.com/gabrieldonadel))
30
+
31
+ ### 💡 Others
32
+
33
+ - [Android] Made ReactNativeFeatureFlags a parameter to the constructor of the ErrorRecovery class to be able to make tests pass ([#34363](https://github.com/expo/expo/pull/34363) by [@chrfalch](https://github.com/chrfalch))
34
+ - [iOS] Inject logger from controllers down to dependent objects. ([#34035](https://github.com/expo/expo/pull/34035) by [@wschurman](https://github.com/wschurman))
35
+ - [apple] Migrate remaining `expo-module.config.json` to unified platform syntax. ([#34445](https://github.com/expo/expo/pull/34445) by [@reichhartd](https://github.com/reichhartd))
36
+ - Fixed build error on iOS Expo Go. ([#34485](https://github.com/expo/expo/pull/34485) by [@kudo](https://github.com/kudo))
37
+ - Fixed Android unit test errors in BuilDataTest. ([#34510](https://github.com/expo/expo/pull/34510) by [@kudo](https://github.com/kudo))
38
+ - [Android] Started using expo modules gradle plugin. ([#34806](https://github.com/expo/expo/pull/34806) by [@lukmccall](https://github.com/lukmccall))
39
+ - Drop `fs-extra` in favor of `fs`. ([#35036](https://github.com/expo/expo/pull/35036) by [@kitten](https://github.com/kitten))
40
+ - Drop `fast-glob` in favor of `glob`. ([#35082](https://github.com/expo/expo/pull/35082) by [@kitten](https://github.com/kitten))
41
+ - Drop `fbemitter` in favor of custom emitter. ([#35317](https://github.com/expo/expo/pull/35317) by [@kitten](https://github.com/kitten))
42
+ - E2E tests for custom init. ([#35569](https://github.com/expo/expo/pull/35569) by [@douglowder](https://github.com/douglowder))
43
+ - Refactored `RCTReactNativeFactory` integration. ([#35679](https://github.com/expo/expo/pull/35679) by [@kudo](https://github.com/kudo))
44
+
45
+ ## 0.27.4 - 2025-03-18
14
46
 
15
47
  ### 🎉 New features
16
48
 
17
49
  - Support brownfield apps with EX_UPDATES_CUSTOM_INIT flag. ([#35391](https://github.com/expo/expo/pull/35391) by [@douglowder](https://github.com/douglowder))
18
50
 
19
- ## 0.27.3 2025-03-11
51
+ ## 0.27.3 - 2025-03-11
20
52
 
21
53
  ### 🐛 Bug fixes
22
54
 
23
55
  - Pass through the package version to config plugin sync utilities ([#35372](https://github.com/expo/expo/pull/35372) by [@brentvatne](https://github.com/brentvatne))
24
56
 
25
- ## 0.27.2 2025-02-26
57
+ ## 0.27.2 - 2025-02-26
26
58
 
27
59
  ### 💡 Others
28
60
 
29
61
  - Add update id headers to asset requests ([#34453](https://github.com/expo/expo/pull/34453) by [@gabrieldonadel](https://github.com/gabrieldonadel))
30
62
 
31
- ## 0.27.1 2025-02-21
63
+ ## 0.27.1 - 2025-02-21
32
64
 
33
65
  ### 🎉 New features
34
66
 
35
67
  - Add `Updates.setUpdateURLAndRequestHeadersOverride()` to allow overriding update URL configuration from the JS API. ([#34422](https://github.com/expo/expo/pull/34422), [#34423](https://github.com/expo/expo/pull/34423), [#34425](https://github.com/expo/expo/pull/34425), [#34426](https://github.com/expo/expo/pull/34426), [#34454](https://github.com/expo/expo/pull/34454), [#34455](https://github.com/expo/expo/pull/34455), [#34428](https://github.com/expo/expo/pull/34428), [#34404](https://github.com/expo/expo/pull/34404) by [@kudo](https://github.com/kudo), [@wschurman](https://github.com/wschurman))
36
68
 
37
- ### 🐛 Bug fixes
38
-
39
- - Fixed build error on iOS Expo Go. ([#34485](https://github.com/expo/expo/pull/34485) by [@kudo](https://github.com/kudo))
40
- - Fixed Android unit test errors in BuilDataTest. ([#34510](https://github.com/expo/expo/pull/34510) by [@kudo](https://github.com/kudo))
41
-
42
- ## 0.26.19 — 2025-02-19
69
+ ## 0.26.19 - 2025-02-19
43
70
 
44
71
  ### 💡 Others
45
72
 
46
73
  - Fixed incorrect error log on Android. ([#34785](https://github.com/expo/expo/pull/34785) by [@kudo](https://github.com/kudo))
47
74
 
48
- ## 0.26.18 2025-02-12
75
+ ## 0.26.18 - 2025-02-12
49
76
 
50
77
  ### 🐛 Bug fixes
51
78
 
52
79
  - [Android] Fix `bytesToHex` `ArrayIndexOutOfBoundsException` during conversion. ([#34855](https://github.com/expo/expo/pull/34855) by [@gabrieldonadel](https://github.com/gabrieldonadel))
53
80
 
54
- ## 0.26.17 2025-02-06
81
+ ## 0.26.17 - 2025-02-06
55
82
 
56
83
  _This version does not introduce any user-facing changes._
57
84
 
58
- ## 0.26.16 2025-02-04
85
+ ## 0.26.16 - 2025-02-04
59
86
 
60
87
  ### 🐛 Bug fixes
61
88
 
62
89
  - Removed Apache Commons IO dependency and fixed crash issue on Android 7. ([#34638](https://github.com/expo/expo/pull/34638) by [@kudo](https://github.com/kudo))
63
90
 
64
- ## 0.26.15 2025-01-31
91
+ ## 0.26.15 - 2025-01-31
65
92
 
66
93
  ### 🐛 Bug fixes
67
94
 
68
95
  - Fix issue where syncing codesigning config for bare projects would clobber existing Expo.plist config ([#34597](https://github.com/expo/expo/pull/34597) by [@brentvatne](https://github.com/brentvatne))
69
96
 
70
- ## 0.26.14 2025-01-31
97
+ ## 0.26.14 - 2025-01-31
71
98
 
72
99
  _This version does not introduce any user-facing changes._
73
100
 
74
- ## 0.26.13 2025-01-19
101
+ ## 0.26.13 - 2025-01-19
75
102
 
76
103
  _This version does not introduce any user-facing changes._
77
104
 
78
- ## 0.26.12 2025-01-10
105
+ ## 0.26.12 - 2025-01-10
79
106
 
80
107
  _This version does not introduce any user-facing changes._
81
108
 
82
- ## 0.26.11 2025-01-08
109
+ ## 0.26.11 - 2025-01-08
83
110
 
84
111
  ### 🐛 Bug fixes
85
112
 
86
113
  - Fix an issue where `launchFallbackUpdateFromDisk` is called from a foreground thread leading to ANRs. ([#33693](https://github.com/expo/expo/pull/33693) by [@alanjhughes](https://github.com/alanjhughes))
87
114
 
88
- ## 0.26.10 2024-12-05
115
+ ## 0.26.10 - 2024-12-05
89
116
 
90
117
  ### 🐛 Bug fixes
91
118
 
@@ -1,30 +1,45 @@
1
1
  buildscript {
2
- def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
3
- apply from: expoModulesCorePlugin
4
- applyKotlinExpoModulesCorePlugin()
2
+ ext {
3
+ boolish = { value ->
4
+ return value.toString().toBoolean()
5
+ }
6
+ getKspVersion = {
7
+ if (rootProject.hasProperty("kspVersion")) {
8
+ return rootProject["kspVersion"]
9
+ }
10
+
11
+ // We can remove this path once we update the test environment
12
+ // to use the same version of Kotlin as the `expo/expo` repo.
13
+ def kotlinVersion = rootProject["kotlinVersion"]
14
+ if (kotlinVersion == "2.0.21") {
15
+ return "2.0.21-1.0.28"
16
+ } else if (kotlinVersion == "1.9.25") {
17
+ return "1.9.25-1.0.20"
18
+ }
19
+
20
+ return "1.9.24-1.0.20"
21
+ }
22
+ }
5
23
 
6
24
  repositories {
7
25
  mavenCentral()
8
26
  }
9
27
 
10
28
  dependencies {
11
- classpath "com.google.devtools.ksp:symbol-processing-gradle-plugin:${kspVersion()}"
29
+ classpath "com.google.devtools.ksp:symbol-processing-gradle-plugin:${getKspVersion()}"
12
30
  }
13
31
  }
14
32
 
15
33
  apply plugin: 'com.android.library'
34
+ apply plugin: 'expo-module-gradle-plugin'
16
35
  apply plugin: 'com.google.devtools.ksp'
17
36
 
18
- group = 'host.exp.exponent'
19
- version = '0.27.4'
37
+ expoModule {
38
+ canBePublished false
39
+ }
20
40
 
21
- def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
22
- apply from: expoModulesCorePlugin
23
- applyKotlinExpoModulesCorePlugin()
24
- applyKspJvmToolchain()
25
- useCoreDependencies()
26
- useDefaultAndroidSdkVersions()
27
- useExpoPublishing()
41
+ group = 'host.exp.exponent'
42
+ version = '0.28.0'
28
43
 
29
44
  // Utility method to derive boolean values from the environment or from Java properties,
30
45
  // and return them as strings to be used in BuildConfig fields
@@ -67,7 +82,7 @@ android {
67
82
  namespace "expo.modules.updates"
68
83
  defaultConfig {
69
84
  versionCode 31
70
- versionName '0.27.4'
85
+ versionName '0.28.0'
71
86
  consumerProguardFiles("proguard-rules.pro")
72
87
  testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
73
88
 
@@ -122,7 +137,8 @@ dependencies {
122
137
  testImplementation 'junit:junit:4.13.2'
123
138
  testImplementation 'androidx.test:core:1.5.0'
124
139
  testImplementation "io.mockk:mockk:$mockk_version"
125
- testImplementation "org.jetbrains.kotlin:kotlin-test-junit:${kotlinVersion()}"
140
+ testImplementation "org.jetbrains.kotlin:kotlin-test-junit:${kotlinVersion}"
141
+ testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3'
126
142
  testImplementation 'org.robolectric:robolectric:4.14.1'
127
143
 
128
144
  androidTestImplementation 'com.squareup.okio:okio:2.9.0'
@@ -131,7 +147,8 @@ dependencies {
131
147
  androidTestImplementation 'androidx.test:rules:1.5.0'
132
148
  androidTestImplementation "io.mockk:mockk-android:$mockk_version"
133
149
  androidTestImplementation "androidx.room:room-testing:$room_version"
134
- androidTestImplementation "org.jetbrains.kotlin:kotlin-test-junit:${kotlinVersion()}"
150
+ androidTestImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3'
151
+ androidTestImplementation "org.jetbrains.kotlin:kotlin-test-junit:${kotlinVersion}"
135
152
 
136
- implementation "org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion()}"
153
+ implementation "org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}"
137
154
  }
@@ -35,7 +35,7 @@ class DisabledUpdatesController(
35
35
  /** Keep the activity for [RecreateReactContextProcedure] to relaunch the app. */
36
36
  private var weakActivity: WeakReference<Activity>? = null
37
37
 
38
- private val logger = UpdatesLogger(context)
38
+ private val logger = UpdatesLogger(context.filesDir)
39
39
  override val eventManager: IUpdatesEventManager = UpdatesEventManager(logger)
40
40
 
41
41
  // disabled controller state machine can only be idle or restarting
@@ -2,7 +2,6 @@ package expo.modules.updates
2
2
 
3
3
  import android.app.Activity
4
4
  import android.content.Context
5
- import android.os.AsyncTask
6
5
  import android.os.Bundle
7
6
  import com.facebook.react.bridge.ReactContext
8
7
  import com.facebook.react.devsupport.interfaces.DevSupportManager
@@ -27,6 +26,9 @@ import expo.modules.updates.procedures.StartupProcedure
27
26
  import expo.modules.updates.selectionpolicy.SelectionPolicyFactory
28
27
  import expo.modules.updates.statemachine.UpdatesStateMachine
29
28
  import expo.modules.updates.statemachine.UpdatesStateValue
29
+ import kotlinx.coroutines.CoroutineScope
30
+ import kotlinx.coroutines.Dispatchers
31
+ import kotlinx.coroutines.launch
30
32
  import java.io.File
31
33
  import java.lang.ref.WeakReference
32
34
  import kotlin.time.DurationUnit
@@ -42,7 +44,7 @@ class EnabledUpdatesController(
42
44
  ) : IUpdatesController {
43
45
  /** Keep the activity for [RelaunchProcedure] to relaunch the app. */
44
46
  private var weakActivity: WeakReference<Activity>? = null
45
- private val logger = UpdatesLogger(context)
47
+ private val logger = UpdatesLogger(context.filesDir)
46
48
  override val eventManager: IUpdatesEventManager = UpdatesEventManager(logger)
47
49
 
48
50
  private val fileDownloader = FileDownloader(context, updatesConfiguration, logger)
@@ -51,9 +53,10 @@ class EnabledUpdatesController(
51
53
  )
52
54
  private val stateMachine = UpdatesStateMachine(logger, eventManager, UpdatesStateValue.entries.toSet())
53
55
  private val databaseHolder = DatabaseHolder(UpdatesDatabase.getInstance(context))
56
+ private val controllerScope = CoroutineScope(Dispatchers.IO)
54
57
 
55
58
  private fun purgeUpdatesLogsOlderThanOneDay() {
56
- UpdatesLogReader(context).purgeLogEntries {
59
+ UpdatesLogReader(context.filesDir).purgeLogEntries {
57
60
  if (it != null) {
58
61
  logger.error("UpdatesLogReader: error in purgeLogEntries", it, UpdatesErrorCode.Unknown)
59
62
  }
@@ -219,7 +222,7 @@ class EnabledUpdatesController(
219
222
  }
220
223
 
221
224
  override fun getExtraParams(callback: IUpdatesController.ModuleCallback<Bundle>) {
222
- AsyncTask.execute {
225
+ controllerScope.launch {
223
226
  try {
224
227
  val result = ManifestMetadata.getExtraParams(
225
228
  databaseHolder.database,
@@ -245,7 +248,7 @@ class EnabledUpdatesController(
245
248
  }
246
249
 
247
250
  override fun setExtraParam(key: String, value: String?, callback: IUpdatesController.ModuleCallback<Unit>) {
248
- AsyncTask.execute {
251
+ controllerScope.launch {
249
252
  try {
250
253
  ManifestMetadata.setExtraParam(
251
254
  databaseHolder.database,
@@ -18,146 +18,156 @@ import java.lang.ref.WeakReference
18
18
  * start the process of loading and launching an update, then responds appropriately depending on
19
19
  * the callbacks that are invoked.
20
20
  */
21
- class UpdatesController {
22
- companion object {
23
- private var singletonInstance: IUpdatesController? = null
24
- private var overrideConfiguration: UpdatesConfiguration? = null
25
-
26
- @JvmStatic val instance: IUpdatesController
27
- get() {
28
- return checkNotNull(singletonInstance) { "UpdatesController.instance was called before the module was initialized" }
29
- }
21
+ object UpdatesController {
22
+ private var singletonInstance: IUpdatesController? = null
23
+ private var overrideConfiguration: UpdatesConfiguration? = null
24
+
25
+ @JvmStatic
26
+ val instance: IUpdatesController
27
+ get() {
28
+ return checkNotNull(singletonInstance) { "UpdatesController.instance was called before the module was initialized" }
29
+ }
30
30
 
31
- @JvmStatic fun initializeWithoutStarting(context: Context) {
32
- if (singletonInstance != null) {
33
- return
31
+ @JvmStatic
32
+ fun initializeWithoutStarting(context: Context) {
33
+ if (singletonInstance != null) {
34
+ return
35
+ }
36
+ val useDeveloperSupport =
37
+ (context as? ReactApplication)?.reactNativeHost?.useDeveloperSupport ?: false
38
+ if (useDeveloperSupport && !UpdatesPackage.isUsingNativeDebug) {
39
+ if (BuildConfig.USE_DEV_CLIENT) {
40
+ val devLauncherController = initializeAsDevLauncherWithoutStarting(context)
41
+ singletonInstance = devLauncherController
42
+ UpdatesControllerRegistry.controller = WeakReference(devLauncherController)
43
+ } else {
44
+ singletonInstance = DisabledUpdatesController(context, null)
34
45
  }
35
- val useDeveloperSupport = (context as? ReactApplication)?.reactNativeHost?.useDeveloperSupport ?: false
36
- if (useDeveloperSupport && !UpdatesPackage.isUsingNativeDebug) {
37
- if (BuildConfig.USE_DEV_CLIENT) {
38
- val devLauncherController = initializeAsDevLauncherWithoutStarting(context)
39
- singletonInstance = devLauncherController
40
- UpdatesControllerRegistry.controller = WeakReference(devLauncherController)
41
- } else {
42
- singletonInstance = DisabledUpdatesController(context, null)
46
+ return
47
+ }
48
+
49
+ val logger = UpdatesLogger(context.filesDir)
50
+
51
+ val updatesDirectory = try {
52
+ UpdatesUtils.getOrCreateUpdatesDirectory(context)
53
+ } catch (e: Exception) {
54
+ logger.error(
55
+ "The expo-updates system is disabled due to a storage access error",
56
+ e,
57
+ UpdatesErrorCode.InitializationError
58
+ )
59
+ singletonInstance = DisabledUpdatesController(context, e)
60
+ return
61
+ }
62
+
63
+ val updatesConfiguration: UpdatesConfiguration? = overrideConfiguration ?: run {
64
+ when (UpdatesConfiguration.getUpdatesConfigurationValidationResult(context, null)) {
65
+ UpdatesConfigurationValidationResult.VALID -> {
66
+ return@run UpdatesConfiguration(context, null)
43
67
  }
44
- return
45
- }
46
68
 
47
- val logger = UpdatesLogger(context)
69
+ UpdatesConfigurationValidationResult.INVALID_NOT_ENABLED -> logger.warn(
70
+ "The expo-updates system is explicitly disabled. To enable it, set the enabled setting to true.",
71
+ UpdatesErrorCode.InitializationError
72
+ )
48
73
 
49
- val updatesDirectory = try {
50
- UpdatesUtils.getOrCreateUpdatesDirectory(context)
51
- } catch (e: Exception) {
52
- logger.error(
53
- "The expo-updates system is disabled due to a storage access error",
54
- e,
74
+ UpdatesConfigurationValidationResult.INVALID_MISSING_URL -> logger.warn(
75
+ "The expo-updates system is disabled due to an invalid configuration. Ensure a valid URL is supplied.",
55
76
  UpdatesErrorCode.InitializationError
56
77
  )
57
- singletonInstance = DisabledUpdatesController(context, e)
58
- return
59
- }
60
78
 
61
- val updatesConfiguration: UpdatesConfiguration? = overrideConfiguration ?: run {
62
- when (UpdatesConfiguration.getUpdatesConfigurationValidationResult(context, null)) {
63
- UpdatesConfigurationValidationResult.VALID -> {
64
- return@run UpdatesConfiguration(context, null)
65
- }
66
- UpdatesConfigurationValidationResult.INVALID_NOT_ENABLED -> logger.warn(
67
- "The expo-updates system is explicitly disabled. To enable it, set the enabled setting to true.",
68
- UpdatesErrorCode.InitializationError
69
- )
70
- UpdatesConfigurationValidationResult.INVALID_MISSING_URL -> logger.warn(
71
- "The expo-updates system is disabled due to an invalid configuration. Ensure a valid URL is supplied.",
72
- UpdatesErrorCode.InitializationError
73
- )
74
- UpdatesConfigurationValidationResult.INVALID_MISSING_RUNTIME_VERSION -> logger.warn(
75
- "The expo-updates system is disabled due to an invalid configuration. Ensure a runtime version is supplied.",
76
- UpdatesErrorCode.InitializationError
77
- )
78
- }
79
- return@run null
79
+ UpdatesConfigurationValidationResult.INVALID_MISSING_RUNTIME_VERSION -> logger.warn(
80
+ "The expo-updates system is disabled due to an invalid configuration. Ensure a runtime version is supplied.",
81
+ UpdatesErrorCode.InitializationError
82
+ )
80
83
  }
84
+ return@run null
85
+ }
81
86
 
82
- singletonInstance = if (updatesConfiguration != null) {
83
- EnabledUpdatesController(context, updatesConfiguration, updatesDirectory)
84
- } else {
85
- DisabledUpdatesController(context, null)
86
- }
87
+ singletonInstance = if (updatesConfiguration != null) {
88
+ EnabledUpdatesController(context, updatesConfiguration, updatesDirectory)
89
+ } else {
90
+ DisabledUpdatesController(context, null)
87
91
  }
92
+ }
88
93
 
89
- private fun initializeAsDevLauncherWithoutStarting(context: Context): UpdatesDevLauncherController {
90
- check(singletonInstance == null) { "UpdatesController must not be initialized prior to calling initializeAsDevLauncherWithoutStarting" }
94
+ private fun initializeAsDevLauncherWithoutStarting(context: Context): UpdatesDevLauncherController {
95
+ check(singletonInstance == null) { "UpdatesController must not be initialized prior to calling initializeAsDevLauncherWithoutStarting" }
91
96
 
92
- var updatesDirectoryException: Exception? = null
93
- val updatesDirectory = try {
94
- UpdatesUtils.getOrCreateUpdatesDirectory(context)
95
- } catch (e: Exception) {
96
- updatesDirectoryException = e
97
- null
98
- }
97
+ var updatesDirectoryException: Exception? = null
98
+ val updatesDirectory = try {
99
+ UpdatesUtils.getOrCreateUpdatesDirectory(context)
100
+ } catch (e: Exception) {
101
+ updatesDirectoryException = e
102
+ null
103
+ }
99
104
 
100
- val initialUpdatesConfiguration = overrideConfiguration ?: run {
101
- if (UpdatesConfiguration.getUpdatesConfigurationValidationResult(context, null) == UpdatesConfigurationValidationResult.VALID) {
102
- UpdatesConfiguration(context, null)
103
- } else {
105
+ val initialUpdatesConfiguration = overrideConfiguration ?: run {
106
+ if (UpdatesConfiguration.getUpdatesConfigurationValidationResult(
107
+ context,
104
108
  null
105
- }
109
+ ) == UpdatesConfigurationValidationResult.VALID
110
+ ) {
111
+ UpdatesConfiguration(context, null)
112
+ } else {
113
+ null
106
114
  }
107
-
108
- val instance = UpdatesDevLauncherController(
109
- context,
110
- initialUpdatesConfiguration,
111
- updatesDirectory,
112
- updatesDirectoryException
113
- )
114
- singletonInstance = instance
115
- return instance
116
115
  }
117
116
 
118
- /**
119
- * Initializes the UpdatesController singleton. This should be called as early as possible in the
120
- * application's lifecycle. Can pass additional configuration to this method to set or override
121
- * configuration values at runtime rather than just AndroidManifest.xml.
122
- * @param context the base context of the application, ideally a [ReactApplication]
123
- */
124
- @JvmStatic fun initialize(context: Context) {
125
- if (singletonInstance == null) {
126
- initializeWithoutStarting(context)
127
- singletonInstance!!.start()
128
- }
129
- }
117
+ val instance = UpdatesDevLauncherController(
118
+ context,
119
+ initialUpdatesConfiguration,
120
+ updatesDirectory,
121
+ updatesDirectoryException
122
+ )
123
+ singletonInstance = instance
124
+ return instance
125
+ }
130
126
 
131
- /**
132
- * Overrides the [UpdatesConfiguration] that will be used inside [UpdatesController]
133
- * This should be called as early as possible in the application's lifecycle.
134
- * Can pass additional configuration to this method to set or override
135
- * configuration values at runtime rather than just AndroidManifest.xml.
136
- *
137
- * @param context the base context of the application, ideally a [ReactApplication]
138
- * @param configuration map of configuration pairs to override those from AndroidManifest.xml
139
- */
140
- @JvmStatic
141
- fun overrideConfiguration(context: Context, configuration: Map<String, Any>) {
142
- if (singletonInstance != null) {
143
- throw AssertionError("The method should be called before UpdatesController.initialize()")
144
- }
145
- val updatesConfigurationValidationResult = UpdatesConfiguration.getUpdatesConfigurationValidationResult(context, configuration)
146
- if (updatesConfigurationValidationResult == UpdatesConfigurationValidationResult.VALID) {
147
- overrideConfiguration = UpdatesConfiguration(context, configuration)
148
- } else {
149
- val logger = UpdatesLogger(context)
150
- logger.warn("Failed to overrideConfiguration: invalid configuration: ${updatesConfigurationValidationResult.name}")
151
- }
127
+ /**
128
+ * Initializes the UpdatesController singleton. This should be called as early as possible in the
129
+ * application's lifecycle. Can pass additional configuration to this method to set or override
130
+ * configuration values at runtime rather than just AndroidManifest.xml.
131
+ * @param context the base context of the application, ideally a [ReactApplication]
132
+ */
133
+ @JvmStatic
134
+ fun initialize(context: Context) {
135
+ if (singletonInstance == null) {
136
+ initializeWithoutStarting(context)
137
+ singletonInstance!!.start()
152
138
  }
139
+ }
153
140
 
154
- internal fun setUpdatesEventManagerObserver(observer: WeakReference<IUpdatesEventManagerObserver>) {
155
- singletonInstance?.eventManager?.observer = observer
156
- singletonInstance?.onEventListenerStartObserving()
141
+ /**
142
+ * Overrides the [UpdatesConfiguration] that will be used inside [UpdatesController]
143
+ * This should be called as early as possible in the application's lifecycle.
144
+ * Can pass additional configuration to this method to set or override
145
+ * configuration values at runtime rather than just AndroidManifest.xml.
146
+ *
147
+ * @param context the base context of the application, ideally a [ReactApplication]
148
+ * @param configuration map of configuration pairs to override those from AndroidManifest.xml
149
+ */
150
+ @JvmStatic
151
+ fun overrideConfiguration(context: Context, configuration: Map<String, Any>) {
152
+ if (singletonInstance != null) {
153
+ throw AssertionError("The method should be called before UpdatesController.initialize()")
157
154
  }
158
-
159
- internal fun removeUpdatesEventManagerObserver() {
160
- singletonInstance?.eventManager?.observer = null
155
+ val updatesConfigurationValidationResult =
156
+ UpdatesConfiguration.getUpdatesConfigurationValidationResult(context, configuration)
157
+ if (updatesConfigurationValidationResult == UpdatesConfigurationValidationResult.VALID) {
158
+ overrideConfiguration = UpdatesConfiguration(context, configuration)
159
+ } else {
160
+ val logger = UpdatesLogger(context.filesDir)
161
+ logger.warn("Failed to overrideConfiguration: invalid configuration: ${updatesConfigurationValidationResult.name}")
161
162
  }
162
163
  }
164
+
165
+ internal fun setUpdatesEventManagerObserver(observer: WeakReference<IUpdatesEventManagerObserver>) {
166
+ singletonInstance?.eventManager?.observer = observer
167
+ singletonInstance?.onEventListenerStartObserving()
168
+ }
169
+
170
+ internal fun removeUpdatesEventManagerObserver() {
171
+ singletonInstance?.eventManager?.observer = null
172
+ }
163
173
  }
@@ -54,7 +54,7 @@ class UpdatesDevLauncherController(
54
54
 
55
55
  private var launcher: Launcher? = null
56
56
 
57
- private val logger = UpdatesLogger(context)
57
+ private val logger = UpdatesLogger(context.filesDir)
58
58
 
59
59
  private var previousUpdatesConfiguration: UpdatesConfiguration? = null
60
60
  private var updatesConfiguration: UpdatesConfiguration? = initialUpdatesConfiguration
@@ -78,8 +78,11 @@ class UpdatesDevLauncherController(
78
78
  }
79
79
 
80
80
  @get:Synchronized
81
- override val launchAssetFile: String
82
- get() = throw Exception("IUpdatesController.launchAssetFile should not be called in dev client")
81
+ override val launchAssetFile: String?
82
+ get() {
83
+ logger.warn("launchAssetFile should not be called from expo-dev-client build, except for Detox testing")
84
+ return null
85
+ }
83
86
 
84
87
  override val bundleAssetName: String
85
88
  get() = throw Exception("IUpdatesController.bundleAssetName should not be called in dev client")