Skip to content
This repository was archived by the owner on May 20, 2025. It is now read-only.

Commit c631036

Browse files
committed
Remove support for legacy React Native versions
1 parent 41c0c88 commit c631036

File tree

2 files changed

+25
-54
lines changed

2 files changed

+25
-54
lines changed

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

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,22 @@
11
package com.microsoft.codepush.react;
22

3+
import android.content.Context;
4+
import android.content.pm.PackageInfo;
5+
import android.content.pm.PackageManager;
6+
37
import com.facebook.react.ReactInstanceManager;
48
import com.facebook.react.ReactPackage;
59
import com.facebook.react.bridge.JavaScriptModule;
610
import com.facebook.react.bridge.NativeModule;
711
import com.facebook.react.bridge.ReactApplicationContext;
812
import com.facebook.react.uimanager.ViewManager;
913

10-
import android.content.Context;
11-
import android.content.pm.ApplicationInfo;
12-
import android.content.pm.PackageInfo;
13-
import android.content.pm.PackageManager;
14-
1514
import org.json.JSONException;
1615
import org.json.JSONObject;
1716

1817
import java.io.File;
19-
import java.io.IOException;
2018
import java.util.ArrayList;
2119
import java.util.List;
22-
import java.util.zip.ZipEntry;
23-
import java.util.zip.ZipFile;
2420

