Skip to content

Commit 75b4ed6

Browse files
authored
fix(Android): make update and reload behavior work properly (#105)
* fix(Android): support React Native version 0.81+ by updating field access for ReactHost * fix(Android): update not working properly * docs: add note for users on React Native 0.76 or lower
1 parent ea45e52 commit 75b4ed6

File tree

3 files changed

+29
-16
lines changed

3 files changed

+29
-16
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010

1111
Supports React Native 0.74 ~ 0.82.
1212

13+
> [!NOTE]
14+
> If you are using React Native 0.76 or lower, please use version `12.0.2` of this library.
15+
1316
(Tested on the React Native CLI template apps)
1417

1518
### ✅ Requirements

android/app/proguard-rules.pro

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,14 @@
2020
-keepclassmembers class com.facebook.react.ReactInstanceManager {
2121
private final ** mBundleLoader;
2222
}
23-
-keepclassmembers class com.facebook.react.ReactDelegate {
24-
private ** mReactHost; # bridgeless
25-
public void reload(...); # RN 0.74 and above
26-
}
2723
# bridgeless
2824
-keepclassmembers class com.facebook.react.defaults.DefaultReactHostDelegate {
2925
private ** jsBundleLoader;
3026
}
3127
# bridgeless
3228
-keepclassmembers class com.facebook.react.runtime.ReactHostImpl {
33-
private final ** mReactHostDelegate;
29+
private final ** mReactHostDelegate; # RN < 0.81
30+
private final ** reactHostDelegate; # RN 0.81+
3431
}
3532

3633
# Can't find referenced class org.bouncycastle.**

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

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212

1313
import com.facebook.react.ReactDelegate;
1414
import com.facebook.react.ReactHost;
15-
import com.facebook.react.ReactInstanceManager;
1615
import com.facebook.react.ReactActivity;
16+
import com.facebook.react.ReactInstanceManager;
1717
import com.facebook.react.ReactRootView;
1818
import com.facebook.react.bridge.Arguments;
1919
import com.facebook.react.bridge.JSBundleLoader;
@@ -126,7 +126,9 @@ private void setJSBundle(String latestJSBundleFile) throws IllegalAccessExceptio
126126

127127
ReactHost reactHost = resolveReactHost();
128128
if (reactHost == null) {
129+
CodePushUtils.log("Unable to resolve ReactHost");
129130
// Bridge, Old Architecture
131+
setJSBundleLoaderBridge(latestJSBundleLoader);
130132
return;
131133
}
132134

@@ -138,11 +140,27 @@ private void setJSBundle(String latestJSBundleFile) throws IllegalAccessExceptio
138140
}
139141
}
140142

143+
private void setJSBundleLoaderBridge(JSBundleLoader latestJSBundleLoader) throws NoSuchFieldException, IllegalAccessException {
144+
ReactDelegate reactDelegate = resolveReactDelegate();
145+
assert reactDelegate != null;
146+
ReactInstanceManager instanceManager = reactDelegate.getReactInstanceManager();
147+
Field bundleLoaderField = instanceManager.getClass().getDeclaredField("mBundleLoader");
148+
bundleLoaderField.setAccessible(true);
149+
bundleLoaderField.set(instanceManager, latestJSBundleLoader);
150+
}
151+
141152
@OptIn(markerClass = UnstableReactNativeAPI.class)
142153
private void setJSBundleLoaderBridgeless(ReactHost reactHost, JSBundleLoader latestJSBundleLoader) throws NoSuchFieldException, IllegalAccessException {
143-
Field mReactHostDelegateField = reactHost.getClass().getDeclaredField("mReactHostDelegate");
144-
mReactHostDelegateField.setAccessible(true);
145-
ReactHostDelegate reactHostDelegate = (ReactHostDelegate) mReactHostDelegateField.get(reactHost);
154+
Field reactHostDelegateField;
155+
try {
156+
// RN < 0.81
157+
reactHostDelegateField = reactHost.getClass().getDeclaredField("mReactHostDelegate");
158+
} catch (NoSuchFieldException e) {
159+
// RN >= 0.81
160+
reactHostDelegateField = reactHost.getClass().getDeclaredField("reactHostDelegate");
161+
}
162+
reactHostDelegateField.setAccessible(true);
163+
ReactHostDelegate reactHostDelegate = (ReactHostDelegate) reactHostDelegateField.get(reactHost);
146164
assert reactHostDelegate != null;
147165
Field jsBundleLoaderField = reactHostDelegate.getClass().getDeclaredField("jsBundleLoader");
148166
jsBundleLoaderField.setAccessible(true);
@@ -216,16 +234,11 @@ private ReactDelegate resolveReactDelegate() {
216234
private ReactHost resolveReactHost() {
217235
ReactDelegate reactDelegate = resolveReactDelegate();
218236
if (reactDelegate == null) {
237+
CodePushUtils.log("Unable to resolve ReactDelegate");
219238
return null;
220239
}
221240

222-
try {
223-
Field reactHostField = reactDelegate.getClass().getDeclaredField("mReactHost");
224-
reactHostField.setAccessible(true);
225-
return (ReactHost) reactHostField.get(reactDelegate);
226-
} catch (Exception e) {
227-
return null;
228-
}
241+
return reactDelegate.getReactHost();
229242
}
230243

231244
private void restartAppInternal(boolean onlyIfUpdateIsPending) {

0 commit comments

Comments
 (0)