@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.
@@ -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
- public class CodePushNativeModule extends BaseJavaModule {
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 CodePush mCodePush;
56
- private SettingsManager mSettingsManager;
57
- private CodePushTelemetryManager mTelemetryManager;
58
- private CodePushUpdateManager mUpdateManager;
59
-
60
- private boolean _allowed = true;
61
- private boolean _restartInProgress = false;
62
- private ArrayList<Boolean> _restartQueue = new ArrayList<>();
63
-
64
- public CodePushNativeModule(ReactApplicationContext reactContext, CodePush codePush, CodePushUpdateManager codePushUpdateManager, CodePushTelemetryManager codePushTelemetryManager, SettingsManager settingsManager) {
65
- super(reactContext);
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
- @Override
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 = getReactApplicationContext().getCurrentActivity();
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(getReactApplicationContext(), latestJSBundleFile, false);
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(getReactApplicationContext(), latestJSBundleFile, false);
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
- ReactHost reactHost = resolveReactHost();
169
- if (reactHost != null) {
170
- devSupportManager = reactHost.getDevSupportManager();
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
- // This workaround has been implemented in order to fix https://github.com/facebook/react-native/issues/14533
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
- getReactApplicationContext().removeLifecycleEventListener(mLifecycleEventListener);
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 = getReactApplicationContext().getCurrentActivity();
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
- instanceManager = reactApplication.getReactNativeHost().getReactInstanceManager();
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 = getReactApplicationContext().getCurrentActivity();
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
- @ReactMethod
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
- @ReactMethod
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
- @ReactMethod
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
- @ReactMethod
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
- @ReactMethod
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
- getReactApplicationContext().runOnUiQueueThread(new Runnable() {
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
- getReactApplicationContext()
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
- @ReactMethod
483
- public void getConfiguration(Promise promise) {
428
+ void getConfiguration(Promise promise) {
484
429
  try {
485
- WritableMap configMap = Arguments.createMap();
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
- @ReactMethod
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
- if (updateState == CodePushUpdateState.PENDING.getValue() && !currentUpdateIsPending) {
524
- // The caller wanted a pending update
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 (updateState == CodePushUpdateState.RUNNING.getValue() && currentUpdateIsPending) {
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
- @ReactMethod
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
- @ReactMethod
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
- if (installMode == CodePushInstallMode.ON_NEXT_RESUME.getValue() ||
644
- // We also add the resume listener if the installMode is IMMEDIATE, because
645
- // if the current activity is backgrounded, we want to reload the bundle when
646
- // it comes back into the foreground.
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
- // Store the minimum duration on the native module as an instance
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 (installMode == CodePushInstallMode.IMMEDIATE.getValue()
676
- || durationInBackground >= CodePushNativeModule.this.mMinimumBackgroundDuration) {
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 (installMode == CodePushInstallMode.ON_NEXT_SUSPEND.getValue() && mSettingsManager.isPendingUpdate(null)) {
690
- appSuspendHandler.postDelayed(loadBundleRunnable, minimumBackgroundDuration * 1000);
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
- getReactApplicationContext().addLifecycleEventListener(mLifecycleEventListener);
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
- @ReactMethod
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
- @ReactMethod
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
- @ReactMethod
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
- @ReactMethod
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
- @ReactMethod
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
- @ReactMethod
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
- @ReactMethod
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
- @ReactMethod
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
- @ReactMethod
826
- public void addListener(String eventName) {
827
- // Set up any upstream listeners or background tasks as necessary
724
+ void addListener(String eventName) {
725
+ // no-op
828
726
  }
829
727
 
830
- @ReactMethod
831
- public void removeListeners(Integer count) {
832
- // Remove upstream listeners, stop unnecessary background tasks
728
+ void removeListeners(double count) {
729
+ // no-op
833
730
  }
834
731
 
835
- public ReactHostDelegate getReactHostDelegate(ReactHostImpl reactHostImpl) {
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
+