2521
public class CodePush implements ReactPackage {
2622

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

Lines changed: 21 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
package com.microsoft.codepush.react;
22

33
import android.app.Activity;
4-
import android.content.Context;
54
import android.os.AsyncTask;
65
import android.os.Handler;
76
import android.os.Looper;
87
import android.provider.Settings;
9-
import android.view.Choreographer;
108

11-
import com.facebook.react.ReactActivity;
9+
import com.facebook.react.ReactApplication;
1210
import com.facebook.react.ReactInstanceManager;
1311
import com.facebook.react.bridge.Arguments;
1412
import com.facebook.react.bridge.LifecycleEventListener;
@@ -18,8 +16,8 @@
1816
import com.facebook.react.bridge.ReactMethod;
1917
import com.facebook.react.bridge.ReadableMap;
2018
import com.facebook.react.bridge.WritableMap;
21-
import com.facebook.react.modules.core.DeviceEventManagerModule;
2219
import com.facebook.react.modules.core.ChoreographerCompat;
20+
import com.facebook.react.modules.core.DeviceEventManagerModule;
2321
import com.facebook.react.modules.core.ReactChoreographer;
2422

2523
import org.json.JSONArray;
@@ -44,9 +42,6 @@ public class CodePushNativeModule extends ReactContextBaseJavaModule {
4442
private CodePushTelemetryManager mTelemetryManager;
4543
private CodePushUpdateManager mUpdateManager;
4644

47-
private static final String REACT_APPLICATION_CLASS_NAME = "com.facebook.react.ReactApplication";
48-
private static final String REACT_NATIVE_HOST_CLASS_NAME = "com.facebook.react.ReactNativeHost";
49-
5045
public CodePushNativeModule(ReactApplicationContext reactContext, CodePush codePush, CodePushUpdateManager codePushUpdateManager, CodePushTelemetryManager codePushTelemetryManager, SettingsManager settingsManager) {
5146
super(reactContext);
5247

@@ -100,7 +95,7 @@ public void run() {
10095

10196
// Use reflection to find and set the appropriate fields on ReactInstanceManager. See #556 for a proposal for a less brittle way
10297
// to approach this.
103-
private void setJSBundle(ReactInstanceManager instanceManager, String latestJSBundleFile) throws NoSuchFieldException, IllegalAccessException {
98+
private void setJSBundle(ReactInstanceManager instanceManager, String latestJSBundleFile) throws IllegalAccessException {
10499
try {
105100
Field bundleLoaderField = instanceManager.getClass().getDeclaredField("mBundleLoader");
106101
Class<?> jsBundleLoaderClass = Class.forName("com.facebook.react.cxxbridge.JSBundleLoader");
@@ -109,7 +104,7 @@ private void setJSBundle(ReactInstanceManager instanceManager, String latestJSBu
109104
? "createAssetLoader" : "createFileLoader";
110105

111106
Method[] methods = jsBundleLoaderClass.getDeclaredMethods();
112-
for (Method method : methods) {
107+
for (Method method : methods) {
113108
if (method.getName().equals(createFileLoaderMethodName)) {
114109
createFileLoaderMethod = method;
115110
break;
@@ -127,7 +122,7 @@ private void setJSBundle(ReactInstanceManager instanceManager, String latestJSBu
127122
// RN >= v0.34
128123
latestJSBundleLoader = createFileLoaderMethod.invoke(jsBundleLoaderClass, latestJSBundleFile);
129124
} else if (numParameters == 2) {
130-
// RN >= v0.31 && RN < v0.34 or AssetLoader instance
125+
// AssetLoader instance
131126
latestJSBundleLoader = createFileLoaderMethod.invoke(jsBundleLoaderClass, getReactApplicationContext(), latestJSBundleFile);
132127
} else {
133128
throw new NoSuchMethodException("Could not find a recognized 'createFileLoader' method");
@@ -136,14 +131,13 @@ private void setJSBundle(ReactInstanceManager instanceManager, String latestJSBu
136131
bundleLoaderField.setAccessible(true);
137132
bundleLoaderField.set(instanceManager, latestJSBundleLoader);
138133
} catch (Exception e) {
139-
// RN < v0.31
140-
Field jsBundleField = instanceManager.getClass().getDeclaredField("mJSBundleFile");
141-
jsBundleField.setAccessible(true);
142-
jsBundleField.set(instanceManager, latestJSBundleFile);
134+
CodePushUtils.log("Unable to set JSBundle - CodePush may not support this version of React Native");
135+
throw new IllegalAccessException("Could not setJSBundle");
143136
}
144137
}
145138

146139
private void loadBundle() {
140+
clearLifecycleEventListener();
147141
mCodePush.clearDebugCacheIfNeeded();
148142
try {
149143
// #1) Get the ReactInstanceManager instance, which is what includes the
@@ -159,12 +153,11 @@ private void loadBundle() {
159153
setJSBundle(instanceManager, latestJSBundleFile);
160154

161155
// #3) Get the context creation method and fire it on the UI thread (which RN enforces)
162-
final Method recreateMethod = instanceManager.getClass().getMethod("recreateReactContextInBackground");
163156
new Handler(Looper.getMainLooper()).post(new Runnable() {
164157
@Override
165158
public void run() {
166159
try {
167-
recreateMethod.invoke(instanceManager);
160+
instanceManager.recreateReactContextInBackground();
168161
mCodePush.initializeUpdateAfterRestart();
169162
} catch (Exception e) {
170163
// The recreation method threw an unknown exception
@@ -181,6 +174,14 @@ public void run() {
181174
}
182175
}
183176

177+
private void clearLifecycleEventListener() {
178+
// Remove LifecycleEventListener to prevent infinite restart loop
179+
if (mLifecycleEventListener != null) {
180+
getReactApplicationContext().removeLifecycleEventListener(mLifecycleEventListener);
181+
mLifecycleEventListener = null;
182+
}
183+
}
184+
184185
// Use reflection to find the ReactInstanceManager. See #556 for a proposal for a less brittle way to approach this.
185186
private ReactInstanceManager resolveInstanceManager() throws NoSuchFieldException, IllegalAccessException {
186187
ReactInstanceManager instanceManager = CodePush.getReactInstanceManager();
@@ -192,37 +193,11 @@ private ReactInstanceManager resolveInstanceManager() throws NoSuchFieldExceptio
192193
if (currentActivity == null) {
193194
return null;
194195
}
195-
try {
196-
// In RN >=0.29, the "mReactInstanceManager" field yields a null value, so we try
197-
// to get the instance manager via the ReactNativeHost, which only exists in 0.29.
198-
Method getApplicationMethod = ReactActivity.class.getMethod("getApplication");
199-
Object reactApplication = getApplicationMethod.invoke(currentActivity);
200-
Class<?> reactApplicationClass = tryGetClass(REACT_APPLICATION_CLASS_NAME);
201-
Method getReactNativeHostMethod = reactApplicationClass.getMethod("getReactNativeHost");
202-
Object reactNativeHost = getReactNativeHostMethod.invoke(reactApplication);
203-
Class<?> reactNativeHostClass = tryGetClass(REACT_NATIVE_HOST_CLASS_NAME);
204-
Method getReactInstanceManagerMethod = reactNativeHostClass.getMethod("getReactInstanceManager");
205-
instanceManager = (ReactInstanceManager)getReactInstanceManagerMethod.invoke(reactNativeHost);
206-
} catch (Exception e) {
207-
// The React Native version might be older than 0.29, or the activity does not
208-
// extend ReactActivity, so we try to get the instance manager via the
209-
// "mReactInstanceManager" field.
210-
Class instanceManagerHolderClass = currentActivity instanceof ReactActivity
211-
? ReactActivity.class
212-
: currentActivity.getClass();
213-
Field instanceManagerField = instanceManagerHolderClass.getDeclaredField("mReactInstanceManager");
214-
instanceManagerField.setAccessible(true);
215-
instanceManager = (ReactInstanceManager)instanceManagerField.get(currentActivity);
216-
}
217-
return instanceManager;
218-
}
219196

220-
private Class tryGetClass(String className) {
221-
try {
222-
return Class.forName(className);
223-
} catch (ClassNotFoundException e) {
224-
return null;
225-
}
197+
ReactApplication reactApplication = (ReactApplication) currentActivity.getApplication();
198+
instanceManager = reactApplication.getReactNativeHost().getReactInstanceManager();
199+
200+
return instanceManager;
226201
}
227202

228203
@ReactMethod

0 commit comments

Comments
 (0)