|
7 | 7 | import android.os.Looper;
|
8 | 8 | import android.view.View;
|
9 | 9 |
|
| 10 | +import androidx.annotation.OptIn; |
| 11 | + |
10 | 12 | import com.facebook.react.ReactApplication;
|
11 | 13 | import com.facebook.react.ReactDelegate;
|
| 14 | +import com.facebook.react.ReactHost; |
12 | 15 | import com.facebook.react.ReactInstanceManager;
|
13 | 16 | import com.facebook.react.ReactActivity;
|
14 | 17 | import com.facebook.react.ReactRootView;
|
|
21 | 24 | import com.facebook.react.bridge.ReactMethod;
|
22 | 25 | import com.facebook.react.bridge.ReadableMap;
|
23 | 26 | import com.facebook.react.bridge.WritableMap;
|
24 |
| -import com.facebook.react.devsupport.interfaces.DevSupportManager; |
| 27 | +import com.facebook.react.common.annotations.UnstableReactNativeAPI; |
25 | 28 | import com.facebook.react.modules.core.ChoreographerCompat;
|
26 | 29 | import com.facebook.react.modules.core.DeviceEventManagerModule;
|
27 | 30 | import com.facebook.react.modules.core.ReactChoreographer;
|
| 31 | +import com.facebook.react.runtime.ReactHostDelegate; |
28 | 32 |
|
29 | 33 | import org.json.JSONArray;
|
30 | 34 | import org.json.JSONException;
|
@@ -122,15 +126,38 @@ private void setJSBundle(ReactInstanceManager instanceManager, String latestJSBu
|
122 | 126 | latestJSBundleLoader = JSBundleLoader.createFileLoader(latestJSBundleFile);
|
123 | 127 | }
|
124 | 128 |
|
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); |
128 | 138 | } catch (Exception e) {
|
129 | 139 | CodePushUtils.log("Unable to set JSBundle - CodePush may not support this version of React Native");
|
130 | 140 | throw new IllegalAccessException("Could not setJSBundle");
|
131 | 141 | }
|
132 | 142 | }
|
133 | 143 |
|
| 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 | + |
134 | 161 | private void loadBundle() {
|
135 | 162 | clearLifecycleEventListener();
|
136 | 163 | try {
|
@@ -161,7 +188,7 @@ public void run() {
|
161 | 188 | // reload method introduced in RN 0.74 (https://github.com/reactwg/react-native-new-architecture/discussions/174)
|
162 | 189 | // so, we need to check if reload method exists and call it
|
163 | 190 | try {
|
164 |
| - ReactDelegate reactDelegate = CodePushNativeModule.this.resolveReactDelegate(); |
| 191 | + ReactDelegate reactDelegate = resolveReactDelegate(); |
165 | 192 | if (reactDelegate == null) {
|
166 | 193 | throw new NoSuchMethodException("ReactDelegate doesn't have reload method in RN < 0.74");
|
167 | 194 | }
|
@@ -229,6 +256,21 @@ private ReactDelegate resolveReactDelegate() {
|
229 | 256 | }
|
230 | 257 | }
|
231 | 258 |
|
| 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 | + |
232 | 274 | // Use reflection to find the ReactInstanceManager. See #556 for a proposal for a less brittle way to approach this.
|
233 | 275 | private ReactInstanceManager resolveInstanceManager() throws NoSuchFieldException, IllegalAccessException {
|
234 | 276 | ReactInstanceManager instanceManager = CodePush.getReactInstanceManager();
|
|
0 commit comments