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

Commit b1f32a9

Browse files
committed
Merge pull request #306 from Microsoft/fix-305
Fix - App crashes when backgrounded before an app is installed
2 parents 25f313a + 3e29100 commit b1f32a9

File tree

3 files changed

+38
-30
lines changed

3 files changed

+38
-30
lines changed

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

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,10 @@ public CodePush(String deploymentKey, Activity mainActivity, boolean isDebugMode
107107
}
108108

109109
currentInstance = this;
110-
110+
111111
clearDebugCacheIfNeeded();
112112
}
113-
113+
114114
private void clearDebugCacheIfNeeded() {
115115
if (isDebugMode && isPendingUpdate(null)) {
116116
// This needs to be kept in sync with https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManager.java#L78
@@ -120,7 +120,7 @@ private void clearDebugCacheIfNeeded() {
120120
}
121121
}
122122
}
123-
123+
124124
private long getBinaryResourcesModifiedTime() {
125125
ZipFile applicationFile = null;
126126
try {
@@ -144,15 +144,15 @@ private long getBinaryResourcesModifiedTime() {
144144
public static String getBundleUrl() {
145145
return getBundleUrl(DEFAULT_JS_BUNDLE_NAME);
146146
}
147-
147+
148148
public static String getBundleUrl(String assetsBundleFileName) {
149149
if (currentInstance == null) {
150150
throw new CodePushNotInitializedException("A CodePush instance has not been created yet. Have you added it to your app's list of ReactPackages?");
151151
}
152152

153153
return currentInstance.getBundleUrlInternal(assetsBundleFileName);
154154
}
155-
155+
156156
public String getBundleUrlInternal(String assetsBundleFileName) {
157157
this.assetsBundleFileName = assetsBundleFileName;
158158
String binaryJsBundleUrl = ASSETS_BUNDLE_PREFIX + assetsBundleFileName;
@@ -230,7 +230,7 @@ private JSONObject getPendingUpdate() {
230230
return null;
231231
}
232232
}
233-
233+
234234
private void initializeUpdateAfterRestart() {
235235
JSONObject pendingUpdate = getPendingUpdate();
236236
if (pendingUpdate != null) {
@@ -277,7 +277,7 @@ private boolean isFailedHash(String packageHash) {
277277

278278
private boolean isPendingUpdate(String packageHash) {
279279
JSONObject pendingUpdate = getPendingUpdate();
280-
280+
281281
try {
282282
return pendingUpdate != null &&
283283
!pendingUpdate.getBoolean(PENDING_UPDATE_IS_LOADING_KEY) &&
@@ -297,7 +297,7 @@ private void removePendingUpdate() {
297297
SharedPreferences settings = applicationContext.getSharedPreferences(CODE_PUSH_PREFERENCES, 0);
298298
settings.edit().remove(PENDING_UPDATE_KEY).commit();
299299
}
300-
300+
301301
private void rollbackPackage() {
302302
WritableMap failedPackage = codePushPackage.getCurrentPackage();
303303
saveFailedUpdate(failedPackage);
@@ -357,47 +357,47 @@ public void clearUpdates() {
357357
private class CodePushNativeModule extends ReactContextBaseJavaModule {
358358
private LifecycleEventListener lifecycleEventListener = null;
359359
private int minimumBackgroundDuration = 0;
360-
360+
361361
public CodePushNativeModule(ReactApplicationContext reactContext) {
362362
super(reactContext);
363363
}
364-
364+
365365
@Override
366366
public Map<String, Object> getConstants() {
367367
final Map<String, Object> constants = new HashMap<>();
368-
368+
369369
constants.put("codePushInstallModeImmediate", CodePushInstallMode.IMMEDIATE.getValue());
370370
constants.put("codePushInstallModeOnNextRestart", CodePushInstallMode.ON_NEXT_RESTART.getValue());
371371
constants.put("codePushInstallModeOnNextResume", CodePushInstallMode.ON_NEXT_RESUME.getValue());
372-
372+
373373
constants.put("codePushUpdateStateRunning", CodePushUpdateState.RUNNING.getValue());
374374
constants.put("codePushUpdateStatePending", CodePushUpdateState.PENDING.getValue());
375375
constants.put("codePushUpdateStateLatest", CodePushUpdateState.LATEST.getValue());
376-
376+
377377
return constants;
378378
}
379379

380380
@Override
381381
public String getName() {
382382
return "CodePush";
383383
}
384-
384+
385385
@Override
386386
public void initialize() {
387387
CodePush.this.initializeUpdateAfterRestart();
388388
}
389-
389+
390390
private void loadBundleLegacy() {
391391
Intent intent = mainActivity.getIntent();
392392
mainActivity.finish();
393393
mainActivity.startActivity(intent);
394-
394+
395395
currentInstance = null;
396396
}
397-
397+
398398
private void loadBundle() {
399399
CodePush.this.clearDebugCacheIfNeeded();
400-
400+
401401
try {
402402
// #1) Get the private ReactInstanceManager, which is what includes
403403
// the logic to reload the current React context.
@@ -410,7 +410,7 @@ private void loadBundle() {
410410
Field jsBundleField = instanceManager.getClass().getDeclaredField("mJSBundleFile");
411411
jsBundleField.setAccessible(true);
412412
jsBundleField.set(instanceManager, latestJSBundleFile);
413-
413+
414414
// #3) Get the context creation method and fire it on the UI thread (which RN enforces)
415415
final Method recreateMethod = instanceManager.getClass().getMethod("recreateReactContextInBackground");
416416
mainActivity.runOnUiThread(new Runnable() {
@@ -488,14 +488,14 @@ public void getConfiguration(Promise promise) {
488488

489489
promise.resolve(configMap);
490490
}
491-
491+
492492
@ReactMethod
493493
public void getUpdateMetadata(final int updateState, final Promise promise) {
494494
AsyncTask<Void, Void, Void> asyncTask = new AsyncTask<Void, Void, Void>() {
495495
@Override
496496
protected Void doInBackground(Void... params) {
497497
WritableMap currentPackage = codePushPackage.getCurrentPackage();
498-
498+
499499
if (currentPackage == null) {
500500
promise.resolve("");
501501
return null;
@@ -507,7 +507,7 @@ protected Void doInBackground(Void... params) {
507507
String currentHash = currentPackage.getString(PACKAGE_HASH_KEY);
508508
currentUpdateIsPending = CodePush.this.isPendingUpdate(currentHash);
509509
}
510-
510+
511511
if (updateState == CodePushUpdateState.PENDING.getValue() && !currentUpdateIsPending) {
512512
// The caller wanted a pending update
513513
// but there isn't currently one.
@@ -532,7 +532,7 @@ protected Void doInBackground(Void... params) {
532532
currentPackage.putBoolean("isPending", currentUpdateIsPending);
533533
promise.resolve(currentPackage);
534534
}
535-
535+
536536
return null;
537537
}
538538
};
@@ -615,7 +615,11 @@ protected Void doInBackground(Void... params) {
615615
public void onHostResume() {
616616
// Determine how long the app was in the background and ensure
617617
// that it meets the minimum duration amount of time.
618-
long durationInBackground = (new Date().getTime() - lastPausedDate.getTime()) / 1000;
618+
long durationInBackground = 0;
619+
if (lastPausedDate != null) {
620+
durationInBackground = (new Date().getTime() - lastPausedDate.getTime()) / 1000;
621+
}
622+
619623
if (durationInBackground >= CodePushNativeModule.this.minimumBackgroundDuration) {
620624
loadBundle();
621625
}
@@ -645,7 +649,7 @@ public void onHostDestroy() {
645649

646650
asyncTask.execute();
647651
}
648-
652+
649653
@ReactMethod
650654
public void isFailedUpdate(String packageHash, Promise promise) {
651655
promise.resolve(isFailedHash(packageHash));
@@ -665,7 +669,7 @@ public void notifyApplicationReady(Promise promise) {
665669
removePendingUpdate();
666670
promise.resolve("");
667671
}
668-
672+
669673
@ReactMethod
670674
public void restartApp(boolean onlyIfUpdateIsPending) {
671675
// If this is an unconditional restart request, or there

ios/CodePush/CodePush.m

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ + (void)setUsingTestConfiguration:(BOOL)shouldUseTestConfiguration
175175
/*
176176
* This method is used to clear updates that are installed
177177
* under a different app version and hence don't apply anymore,
178-
* during a debug run configuration and when the bridge is
178+
* during a debug run configuration and when the bridge is
179179
* running the JS bundle from the dev server.
180180
*/
181181
- (void)clearDebugUpdates
@@ -273,7 +273,7 @@ - (void)initializeUpdateAfterRestart
273273
#ifdef DEBUG
274274
[self clearDebugUpdates];
275275
#endif
276-
276+
277277
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
278278
NSDictionary *pendingUpdate = [preferences objectForKey:PendingUpdateKey];
279279
if (pendingUpdate) {
@@ -456,7 +456,11 @@ - (void)applicationWillEnterForeground
456456
{
457457
// Determine how long the app was in the background and ensure
458458
// that it meets the minimum duration amount of time.
459-
int durationInBackground = [[NSDate date] timeIntervalSinceDate:_lastResignedDate];
459+
int durationInBackground = 0;
460+
if (_lastResignedDate) {
461+
durationInBackground = [[NSDate date] timeIntervalSinceDate:_lastResignedDate];
462+
}
463+
460464
if (durationInBackground >= _minimumBackgroundDuration) {
461465
[self loadBundle];
462466
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-native-code-push",
3-
"version": "1.10.3-beta",
3+
"version": "1.10.4-beta",
44
"description": "React Native plugin for the CodePush service",
55
"main": "CodePush.js",
66
"homepage": "https://microsoft.github.io/code-push",

0 commit comments

Comments
 (0)