mirror of
https://github.com/zhigang1992/react-native-code-push.git
synced 2026-06-12 08:59:05 +08:00
Merge pull request #387 from Microsoft/restart-app-2x
fix double restart issue
This commit is contained in:
@@ -61,8 +61,7 @@ apply from: "react.gradle"
|
||||
apply from: "../../node_modules/react-native-code-push/android/codepush.gradle"
|
||||
|
||||
/**
|
||||
* Set this to true to create three separate APKs instead of one:
|
||||
* - A universal APK that works on all devices
|
||||
* Set this to true to create two separate APKs instead of one:
|
||||
* - An APK that only works on ARM devices
|
||||
* - An APK that only works on x86 devices
|
||||
* The advantage is the size of the APK is reduced by about 4MB.
|
||||
@@ -93,7 +92,7 @@ android {
|
||||
splits {
|
||||
abi {
|
||||
enable enableSeparateBuildPerCPUArchitecture
|
||||
universalApk true
|
||||
universalApk false // Also generate an universal APK
|
||||
reset()
|
||||
include "armeabi-v7a", "x86"
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ let CodePushDemoApp = React.createClass({
|
||||
break;
|
||||
case CodePush.SyncStatus.UPDATE_INSTALLED:
|
||||
self.setState({
|
||||
syncMessage: "Update installed and will be run when the app next resumes.",
|
||||
syncMessage: "Update installed.",
|
||||
progress: false
|
||||
});
|
||||
break;
|
||||
|
||||
@@ -3,44 +3,57 @@ const NativeCodePush = require("react-native").NativeModules.CodePush;
|
||||
|
||||
const RestartManager = (() => {
|
||||
let _allowed = true;
|
||||
let _restartPending = false;
|
||||
let _restartInProgress = false;
|
||||
let _restartQueue = [];
|
||||
|
||||
function allow() {
|
||||
log("Re-allowing restarts");
|
||||
_allowed = true;
|
||||
|
||||
if (_restartPending) {
|
||||
|
||||
if (_restartQueue.length) {
|
||||
log("Executing pending restart");
|
||||
restartApp(true);
|
||||
restartApp(_restartQueue.shift(1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function clearPendingRestart() {
|
||||
_restartPending = false;
|
||||
_restartQueue = [];
|
||||
}
|
||||
|
||||
|
||||
function disallow() {
|
||||
log("Disallowing restarts");
|
||||
_allowed = false;
|
||||
}
|
||||
|
||||
function restartApp(onlyIfUpdateIsPending = false) {
|
||||
if (_allowed) {
|
||||
NativeCodePush.restartApp(onlyIfUpdateIsPending);
|
||||
log("Restarting app");
|
||||
} else {
|
||||
async function restartApp(onlyIfUpdateIsPending = false) {
|
||||
if (_restartInProgress) {
|
||||
log("Restart request queued until the current restart is completed");
|
||||
_restartQueue.push(onlyIfUpdateIsPending);
|
||||
} else if (!_allowed) {
|
||||
log("Restart request queued until restarts are re-allowed");
|
||||
_restartPending = true;
|
||||
return true;
|
||||
_restartQueue.push(onlyIfUpdateIsPending);
|
||||
} else {
|
||||
_restartInProgress = true;
|
||||
if (await NativeCodePush.restartApp(onlyIfUpdateIsPending)) {
|
||||
// The app has already restarted, so there is no need to
|
||||
// process the remaining queued restarts.
|
||||
log("Restarting app");
|
||||
return;
|
||||
}
|
||||
|
||||
_restartInProgress = false;
|
||||
if (_restartQueue.length) {
|
||||
restartApp(_restartQueue.shift(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
allow,
|
||||
clearPendingRestart,
|
||||
clearPendingRestart,
|
||||
disallow,
|
||||
restartApp
|
||||
};
|
||||
})();
|
||||
|
||||
module.exports = RestartManager;
|
||||
module.exports = RestartManager;
|
||||
|
||||
@@ -449,12 +449,16 @@ public class CodePushNativeModule extends ReactContextBaseJavaModule {
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void restartApp(boolean onlyIfUpdateIsPending) {
|
||||
public void restartApp(boolean onlyIfUpdateIsPending, Promise promise) {
|
||||
// If this is an unconditional restart request, or there
|
||||
// is current pending update, then reload the app.
|
||||
if (!onlyIfUpdateIsPending || mSettingsManager.isPendingUpdate(null)) {
|
||||
loadBundle();
|
||||
promise.resolve(true);
|
||||
return;
|
||||
}
|
||||
|
||||
promise.resolve(false);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
|
||||
@@ -740,13 +740,19 @@ RCT_EXPORT_METHOD(notifyApplicationReady:(RCTPromiseResolveBlock)resolve
|
||||
/*
|
||||
* This method is the native side of the CodePush.restartApp() method.
|
||||
*/
|
||||
RCT_EXPORT_METHOD(restartApp:(BOOL)onlyIfUpdateIsPending)
|
||||
RCT_EXPORT_METHOD(restartApp:(BOOL)onlyIfUpdateIsPending
|
||||
resolve:(RCTPromiseResolveBlock)resolve
|
||||
rejecter:(RCTPromiseRejectBlock)reject)
|
||||
{
|
||||
// If this is an unconditional restart request, or there
|
||||
// is current pending update, then reload the app.
|
||||
if (!onlyIfUpdateIsPending || [self isPendingUpdate:nil]) {
|
||||
[self loadBundle];
|
||||
resolve(@(YES));
|
||||
return;
|
||||
}
|
||||
|
||||
resolve(@(NO));
|
||||
}
|
||||
|
||||
#pragma mark - JavaScript-exported module methods (Private)
|
||||
|
||||
17
test/template/scenarios/scenarioInstallRestart2x.js
Normal file
17
test/template/scenarios/scenarioInstallRestart2x.js
Normal file
@@ -0,0 +1,17 @@
|
||||
var CodePushWrapper = require("../codePushWrapper.js");
|
||||
import CodePush from "react-native-code-push";
|
||||
|
||||
module.exports = {
|
||||
startTest: function(testApp) {
|
||||
CodePushWrapper.checkAndInstall(testApp,
|
||||
() => {
|
||||
CodePush.restartApp();
|
||||
CodePush.restartApp();
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
getScenarioName: function() {
|
||||
return "Install and Restart 2x";
|
||||
}
|
||||
};
|
||||
17
test/template/scenarios/scenarioRestart2x.js
Normal file
17
test/template/scenarios/scenarioRestart2x.js
Normal file
@@ -0,0 +1,17 @@
|
||||
var CodePushWrapper = require("../codePushWrapper.js");
|
||||
import CodePush from "react-native-code-push";
|
||||
|
||||
module.exports = {
|
||||
startTest: function(testApp) {
|
||||
CodePush.restartApp(true);
|
||||
CodePushWrapper.checkAndInstall(testApp,
|
||||
() => {
|
||||
CodePush.restartApp(true);
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
getScenarioName: function() {
|
||||
return "Restart2x";
|
||||
}
|
||||
};
|
||||
39
test/test.ts
39
test/test.ts
@@ -465,12 +465,14 @@ const ScenarioInstall = "scenarioInstall.js";
|
||||
const ScenarioInstallOnResumeWithRevert = "scenarioInstallOnResumeWithRevert.js";
|
||||
const ScenarioInstallOnRestartWithRevert = "scenarioInstallOnRestartWithRevert.js";
|
||||
const ScenarioInstallWithRevert = "scenarioInstallWithRevert.js";
|
||||
const ScenarioInstallRestart2x = "scenarioInstallRestart2x.js";
|
||||
const ScenarioSync1x = "scenarioSync.js";
|
||||
const ScenarioSyncResume = "scenarioSyncResume.js";
|
||||
const ScenarioSyncResumeDelay = "scenarioSyncResumeDelay.js";
|
||||
const ScenarioSyncRestartDelay = "scenarioSyncResumeDelay.js";
|
||||
const ScenarioSync2x = "scenarioSync2x.js";
|
||||
const ScenarioRestart = "scenarioRestart.js";
|
||||
const ScenarioRestart2x = "scenarioRestart2x.js";
|
||||
const ScenarioSyncMandatoryDefault = "scenarioSyncMandatoryDefault.js";
|
||||
const ScenarioSyncMandatoryResume = "scenarioSyncMandatoryResume.js";
|
||||
const ScenarioSyncMandatoryRestart = "scenarioSyncMandatoryRestart.js";
|
||||
@@ -986,6 +988,43 @@ PluginTestingFramework.initializeTests(new RNProjectManager(), supportedTargetPl
|
||||
});
|
||||
}, ScenarioRestart);
|
||||
|
||||
TestBuilder.describe("#codePush.restartApplication.2x",
|
||||
() => {
|
||||
TestBuilder.it("blocks when a restart is in progress and doesn't crash if there is a pending package", false,
|
||||
(done: MochaDone) => {
|
||||
ServerUtil.updateResponse = { updateInfo: ServerUtil.createUpdateResponse(false, targetPlatform) };
|
||||
setupTestRunScenario(projectManager, targetPlatform, ScenarioInstallRestart2x)
|
||||
.then(setupUpdateScenario.bind(this, projectManager, targetPlatform, UpdateDeviceReady, "Update 1"))
|
||||
.then<void>((updatePath: string) => {
|
||||
ServerUtil.updatePackagePath = updatePath;
|
||||
projectManager.runApplication(TestConfig.testRunDirectory, targetPlatform);
|
||||
return ServerUtil.expectTestMessages([
|
||||
ServerUtil.TestMessage.CHECK_UPDATE_AVAILABLE,
|
||||
ServerUtil.TestMessage.DOWNLOAD_SUCCEEDED,
|
||||
ServerUtil.TestMessage.UPDATE_INSTALLED,
|
||||
ServerUtil.TestMessage.DEVICE_READY_AFTER_UPDATE]);
|
||||
})
|
||||
.done(() => { done(); }, (e) => { done(e); });
|
||||
});
|
||||
|
||||
TestBuilder.it("doesn't block when the restart is ignored", false,
|
||||
(done: MochaDone) => {
|
||||
ServerUtil.updateResponse = { updateInfo: ServerUtil.createUpdateResponse(false, targetPlatform) };
|
||||
setupTestRunScenario(projectManager, targetPlatform, ScenarioRestart2x)
|
||||
.then(setupUpdateScenario.bind(this, projectManager, targetPlatform, UpdateDeviceReady, "Update 1"))
|
||||
.then<void>((updatePath: string) => {
|
||||
ServerUtil.updatePackagePath = updatePath;
|
||||
projectManager.runApplication(TestConfig.testRunDirectory, targetPlatform);
|
||||
return ServerUtil.expectTestMessages([
|
||||
ServerUtil.TestMessage.CHECK_UPDATE_AVAILABLE,
|
||||
ServerUtil.TestMessage.DOWNLOAD_SUCCEEDED,
|
||||
ServerUtil.TestMessage.UPDATE_INSTALLED,
|
||||
ServerUtil.TestMessage.DEVICE_READY_AFTER_UPDATE]);
|
||||
})
|
||||
.done(() => { done(); }, (e) => { done(e); });
|
||||
});
|
||||
});
|
||||
|
||||
TestBuilder.describe("#window.codePush.sync",
|
||||
() => {
|
||||
// We test the functionality with sync twice--first, with sync only called once,
|
||||
|
||||
Reference in New Issue
Block a user