@srcpush/react-native-code-push 1.0.3-develop.5 → 1.0.3-feat-new-arch.1
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/AlertAdapter.js +21 -2
- package/CodePush.js +16 -1
- package/android/app/build.gradle +24 -9
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePush.java +52 -10
- package/android/app/src/main/java/com/microsoft/codepush/react/{CodePushDialog.java → CodePushDialogImpl.java} +28 -28
- package/android/app/src/main/java/com/microsoft/codepush/react/{CodePushNativeModule.java → CodePushNativeModuleImpl.java} +94 -198
- package/android/app/src/newarch/java/com/microsoft/codepush/react/CodePushDialog.java +49 -0
- package/android/app/src/newarch/java/com/microsoft/codepush/react/CodePushNativeModule.java +143 -0
- package/android/app/src/oldarch/java/com/microsoft/codepush/react/CodePushDialog.java +49 -0
- package/android/app/src/oldarch/java/com/microsoft/codepush/react/CodePushNativeModule.java +141 -0
- package/package.json +9 -1
- package/src/specs/NativeCodePush.ts +56 -0
- package/src/specs/NativeCodePushDialog.ts +19 -0
|
@@ -5,6 +5,7 @@ import android.content.SharedPreferences;
|
|
|
5
5
|
import android.os.AsyncTask;
|
|
6
6
|
import android.os.Handler;
|
|
7
7
|
import android.os.Looper;
|
|
8
|
+
import android.view.Choreographer;
|
|
8
9
|
import android.view.View;
|
|
9
10
|
|
|
10
11
|
import androidx.annotation.OptIn;
|
|
@@ -14,12 +15,10 @@ import com.facebook.react.ReactHost;
|
|
|
14
15
|
import com.facebook.react.ReactInstanceManager;
|
|
15
16
|
import com.facebook.react.ReactRootView;
|
|
16
17
|
import com.facebook.react.bridge.Arguments;
|
|
17
|
-
import com.facebook.react.bridge.BaseJavaModule;
|
|
18
18
|
import com.facebook.react.bridge.JSBundleLoader;
|
|
19
19
|
import com.facebook.react.bridge.LifecycleEventListener;
|
|
20
20
|
import com.facebook.react.bridge.Promise;
|
|
21
21
|
import com.facebook.react.bridge.ReactApplicationContext;
|
|
22
|
-
import com.facebook.react.bridge.ReactMethod;
|
|
23
22
|
import com.facebook.react.bridge.ReadableMap;
|
|
24
23
|
import com.facebook.react.bridge.WritableMap;
|
|
25
24
|
import com.facebook.react.common.annotations.UnstableReactNativeAPI;
|
|
@@ -29,7 +28,6 @@ import com.facebook.react.modules.core.ReactChoreographer;
|
|
|
29
28
|
import com.facebook.react.modules.debug.interfaces.DeveloperSettings;
|
|
30
29
|
import com.facebook.react.runtime.ReactHostDelegate;
|
|
31
30
|
import com.facebook.react.runtime.ReactHostImpl;
|
|
32
|
-
import android.view.Choreographer;
|
|
33
31
|
|
|
34
32
|
import org.json.JSONArray;
|
|
35
33
|
import org.json.JSONException;
|
|
@@ -46,30 +44,35 @@ import java.util.Map;
|
|
|
46
44
|
import java.util.UUID;
|
|
47
45
|
|
|
48
46
|
@OptIn(markerClass = UnstableReactNativeAPI.class)
|
|
49
|
-
|
|
47
|
+
final class CodePushNativeModuleImpl {
|
|
50
48
|
private String mBinaryContentsHash = null;
|
|
51
49
|
private String mClientUniqueId = null;
|
|
52
50
|
private LifecycleEventListener mLifecycleEventListener = null;
|
|
53
51
|
private int mMinimumBackgroundDuration = 0;
|
|
54
52
|
|
|
55
|
-
private
|
|
56
|
-
private
|
|
57
|
-
private
|
|
58
|
-
private
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
private
|
|
62
|
-
private
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
53
|
+
private final ReactApplicationContext reactContext;
|
|
54
|
+
private final CodePush mCodePush;
|
|
55
|
+
private final SettingsManager mSettingsManager;
|
|
56
|
+
private final CodePushTelemetryManager mTelemetryManager;
|
|
57
|
+
private final CodePushUpdateManager mUpdateManager;
|
|
58
|
+
|
|
59
|
+
private boolean _allowed = true;
|
|
60
|
+
private boolean _restartInProgress = false;
|
|
61
|
+
private final ArrayList<Boolean> _restartQueue = new ArrayList<>();
|
|
62
|
+
|
|
63
|
+
CodePushNativeModuleImpl(
|
|
64
|
+
ReactApplicationContext reactContext,
|
|
65
|
+
CodePush codePush,
|
|
66
|
+
CodePushUpdateManager codePushUpdateManager,
|
|
67
|
+
CodePushTelemetryManager codePushTelemetryManager,
|
|
68
|
+
SettingsManager settingsManager
|
|
69
|
+
) {
|
|
70
|
+
this.reactContext = reactContext;
|
|
67
71
|
mCodePush = codePush;
|
|
68
72
|
mSettingsManager = settingsManager;
|
|
69
73
|
mTelemetryManager = codePushTelemetryManager;
|
|
70
74
|
mUpdateManager = codePushUpdateManager;
|
|
71
75
|
|
|
72
|
-
// Initialize module state while we have a reference to the current context.
|
|
73
76
|
mBinaryContentsHash = CodePushUpdateUtils.getHashForBinaryContents(reactContext, mCodePush.isDebugMode());
|
|
74
77
|
|
|
75
78
|
SharedPreferences preferences = codePush.getContext().getSharedPreferences(CodePushConstants.CODE_PUSH_PREFERENCES, 0);
|
|
@@ -80,8 +83,7 @@ public class CodePushNativeModule extends BaseJavaModule {
|
|
|
80
83
|
}
|
|
81
84
|
}
|
|
82
85
|
|
|
83
|
-
|
|
84
|
-
public Map<String, Object> getConstants() {
|
|
86
|
+
Map<String, Object> getConstants() {
|
|
85
87
|
final Map<String, Object> constants = new HashMap<>();
|
|
86
88
|
|
|
87
89
|
constants.put("codePushInstallModeImmediate", CodePushInstallMode.IMMEDIATE.getValue());
|
|
@@ -96,16 +98,9 @@ public class CodePushNativeModule extends BaseJavaModule {
|
|
|
96
98
|
return constants;
|
|
97
99
|
}
|
|
98
100
|
|
|
99
|
-
@Override
|
|
100
|
-
public String getName() {
|
|
101
|
-
return "CodePush";
|
|
102
|
-
}
|
|
103
|
-
|
|
104
101
|
private void loadBundleLegacy() {
|
|
105
|
-
final Activity currentActivity =
|
|
102
|
+
final Activity currentActivity = reactContext.getCurrentActivity();
|
|
106
103
|
if (currentActivity == null) {
|
|
107
|
-
// The currentActivity can be null if it is backgrounded / destroyed, so we simply
|
|
108
|
-
// no-op to prevent any null pointer exceptions.
|
|
109
104
|
return;
|
|
110
105
|
}
|
|
111
106
|
mCodePush.invalidateCurrentInstance();
|
|
@@ -118,13 +113,11 @@ public class CodePushNativeModule extends BaseJavaModule {
|
|
|
118
113
|
});
|
|
119
114
|
}
|
|
120
115
|
|
|
121
|
-
// Use reflection to find and set the appropriate fields on ReactInstanceManager. See #556 for a proposal for a less brittle way
|
|
122
|
-
// to approach this.
|
|
123
116
|
private void setJSBundle(ReactInstanceManager instanceManager, String latestJSBundleFile) throws IllegalAccessException {
|
|
124
117
|
try {
|
|
125
118
|
JSBundleLoader latestJSBundleLoader;
|
|
126
119
|
if (latestJSBundleFile.toLowerCase().startsWith("assets://")) {
|
|
127
|
-
latestJSBundleLoader = JSBundleLoader.createAssetLoader(
|
|
120
|
+
latestJSBundleLoader = JSBundleLoader.createAssetLoader(reactContext, latestJSBundleFile, false);
|
|
128
121
|
} else {
|
|
129
122
|
latestJSBundleLoader = JSBundleLoader.createFileLoader(latestJSBundleFile);
|
|
130
123
|
}
|
|
@@ -138,13 +131,11 @@ public class CodePushNativeModule extends BaseJavaModule {
|
|
|
138
131
|
}
|
|
139
132
|
}
|
|
140
133
|
|
|
141
|
-
// Use reflection to find and set the appropriate fields on ReactHostDelegate. See #556 for a proposal for a less brittle way
|
|
142
|
-
// to approach this.
|
|
143
134
|
private void setJSBundle(ReactHostDelegate reactHostDelegate, String latestJSBundleFile) throws IllegalAccessException {
|
|
144
135
|
try {
|
|
145
136
|
JSBundleLoader latestJSBundleLoader;
|
|
146
137
|
if (latestJSBundleFile.toLowerCase().startsWith("assets://")) {
|
|
147
|
-
latestJSBundleLoader = JSBundleLoader.createAssetLoader(
|
|
138
|
+
latestJSBundleLoader = JSBundleLoader.createAssetLoader(reactContext, latestJSBundleFile, false);
|
|
148
139
|
} else {
|
|
149
140
|
latestJSBundleLoader = JSBundleLoader.createFileLoader(latestJSBundleFile);
|
|
150
141
|
}
|
|
@@ -161,54 +152,42 @@ public class CodePushNativeModule extends BaseJavaModule {
|
|
|
161
152
|
private void loadBundle() {
|
|
162
153
|
clearLifecycleEventListener();
|
|
163
154
|
|
|
164
|
-
// ReactNative core components are changed on new architecture.
|
|
165
155
|
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
|
|
166
156
|
try {
|
|
167
157
|
DevSupportManager devSupportManager = null;
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
158
|
+
ReactHost reactHost = resolveReactHost();
|
|
159
|
+
if (reactHost != null) {
|
|
160
|
+
devSupportManager = reactHost.getDevSupportManager();
|
|
161
|
+
}
|
|
172
162
|
boolean isLiveReloadEnabled = isLiveReloadEnabled(devSupportManager);
|
|
173
|
-
|
|
174
163
|
mCodePush.clearDebugCacheIfNeeded(isLiveReloadEnabled);
|
|
175
|
-
} catch(Exception e) {
|
|
176
|
-
// If we got error in out reflection we should clear debug cache anyway.
|
|
164
|
+
} catch (Exception e) {
|
|
177
165
|
mCodePush.clearDebugCacheIfNeeded(false);
|
|
178
166
|
}
|
|
179
167
|
|
|
180
168
|
try {
|
|
181
|
-
// #1) Get the ReactHost instance, which is what includes the
|
|
182
|
-
// logic to reload the current React context.
|
|
183
169
|
final ReactHost reactHost = resolveReactHost();
|
|
184
170
|
if (reactHost == null) {
|
|
185
171
|
return;
|
|
186
172
|
}
|
|
187
173
|
|
|
188
174
|
String latestJSBundleFile = mCodePush.getJSBundleFileInternal(mCodePush.getAssetsBundleFileName());
|
|
175
|
+
ReactHostDelegate delegate = getReactHostDelegate((ReactHostImpl) reactHost);
|
|
176
|
+
if (delegate != null) {
|
|
177
|
+
setJSBundle(delegate, latestJSBundleFile);
|
|
178
|
+
}
|
|
189
179
|
|
|
190
|
-
// #2) Update the locally stored JS bundle file path
|
|
191
|
-
setJSBundle(getReactHostDelegate((ReactHostImpl) reactHost), latestJSBundleFile);
|
|
192
|
-
|
|
193
|
-
// #3) Get the context creation method
|
|
194
180
|
try {
|
|
195
181
|
reactHost.reload("CodePush triggers reload");
|
|
196
182
|
mCodePush.initializeUpdateAfterRestart();
|
|
197
183
|
} catch (Exception e) {
|
|
198
|
-
// The recreation method threw an unknown exception
|
|
199
|
-
// so just simply fallback to restarting the Activity (if it exists)
|
|
200
184
|
loadBundleLegacy();
|
|
201
185
|
}
|
|
202
|
-
|
|
203
186
|
} catch (Exception e) {
|
|
204
|
-
// Our reflection logic failed somewhere
|
|
205
|
-
// so fall back to restarting the Activity (if it exists)
|
|
206
187
|
CodePushUtils.log("Failed to load the bundle, falling back to restarting the Activity (if it exists). " + e.getMessage());
|
|
207
188
|
loadBundleLegacy();
|
|
208
189
|
}
|
|
209
|
-
|
|
210
190
|
} else {
|
|
211
|
-
|
|
212
191
|
try {
|
|
213
192
|
DevSupportManager devSupportManager = null;
|
|
214
193
|
ReactInstanceManager reactInstanceManager = resolveInstanceManager();
|
|
@@ -216,53 +195,35 @@ public class CodePushNativeModule extends BaseJavaModule {
|
|
|
216
195
|
devSupportManager = reactInstanceManager.getDevSupportManager();
|
|
217
196
|
}
|
|
218
197
|
boolean isLiveReloadEnabled = isLiveReloadEnabled(devSupportManager);
|
|
219
|
-
|
|
220
198
|
mCodePush.clearDebugCacheIfNeeded(isLiveReloadEnabled);
|
|
221
|
-
} catch(Exception e) {
|
|
222
|
-
// If we got error in out reflection we should clear debug cache anyway.
|
|
199
|
+
} catch (Exception e) {
|
|
223
200
|
mCodePush.clearDebugCacheIfNeeded(false);
|
|
224
201
|
}
|
|
225
202
|
|
|
226
203
|
try {
|
|
227
|
-
// #1) Get the ReactInstanceManager instance, which is what includes the
|
|
228
|
-
// logic to reload the current React context.
|
|
229
204
|
final ReactInstanceManager instanceManager = resolveInstanceManager();
|
|
230
205
|
if (instanceManager == null) {
|
|
231
206
|
return;
|
|
232
207
|
}
|
|
233
208
|
|
|
234
209
|
String latestJSBundleFile = mCodePush.getJSBundleFileInternal(mCodePush.getAssetsBundleFileName());
|
|
235
|
-
|
|
236
|
-
// #2) Update the locally stored JS bundle file path
|
|
237
210
|
setJSBundle(instanceManager, latestJSBundleFile);
|
|
238
211
|
|
|
239
|
-
// #3) Get the context creation method and fire it on the UI thread (which RN enforces)
|
|
240
212
|
new Handler(Looper.getMainLooper()).post(new Runnable() {
|
|
241
213
|
@Override
|
|
242
214
|
public void run() {
|
|
243
215
|
try {
|
|
244
|
-
// We don't need to resetReactRootViews anymore
|
|
245
|
-
// due the issue https://github.com/facebook/react-native/issues/14533
|
|
246
|
-
// has been fixed in RN 0.46.0
|
|
247
|
-
//resetReactRootViews(instanceManager);
|
|
248
|
-
|
|
249
216
|
instanceManager.recreateReactContextInBackground();
|
|
250
217
|
mCodePush.initializeUpdateAfterRestart();
|
|
251
218
|
} catch (Exception e) {
|
|
252
|
-
// The recreation method threw an unknown exception
|
|
253
|
-
// so just simply fallback to restarting the Activity (if it exists)
|
|
254
219
|
loadBundleLegacy();
|
|
255
220
|
}
|
|
256
221
|
}
|
|
257
222
|
});
|
|
258
|
-
|
|
259
223
|
} catch (Exception e) {
|
|
260
|
-
// Our reflection logic failed somewhere
|
|
261
|
-
// so fall back to restarting the Activity (if it exists)
|
|
262
224
|
CodePushUtils.log("Failed to load the bundle, falling back to restarting the Activity (if it exists). " + e.getMessage());
|
|
263
225
|
loadBundleLegacy();
|
|
264
226
|
}
|
|
265
|
-
|
|
266
227
|
}
|
|
267
228
|
}
|
|
268
229
|
|
|
@@ -284,13 +245,11 @@ public class CodePushNativeModule extends BaseJavaModule {
|
|
|
284
245
|
return false;
|
|
285
246
|
}
|
|
286
247
|
|
|
287
|
-
|
|
288
|
-
// resetReactRootViews allows to call recreateReactContextInBackground without any exceptions
|
|
289
|
-
// This fix also relates to https://github.com/microsoft/react-native-code-push/issues/878
|
|
248
|
+
@SuppressWarnings("unused")
|
|
290
249
|
private void resetReactRootViews(ReactInstanceManager instanceManager) throws NoSuchFieldException, IllegalAccessException {
|
|
291
250
|
Field mAttachedRootViewsField = instanceManager.getClass().getDeclaredField("mAttachedRootViews");
|
|
292
251
|
mAttachedRootViewsField.setAccessible(true);
|
|
293
|
-
List<ReactRootView> mAttachedRootViews = (List<ReactRootView>)mAttachedRootViewsField.get(instanceManager);
|
|
252
|
+
List<ReactRootView> mAttachedRootViews = (List<ReactRootView>) mAttachedRootViewsField.get(instanceManager);
|
|
294
253
|
for (ReactRootView reactRootView : mAttachedRootViews) {
|
|
295
254
|
reactRootView.removeAllViews();
|
|
296
255
|
reactRootView.setId(View.NO_ID);
|
|
@@ -299,29 +258,25 @@ public class CodePushNativeModule extends BaseJavaModule {
|
|
|
299
258
|
}
|
|
300
259
|
|
|
301
260
|
private void clearLifecycleEventListener() {
|
|
302
|
-
// Remove LifecycleEventListener to prevent infinite restart loop
|
|
303
261
|
if (mLifecycleEventListener != null) {
|
|
304
|
-
|
|
262
|
+
reactContext.removeLifecycleEventListener(mLifecycleEventListener);
|
|
305
263
|
mLifecycleEventListener = null;
|
|
306
264
|
}
|
|
307
265
|
}
|
|
308
266
|
|
|
309
|
-
// Use reflection to find the ReactInstanceManager. See #556 for a proposal for a less brittle way to approach this.
|
|
310
267
|
private ReactInstanceManager resolveInstanceManager() throws NoSuchFieldException, IllegalAccessException {
|
|
311
268
|
ReactInstanceManager instanceManager = CodePush.getReactInstanceManager();
|
|
312
269
|
if (instanceManager != null) {
|
|
313
270
|
return instanceManager;
|
|
314
271
|
}
|
|
315
272
|
|
|
316
|
-
final Activity currentActivity =
|
|
273
|
+
final Activity currentActivity = reactContext.getCurrentActivity();
|
|
317
274
|
if (currentActivity == null) {
|
|
318
275
|
return null;
|
|
319
276
|
}
|
|
320
277
|
|
|
321
278
|
ReactApplication reactApplication = (ReactApplication) currentActivity.getApplication();
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
return instanceManager;
|
|
279
|
+
return reactApplication.getReactNativeHost().getReactInstanceManager();
|
|
325
280
|
}
|
|
326
281
|
|
|
327
282
|
private ReactHost resolveReactHost() throws NoSuchFieldException, IllegalAccessException {
|
|
@@ -330,7 +285,7 @@ public class CodePushNativeModule extends BaseJavaModule {
|
|
|
330
285
|
return reactHost;
|
|
331
286
|
}
|
|
332
287
|
|
|
333
|
-
final Activity currentActivity =
|
|
288
|
+
final Activity currentActivity = reactContext.getCurrentActivity();
|
|
334
289
|
if (currentActivity == null) {
|
|
335
290
|
return null;
|
|
336
291
|
}
|
|
@@ -365,8 +320,7 @@ public class CodePushNativeModule extends BaseJavaModule {
|
|
|
365
320
|
}
|
|
366
321
|
}
|
|
367
322
|
|
|
368
|
-
|
|
369
|
-
public void allow(Promise promise) {
|
|
323
|
+
void allow(Promise promise) {
|
|
370
324
|
CodePushUtils.log("Re-allowing restarts");
|
|
371
325
|
this._allowed = true;
|
|
372
326
|
|
|
@@ -378,37 +332,30 @@ public class CodePushNativeModule extends BaseJavaModule {
|
|
|
378
332
|
}
|
|
379
333
|
|
|
380
334
|
promise.resolve(null);
|
|
381
|
-
return;
|
|
382
335
|
}
|
|
383
336
|
|
|
384
|
-
|
|
385
|
-
public void clearPendingRestart(Promise promise) {
|
|
337
|
+
void clearPendingRestart(Promise promise) {
|
|
386
338
|
this._restartQueue.clear();
|
|
387
339
|
promise.resolve(null);
|
|
388
|
-
return;
|
|
389
340
|
}
|
|
390
341
|
|
|
391
|
-
|
|
392
|
-
public void disallow(Promise promise) {
|
|
342
|
+
void disallow(Promise promise) {
|
|
393
343
|
CodePushUtils.log("Disallowing restarts");
|
|
394
344
|
this._allowed = false;
|
|
395
345
|
promise.resolve(null);
|
|
396
|
-
return;
|
|
397
346
|
}
|
|
398
347
|
|
|
399
|
-
|
|
400
|
-
public void restartApp(boolean onlyIfUpdateIsPending, Promise promise) {
|
|
348
|
+
void restartApp(boolean onlyIfUpdateIsPending, Promise promise) {
|
|
401
349
|
try {
|
|
402
350
|
restartAppInternal(onlyIfUpdateIsPending);
|
|
403
351
|
promise.resolve(null);
|
|
404
|
-
} catch(CodePushUnknownException e) {
|
|
352
|
+
} catch (CodePushUnknownException e) {
|
|
405
353
|
CodePushUtils.log(e);
|
|
406
354
|
promise.reject(e);
|
|
407
355
|
}
|
|
408
356
|
}
|
|
409
357
|
|
|
410
|
-
|
|
411
|
-
public void downloadUpdate(final ReadableMap updatePackage, final boolean notifyProgress, final Promise promise) {
|
|
358
|
+
void downloadUpdate(final ReadableMap updatePackage, final boolean notifyProgress, final Promise promise) {
|
|
412
359
|
AsyncTask<Void, Void, Void> asyncTask = new AsyncTask<Void, Void, Void>() {
|
|
413
360
|
@Override
|
|
414
361
|
protected Void doInBackground(Void... params) {
|
|
@@ -426,7 +373,6 @@ public class CodePushNativeModule extends BaseJavaModule {
|
|
|
426
373
|
}
|
|
427
374
|
|
|
428
375
|
latestDownloadProgress = downloadProgress;
|
|
429
|
-
// If the download is completed, synchronously send the last event.
|
|
430
376
|
if (latestDownloadProgress.isCompleted()) {
|
|
431
377
|
dispatchDownloadProgressEvent();
|
|
432
378
|
return;
|
|
@@ -437,7 +383,7 @@ public class CodePushNativeModule extends BaseJavaModule {
|
|
|
437
383
|
}
|
|
438
384
|
|
|
439
385
|
hasScheduledNextFrame = true;
|
|
440
|
-
|
|
386
|
+
reactContext.runOnUiQueueThread(new Runnable() {
|
|
441
387
|
@Override
|
|
442
388
|
public void run() {
|
|
443
389
|
ReactChoreographer.getInstance().postFrameCallback(ReactChoreographer.CallbackType.TIMERS_EVENTS, new Choreographer.FrameCallback() {
|
|
@@ -455,7 +401,7 @@ public class CodePushNativeModule extends BaseJavaModule {
|
|
|
455
401
|
}
|
|
456
402
|
|
|
457
403
|
public void dispatchDownloadProgressEvent() {
|
|
458
|
-
|
|
404
|
+
reactContext
|
|
459
405
|
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
|
|
460
406
|
.emit(CodePushConstants.DOWNLOAD_PROGRESS_EVENT_NAME, latestDownloadProgress.createWritableMap());
|
|
461
407
|
}
|
|
@@ -479,29 +425,26 @@ public class CodePushNativeModule extends BaseJavaModule {
|
|
|
479
425
|
asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
480
426
|
}
|
|
481
427
|
|
|
482
|
-
|
|
483
|
-
public void getConfiguration(Promise promise) {
|
|
428
|
+
void getConfiguration(Promise promise) {
|
|
484
429
|
try {
|
|
485
|
-
WritableMap configMap =
|
|
430
|
+
WritableMap configMap = Arguments.createMap();
|
|
486
431
|
configMap.putString("appVersion", mCodePush.getAppVersion());
|
|
487
432
|
configMap.putString("clientUniqueId", mClientUniqueId);
|
|
488
433
|
configMap.putString("deploymentKey", mCodePush.getDeploymentKey());
|
|
489
434
|
configMap.putString("serverUrl", mCodePush.getServerUrl());
|
|
490
435
|
|
|
491
|
-
// The binary hash may be null in debug builds
|
|
492
436
|
if (mBinaryContentsHash != null) {
|
|
493
437
|
configMap.putString(CodePushConstants.PACKAGE_HASH_KEY, mBinaryContentsHash);
|
|
494
438
|
}
|
|
495
439
|
|
|
496
440
|
promise.resolve(configMap);
|
|
497
|
-
} catch(CodePushUnknownException e) {
|
|
441
|
+
} catch (CodePushUnknownException e) {
|
|
498
442
|
CodePushUtils.log(e);
|
|
499
443
|
promise.reject(e);
|
|
500
444
|
}
|
|
501
445
|
}
|
|
502
446
|
|
|
503
|
-
|
|
504
|
-
public void getUpdateMetadata(final int updateState, final Promise promise) {
|
|
447
|
+
void getUpdateMetadata(final double updateState, final Promise promise) {
|
|
505
448
|
AsyncTask<Void, Void, Void> asyncTask = new AsyncTask<Void, Void, Void>() {
|
|
506
449
|
@Override
|
|
507
450
|
protected Void doInBackground(Void... params) {
|
|
@@ -520,43 +463,29 @@ public class CodePushNativeModule extends BaseJavaModule {
|
|
|
520
463
|
currentUpdateIsPending = mSettingsManager.isPendingUpdate(currentHash);
|
|
521
464
|
}
|
|
522
465
|
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
// but there isn't currently one.
|
|
466
|
+
int updateStateValue = (int) updateState;
|
|
467
|
+
if (updateStateValue == CodePushUpdateState.PENDING.getValue() && !currentUpdateIsPending) {
|
|
526
468
|
promise.resolve(null);
|
|
527
|
-
} else if (
|
|
528
|
-
// The caller wants the running update, but the current
|
|
529
|
-
// one is pending, so we need to grab the previous.
|
|
469
|
+
} else if (updateStateValue == CodePushUpdateState.RUNNING.getValue() && currentUpdateIsPending) {
|
|
530
470
|
JSONObject previousPackage = mUpdateManager.getPreviousPackage();
|
|
531
|
-
|
|
532
471
|
if (previousPackage == null) {
|
|
533
472
|
promise.resolve(null);
|
|
534
473
|
return null;
|
|
535
474
|
}
|
|
536
|
-
|
|
537
475
|
promise.resolve(CodePushUtils.convertJsonObjectToWritable(previousPackage));
|
|
538
476
|
} else {
|
|
539
|
-
// The current package satisfies the request:
|
|
540
|
-
// 1) Caller wanted a pending, and there is a pending update
|
|
541
|
-
// 2) Caller wanted the running update, and there isn't a pending
|
|
542
|
-
// 3) Caller wants the latest update, regardless if it's pending or not
|
|
543
477
|
if (mCodePush.isRunningBinaryVersion()) {
|
|
544
|
-
// This only matters in Debug builds. Since we do not clear "outdated" updates,
|
|
545
|
-
// we need to indicate to the JS side that somehow we have a current update on
|
|
546
|
-
// disk that is not actually running.
|
|
547
478
|
CodePushUtils.setJSONValueForKey(currentPackage, "_isDebugOnly", true);
|
|
548
479
|
}
|
|
549
480
|
|
|
550
|
-
// Enable differentiating pending vs. non-pending updates
|
|
551
481
|
CodePushUtils.setJSONValueForKey(currentPackage, "isPending", currentUpdateIsPending);
|
|
552
482
|
promise.resolve(CodePushUtils.convertJsonObjectToWritable(currentPackage));
|
|
553
483
|
}
|
|
554
484
|
} catch (CodePushMalformedDataException e) {
|
|
555
|
-
// We need to recover the app in case 'codepush.json' is corrupted
|
|
556
485
|
CodePushUtils.log(e.getMessage());
|
|
557
486
|
clearUpdates();
|
|
558
487
|
promise.resolve(null);
|
|
559
|
-
} catch(CodePushUnknownException e) {
|
|
488
|
+
} catch (CodePushUnknownException e) {
|
|
560
489
|
CodePushUtils.log(e);
|
|
561
490
|
promise.reject(e);
|
|
562
491
|
}
|
|
@@ -568,8 +497,7 @@ public class CodePushNativeModule extends BaseJavaModule {
|
|
|
568
497
|
asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
569
498
|
}
|
|
570
499
|
|
|
571
|
-
|
|
572
|
-
public void getNewStatusReport(final Promise promise) {
|
|
500
|
+
void getNewStatusReport(final Promise promise) {
|
|
573
501
|
AsyncTask<Void, Void, Void> asyncTask = new AsyncTask<Void, Void, Void>() {
|
|
574
502
|
@Override
|
|
575
503
|
protected Void doInBackground(Void... params) {
|
|
@@ -613,8 +541,8 @@ public class CodePushNativeModule extends BaseJavaModule {
|
|
|
613
541
|
}
|
|
614
542
|
}
|
|
615
543
|
|
|
616
|
-
promise.resolve(
|
|
617
|
-
} catch(CodePushUnknownException e) {
|
|
544
|
+
promise.resolve(null);
|
|
545
|
+
} catch (CodePushUnknownException e) {
|
|
618
546
|
CodePushUtils.log(e);
|
|
619
547
|
promise.reject(e);
|
|
620
548
|
}
|
|
@@ -625,8 +553,7 @@ public class CodePushNativeModule extends BaseJavaModule {
|
|
|
625
553
|
asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
626
554
|
}
|
|
627
555
|
|
|
628
|
-
|
|
629
|
-
public void installUpdate(final ReadableMap updatePackage, final int installMode, final int minimumBackgroundDuration, final Promise promise) {
|
|
556
|
+
void installUpdate(final ReadableMap updatePackage, final double installMode, final double minimumBackgroundDuration, final Promise promise) {
|
|
630
557
|
AsyncTask<Void, Void, Void> asyncTask = new AsyncTask<Void, Void, Void>() {
|
|
631
558
|
@Override
|
|
632
559
|
protected Void doInBackground(Void... params) {
|
|
@@ -637,23 +564,17 @@ public class CodePushNativeModule extends BaseJavaModule {
|
|
|
637
564
|
if (pendingHash == null) {
|
|
638
565
|
throw new CodePushUnknownException("Update package to be installed has no hash.");
|
|
639
566
|
} else {
|
|
640
|
-
mSettingsManager.savePendingUpdate(pendingHash, /* isLoading */false);
|
|
567
|
+
mSettingsManager.savePendingUpdate(pendingHash, /* isLoading */ false);
|
|
641
568
|
}
|
|
642
569
|
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
installMode == CodePushInstallMode.IMMEDIATE.getValue() ||
|
|
648
|
-
installMode == CodePushInstallMode.ON_NEXT_SUSPEND.getValue()) {
|
|
570
|
+
int installModeValue = (int) installMode;
|
|
571
|
+
if (installModeValue == CodePushInstallMode.ON_NEXT_RESUME.getValue()
|
|
572
|
+
|| installModeValue == CodePushInstallMode.IMMEDIATE.getValue()
|
|
573
|
+
|| installModeValue == CodePushInstallMode.ON_NEXT_SUSPEND.getValue()) {
|
|
649
574
|
|
|
650
|
-
|
|
651
|
-
// variable instead of relying on a closure below, so that any
|
|
652
|
-
// subsequent resume-based installs could override it.
|
|
653
|
-
CodePushNativeModule.this.mMinimumBackgroundDuration = minimumBackgroundDuration;
|
|
575
|
+
CodePushNativeModuleImpl.this.mMinimumBackgroundDuration = (int) minimumBackgroundDuration;
|
|
654
576
|
|
|
655
577
|
if (mLifecycleEventListener == null) {
|
|
656
|
-
// Ensure we do not add the listener twice.
|
|
657
578
|
mLifecycleEventListener = new LifecycleEventListener() {
|
|
658
579
|
private Date lastPausedDate = null;
|
|
659
580
|
private Handler appSuspendHandler = new Handler(Looper.getMainLooper());
|
|
@@ -668,12 +589,10 @@ public class CodePushNativeModule extends BaseJavaModule {
|
|
|
668
589
|
@Override
|
|
669
590
|
public void onHostResume() {
|
|
670
591
|
appSuspendHandler.removeCallbacks(loadBundleRunnable);
|
|
671
|
-
// As of RN 36, the resume handler fires immediately if the app is in
|
|
672
|
-
// the foreground, so explicitly wait for it to be backgrounded first
|
|
673
592
|
if (lastPausedDate != null) {
|
|
674
593
|
long durationInBackground = (new Date().getTime() - lastPausedDate.getTime()) / 1000;
|
|
675
|
-
if (
|
|
676
|
-
|| durationInBackground >=
|
|
594
|
+
if (installModeValue == CodePushInstallMode.IMMEDIATE.getValue()
|
|
595
|
+
|| durationInBackground >= CodePushNativeModuleImpl.this.mMinimumBackgroundDuration) {
|
|
677
596
|
CodePushUtils.log("Loading bundle on resume");
|
|
678
597
|
restartAppInternal(false);
|
|
679
598
|
}
|
|
@@ -682,12 +601,10 @@ public class CodePushNativeModule extends BaseJavaModule {
|
|
|
682
601
|
|
|
683
602
|
@Override
|
|
684
603
|
public void onHostPause() {
|
|
685
|
-
// Save the current time so that when the app is later
|
|
686
|
-
// resumed, we can detect how long it was in the background.
|
|
687
604
|
lastPausedDate = new Date();
|
|
688
605
|
|
|
689
|
-
if (
|
|
690
|
-
appSuspendHandler.postDelayed(loadBundleRunnable,
|
|
606
|
+
if (installModeValue == CodePushInstallMode.ON_NEXT_SUSPEND.getValue() && mSettingsManager.isPendingUpdate(null)) {
|
|
607
|
+
appSuspendHandler.postDelayed(loadBundleRunnable, CodePushNativeModuleImpl.this.mMinimumBackgroundDuration * 1000L);
|
|
691
608
|
}
|
|
692
609
|
}
|
|
693
610
|
|
|
@@ -696,12 +613,12 @@ public class CodePushNativeModule extends BaseJavaModule {
|
|
|
696
613
|
}
|
|
697
614
|
};
|
|
698
615
|
|
|
699
|
-
|
|
616
|
+
reactContext.addLifecycleEventListener(mLifecycleEventListener);
|
|
700
617
|
}
|
|
701
618
|
}
|
|
702
619
|
|
|
703
|
-
promise.resolve(
|
|
704
|
-
} catch(CodePushUnknownException e) {
|
|
620
|
+
promise.resolve(null);
|
|
621
|
+
} catch (CodePushUnknownException e) {
|
|
705
622
|
CodePushUtils.log(e);
|
|
706
623
|
promise.reject(e);
|
|
707
624
|
}
|
|
@@ -713,8 +630,7 @@ public class CodePushNativeModule extends BaseJavaModule {
|
|
|
713
630
|
asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
714
631
|
}
|
|
715
632
|
|
|
716
|
-
|
|
717
|
-
public void isFailedUpdate(String packageHash, Promise promise) {
|
|
633
|
+
void isFailedUpdate(String packageHash, Promise promise) {
|
|
718
634
|
try {
|
|
719
635
|
promise.resolve(mSettingsManager.isFailedHash(packageHash));
|
|
720
636
|
} catch (CodePushUnknownException e) {
|
|
@@ -723,8 +639,7 @@ public class CodePushNativeModule extends BaseJavaModule {
|
|
|
723
639
|
}
|
|
724
640
|
}
|
|
725
641
|
|
|
726
|
-
|
|
727
|
-
public void getLatestRollbackInfo(Promise promise) {
|
|
642
|
+
void getLatestRollbackInfo(Promise promise) {
|
|
728
643
|
try {
|
|
729
644
|
JSONObject latestRollbackInfo = mSettingsManager.getLatestRollbackInfo();
|
|
730
645
|
if (latestRollbackInfo != null) {
|
|
@@ -738,8 +653,7 @@ public class CodePushNativeModule extends BaseJavaModule {
|
|
|
738
653
|
}
|
|
739
654
|
}
|
|
740
655
|
|
|
741
|
-
|
|
742
|
-
public void setLatestRollbackInfo(String packageHash, Promise promise) {
|
|
656
|
+
void setLatestRollbackInfo(String packageHash, Promise promise) {
|
|
743
657
|
try {
|
|
744
658
|
mSettingsManager.setLatestRollbackInfo(packageHash);
|
|
745
659
|
promise.resolve(null);
|
|
@@ -749,53 +663,46 @@ public class CodePushNativeModule extends BaseJavaModule {
|
|
|
749
663
|
}
|
|
750
664
|
}
|
|
751
665
|
|
|
752
|
-
|
|
753
|
-
public void isFirstRun(String packageHash, Promise promise) {
|
|
666
|
+
void isFirstRun(String packageHash, Promise promise) {
|
|
754
667
|
try {
|
|
755
668
|
boolean isFirstRun = mCodePush.didUpdate()
|
|
756
669
|
&& packageHash != null
|
|
757
670
|
&& packageHash.length() > 0
|
|
758
671
|
&& packageHash.equals(mUpdateManager.getCurrentPackageHash());
|
|
759
672
|
promise.resolve(isFirstRun);
|
|
760
|
-
} catch(CodePushUnknownException e) {
|
|
673
|
+
} catch (CodePushUnknownException e) {
|
|
761
674
|
CodePushUtils.log(e);
|
|
762
675
|
promise.reject(e);
|
|
763
676
|
}
|
|
764
677
|
}
|
|
765
678
|
|
|
766
|
-
|
|
767
|
-
public void notifyApplicationReady(Promise promise) {
|
|
679
|
+
void notifyApplicationReady(Promise promise) {
|
|
768
680
|
try {
|
|
769
681
|
mSettingsManager.removePendingUpdate();
|
|
770
|
-
promise.resolve(
|
|
771
|
-
} catch(CodePushUnknownException e) {
|
|
682
|
+
promise.resolve(null);
|
|
683
|
+
} catch (CodePushUnknownException e) {
|
|
772
684
|
CodePushUtils.log(e);
|
|
773
685
|
promise.reject(e);
|
|
774
686
|
}
|
|
775
687
|
}
|
|
776
688
|
|
|
777
|
-
|
|
778
|
-
public void recordStatusReported(ReadableMap statusReport) {
|
|
689
|
+
void recordStatusReported(ReadableMap statusReport) {
|
|
779
690
|
try {
|
|
780
691
|
mTelemetryManager.recordStatusReported(statusReport);
|
|
781
|
-
} catch(CodePushUnknownException e) {
|
|
692
|
+
} catch (CodePushUnknownException e) {
|
|
782
693
|
CodePushUtils.log(e);
|
|
783
694
|
}
|
|
784
695
|
}
|
|
785
696
|
|
|
786
|
-
|
|
787
|
-
public void saveStatusReportForRetry(ReadableMap statusReport) {
|
|
697
|
+
void saveStatusReportForRetry(ReadableMap statusReport) {
|
|
788
698
|
try {
|
|
789
699
|
mTelemetryManager.saveStatusReportForRetry(statusReport);
|
|
790
|
-
} catch(CodePushUnknownException e) {
|
|
700
|
+
} catch (CodePushUnknownException e) {
|
|
791
701
|
CodePushUtils.log(e);
|
|
792
702
|
}
|
|
793
703
|
}
|
|
794
704
|
|
|
795
|
-
|
|
796
|
-
// Replaces the current bundle with the one downloaded from removeBundleUrl.
|
|
797
|
-
// It is only to be used during tests. No-ops if the test configuration flag is not set.
|
|
798
|
-
public void downloadAndReplaceCurrentBundle(String remoteBundleUrl) {
|
|
705
|
+
void downloadAndReplaceCurrentBundle(String remoteBundleUrl) {
|
|
799
706
|
try {
|
|
800
707
|
if (mCodePush.isUsingTestConfiguration()) {
|
|
801
708
|
try {
|
|
@@ -804,41 +711,29 @@ public class CodePushNativeModule extends BaseJavaModule {
|
|
|
804
711
|
throw new CodePushUnknownException("Unable to replace current bundle", e);
|
|
805
712
|
}
|
|
806
713
|
}
|
|
807
|
-
} catch(CodePushUnknownException | CodePushMalformedDataException e) {
|
|
714
|
+
} catch (CodePushUnknownException | CodePushMalformedDataException e) {
|
|
808
715
|
CodePushUtils.log(e);
|
|
809
716
|
}
|
|
810
717
|
}
|
|
811
718
|
|
|
812
|
-
|
|
813
|
-
* This method clears CodePush's downloaded updates.
|
|
814
|
-
* It is needed to switch to a different deployment if the current deployment is more recent.
|
|
815
|
-
* Note: we don’t recommend to use this method in scenarios other than that (CodePush will call
|
|
816
|
-
* this method automatically when needed in other cases) as it could lead to unpredictable
|
|
817
|
-
* behavior.
|
|
818
|
-
*/
|
|
819
|
-
@ReactMethod
|
|
820
|
-
public void clearUpdates() {
|
|
719
|
+
void clearUpdates() {
|
|
821
720
|
CodePushUtils.log("Clearing updates.");
|
|
822
721
|
mCodePush.clearUpdates();
|
|
823
722
|
}
|
|
824
723
|
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
// Set up any upstream listeners or background tasks as necessary
|
|
724
|
+
void addListener(String eventName) {
|
|
725
|
+
// no-op
|
|
828
726
|
}
|
|
829
727
|
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
// Remove upstream listeners, stop unnecessary background tasks
|
|
728
|
+
void removeListeners(double count) {
|
|
729
|
+
// no-op
|
|
833
730
|
}
|
|
834
731
|
|
|
835
|
-
|
|
732
|
+
ReactHostDelegate getReactHostDelegate(ReactHostImpl reactHostImpl) {
|
|
836
733
|
try {
|
|
837
734
|
Class<?> clazz = reactHostImpl.getClass();
|
|
838
735
|
Field field = clazz.getDeclaredField("mReactHostDelegate");
|
|
839
736
|
field.setAccessible(true);
|
|
840
|
-
|
|
841
|
-
// Get the value of the field for the provided instance
|
|
842
737
|
return (ReactHostDelegate) field.get(reactHostImpl);
|
|
843
738
|
} catch (NoSuchFieldException | IllegalAccessException e) {
|
|
844
739
|
e.printStackTrace();
|
|
@@ -846,3 +741,4 @@ public class CodePushNativeModule extends BaseJavaModule {
|
|
|
846
741
|
}
|
|
847
742
|
}
|
|
848
743
|
}
|
|
744
|
+
|