@otaupdate/react-native 1.0.1 → 1.0.2
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/README.md
CHANGED
|
@@ -319,3 +319,4 @@ compatible with. Devices on other binary versions never receive it.
|
|
|
319
319
|
| Every update rolls back | `notifyAppReady()` is never reached — usually an early crash, or the call sits behind a screen the user has to navigate to. |
|
|
320
320
|
| `no_matching_binary_version` | The release's `targetBinaryVersion` does not cover the installed native version. |
|
|
321
321
|
| Works in debug, not release | Debug builds load from Metro; the OTA path only runs in release builds. |
|
|
322
|
+
| Android: mandatory update reload-loops (bare RN) | Fixed in 1.0.2. Before that, `IMMEDIATE`/`ON_NEXT_RESUME` tried an in-place JS reload that reused a bundle path fixed at process start, so the same mandatory update kept re-triggering forever. 1.0.2 does a real process restart instead — update to it. |
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
package com.otaupdate
|
|
2
2
|
|
|
3
|
+
import android.content.Intent
|
|
3
4
|
import android.os.Handler
|
|
4
5
|
import android.os.Looper
|
|
5
6
|
import android.util.Log
|
|
6
|
-
import com.facebook.react.ReactApplication
|
|
7
7
|
import com.facebook.react.bridge.Arguments
|
|
8
8
|
import com.facebook.react.bridge.LifecycleEventListener
|
|
9
9
|
import com.facebook.react.bridge.Promise
|
|
@@ -221,33 +221,35 @@ class OtaUpdateModule(private val reactContext: ReactApplicationContext) :
|
|
|
221
221
|
}
|
|
222
222
|
|
|
223
223
|
/**
|
|
224
|
-
*
|
|
225
|
-
*
|
|
226
|
-
*
|
|
224
|
+
* Restarts the whole process so the new bundle is loaded.
|
|
225
|
+
*
|
|
226
|
+
* This used to try an in-place JS-context reload (ReactHost.reload() via
|
|
227
|
+
* reflection on the new architecture, recreateReactContextInBackground() as
|
|
228
|
+
* a bridge-mode fallback) — but on Android BOTH of those reuse a bundle
|
|
229
|
+
* loader/path that was fixed once at ReactInstanceManager/ReactHost
|
|
230
|
+
* construction time (see ReactInstanceManager#mBundleLoader, a `final`
|
|
231
|
+
* field, and DefaultReactHost's internal singleton caching). Neither ever
|
|
232
|
+
* re-consults MainApplication's getJSBundleFile()/jsBundleFilePath, so an
|
|
233
|
+
* IMMEDIATE or ON_NEXT_RESUME install silently kept reloading the OLD
|
|
234
|
+
* bundle forever — for a mandatory update this produced an infinite
|
|
235
|
+
* reload loop, since the freshly-reloaded old bundle immediately saw the
|
|
236
|
+
* same "mandatory update available" response and tried to install again.
|
|
237
|
+
*
|
|
238
|
+
* A genuine process kill + relaunch is the only reliable way to force
|
|
239
|
+
* MainApplication to re-run from scratch and pick up the new bundle path —
|
|
240
|
+
* the same technique restart libraries like react-native-restart use.
|
|
241
|
+
* iOS does not need this: RCTTriggerReloadCommandListeners re-queries
|
|
242
|
+
* bundleURL() fresh on every reload, so it was never affected.
|
|
227
243
|
*/
|
|
228
244
|
private fun reload() {
|
|
229
|
-
val
|
|
230
|
-
if (application !is ReactApplication) {
|
|
231
|
-
Log.e(OtaUpdateStore.TAG, "Application does not implement ReactApplication — cannot restart")
|
|
232
|
-
return
|
|
233
|
-
}
|
|
234
|
-
|
|
245
|
+
val context = reactContext.applicationContext
|
|
235
246
|
try {
|
|
236
|
-
val
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
if (reactHost != null) {
|
|
241
|
-
reactHost.javaClass.methods
|
|
242
|
-
.firstOrNull { it.name == "reload" && it.parameterTypes.size == 1 }
|
|
243
|
-
?.invoke(reactHost, "OTA update applied")
|
|
244
|
-
?: Log.e(OtaUpdateStore.TAG, "ReactHost has no reload(String) method")
|
|
245
|
-
return
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
application.reactNativeHost.reactInstanceManager.recreateReactContextInBackground()
|
|
247
|
+
val launchIntent = context.packageManager.getLaunchIntentForPackage(context.packageName)
|
|
248
|
+
?: throw IllegalStateException("no launch intent for ${context.packageName}")
|
|
249
|
+
context.startActivity(Intent.makeRestartActivityTask(launchIntent.component))
|
|
250
|
+
Runtime.getRuntime().exit(0)
|
|
249
251
|
} catch (e: Exception) {
|
|
250
|
-
Log.e(OtaUpdateStore.TAG, "failed to restart the
|
|
252
|
+
Log.e(OtaUpdateStore.TAG, "failed to restart the app process", e)
|
|
251
253
|
}
|
|
252
254
|
}
|
|
253
255
|
|