Skip to content

Commit e310541

Browse files
committed
fix(Native): JS bundle not replaced in Bridgeless (release build)
1 parent 43a0e37 commit e310541

File tree

1 file changed

+47
-5
lines changed

1 file changed

+47
-5
lines changed

android/app/src/main/java/com/microsoft/codepush/react/CodePushNativeModule.java

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@
77
import android.os.Looper;
88
import android.view.View;
99

10+
import androidx.annotation.OptIn;
11+
1012
import com.facebook.react.ReactApplication;
1113
import com.facebook.react.ReactDelegate;
14+
import com.facebook.react.ReactHost;
1215
import com.facebook.react.ReactInstanceManager;
1316
import com.facebook.react.ReactActivity;
1417
import com.facebook.react.ReactRootView;
@@ -21,10 +24,11 @@
2124
import com.facebook.react.bridge.ReactMethod;
2225
import com.facebook.react.bridge.ReadableMap;
2326
import com.facebook.react.bridge.WritableMap;
24-
import com.facebook.react.devsupport.interfaces.DevSupportManager;
27+
import com.facebook.react.common.annotations.UnstableReactNativeAPI;
2528
import com.facebook.react.modules.core.ChoreographerCompat;
2629
import com.facebook.react.modules.core.DeviceEventManagerModule;
2730
import com.facebook.react.modules.core.ReactChoreographer;
31+
import com.facebook.react.runtime.ReactHostDelegate;
2832

2933
import org.json.JSONArray;
3034
import org.json.JSONException;
@@ -122,15 +126,38 @@ private void setJSBundle(ReactInstanceManager instanceManager, String latestJSBu
122126
latestJSBundleLoader = JSBundleLoader.createFileLoader(latestJSBundleFile);
123127
}
124128

125-
Field bundleLoaderField = instanceManager.getClass().getDeclaredField("mBundleLoader");
126-
bundleLoaderField.setAccessible(true);
127-
bundleLoaderField.set(instanceManager, latestJSBundleLoader);
129+
ReactHost reactHost = resolveReactHost();
130+
if (reactHost == null) {
131+
// Bridge, Old Architecture and RN < 0.74 (we support Bridgeless >= 0.74)
132+
setJSBundleLoaderBridge(instanceManager, latestJSBundleLoader);
133+
return;
134+
}
135+
136+
// Bridgeless (RN >= 0.74)
137+
setJSBundleLoaderBridgeless(reactHost, latestJSBundleLoader);
128138
} catch (Exception e) {
129139
CodePushUtils.log("Unable to set JSBundle - CodePush may not support this version of React Native");
130140
throw new IllegalAccessException("Could not setJSBundle");
131141
}
132142
}
133143

144+
private void setJSBundleLoaderBridge(ReactInstanceManager instanceManager, JSBundleLoader latestJSBundleLoader) throws NoSuchFieldException, IllegalAccessException {
145+
Field bundleLoaderField = instanceManager.getClass().getDeclaredField("mBundleLoader");
146+
bundleLoaderField.setAccessible(true);
147+
bundleLoaderField.set(instanceManager, latestJSBundleLoader);
148+
}
149+
150+
@OptIn(markerClass = UnstableReactNativeAPI.class)
151+
private void setJSBundleLoaderBridgeless(ReactHost reactHost, JSBundleLoader latestJSBundleLoader) throws NoSuchFieldException, IllegalAccessException {
152+
Field mReactHostDelegateField = reactHost.getClass().getDeclaredField("mReactHostDelegate");
153+
mReactHostDelegateField.setAccessible(true);
154+
ReactHostDelegate reactHostDelegate = (ReactHostDelegate) mReactHostDelegateField.get(reactHost);
155+
assert reactHostDelegate != null;
156+
Field jsBundleLoaderField = reactHostDelegate.getClass().getDeclaredField("jsBundleLoader");
157+
jsBundleLoaderField.setAccessible(true);
158+
jsBundleLoaderField.set(reactHostDelegate, latestJSBundleLoader);
159+
}
160+
134161
private void loadBundle() {
135162
clearLifecycleEventListener();
136163
try {
@@ -161,7 +188,7 @@ public void run() {
161188
// reload method introduced in RN 0.74 (https://github.com/reactwg/react-native-new-architecture/discussions/174)
162189
// so, we need to check if reload method exists and call it
163190
try {
164-
ReactDelegate reactDelegate = CodePushNativeModule.this.resolveReactDelegate();
191+
ReactDelegate reactDelegate = resolveReactDelegate();
165192
if (reactDelegate == null) {
166193
throw new NoSuchMethodException("ReactDelegate doesn't have reload method in RN < 0.74");
167194
}
@@ -229,6 +256,21 @@ private ReactDelegate resolveReactDelegate() {
229256
}
230257
}
231258

259+
private ReactHost resolveReactHost() {
260+
ReactDelegate reactDelegate = resolveReactDelegate();
261+
if (reactDelegate == null) {
262+
return null;
263+
}
264+
265+
try {
266+
Field reactHostField = reactDelegate.getClass().getDeclaredField("mReactHost");
267+
reactHostField.setAccessible(true);
268+
return (ReactHost) reactHostField.get(reactDelegate);
269+
} catch (Exception e) {
270+
return null;
271+
}
272+
}
273+
232274
// Use reflection to find the ReactInstanceManager. See #556 for a proposal for a less brittle way to approach this.
233275
private ReactInstanceManager resolveInstanceManager() throws NoSuchFieldException, IllegalAccessException {
234276
ReactInstanceManager instanceManager = CodePush.getReactInstanceManager();

0 commit comments

Comments
 (0)