iOS implementation of minimumBackgroundDuration

This commit is contained in:
Jonathan Carter
2016-03-10 12:06:44 -08:00
parent 52003256f8
commit af2a5c6970
4 changed files with 59 additions and 18 deletions

View File

@@ -239,6 +239,7 @@ async function syncInternal(options = {}, syncStatusChangeCallback, downloadProg
ignoreFailedUpdates: true,
installMode: CodePush.InstallMode.ON_NEXT_RESTART,
mandatoryInstallMode: CodePush.InstallMode.IMMEDIATE,
minimumBackgroundDuration: 0,
updateDialog: null,
...options
};
@@ -273,7 +274,11 @@ async function syncInternal(options = {}, syncStatusChangeCallback, downloadProg
if (resolvedInstallMode == CodePush.InstallMode.ON_NEXT_RESTART) {
log("Update is installed and will be run on the next app restart.");
} else {
log("Update is installed and will be run when the app next resumes.");
if (syncOptions.minimumBackgroundDuration > 0) {
log(`Update is installed and will be run after the app has been in the background for at least ${syncOptions.minimumBackgroundDuration} seconds.`);
} else {
log("Update is installed and will be run when the app next resumes.");
}
}
break;
case CodePush.SyncStatus.UNKNOWN_ERROR:
@@ -302,7 +307,7 @@ async function syncInternal(options = {}, syncStatusChangeCallback, downloadProg
resolvedInstallMode = localPackage.isMandatory ? syncOptions.mandatoryInstallMode : syncOptions.installMode;
syncStatusChangeCallback(CodePush.SyncStatus.INSTALLING_UPDATE);
await localPackage.install(resolvedInstallMode, () => {
await localPackage.install(resolvedInstallMode, syncOptions.minimumBackgroundDuration, () => {
syncStatusChangeCallback(CodePush.SyncStatus.UPDATE_INSTALLED);
});

View File

@@ -567,6 +567,8 @@ While the `sync` method tries to make it easy to perform silent and active updat
* __mandatoryInstallMode__ *(codePush.InstallMode)* - Specifies when you would like to install updates which are marked as mandatory. Defaults to `codePush.InstallMode.IMMEDIATE`. Refer to the [`InstallMode`](#installmode) enum reference for a description of the available options and what they do.
* __minimumBackgroundDuration__ *(Number)* - Specifies the minimum number of seconds that the app needs to have been in the background before restarting the app to apply the udpate. This property only applies to updates which are installed using `InstallMode.ON_NEXT_RESUME`, and can be useful for getting your update in front of end users sooner, without being too obtrusive. Defaults to `0`, which has the effect of applying the update immediately after a resume, regardless how long it was in the background.
* __updateDialog__ *(UpdateDialogOptions)* - An "options" object used to determine whether a confirmation dialog should be displayed to the end user when an update is available, and if so, what strings to use. Defaults to `null`, which has the effect of disabling the dialog completely. Setting this to any truthy value will enable the dialog with the default strings, and passing an object to this parameter allows enabling the dialog as well as overriding one or more of the default strings. Before enabling this option within an App Store-distributed app, please refer to [this note](#user-content-apple-note).
The following list represents the available options and their defaults:
@@ -595,10 +597,10 @@ Example Usage:
// in the Info.plist file
codePush.sync({ deploymentKey: "KEY" });
// Download the update silently
// but install is on the next resume
// instead of waiting until the app is restarted
codePush.sync({ installMode: codePush.InstallMode.ON_NEXT_RESUME });
// Download the update silently, but install it on
// the next resume, as long as at least 5 minutes
// has passed since the app was put into the background.
codePush.sync({ installMode: codePush.InstallMode.ON_NEXT_RESUME, minimumBackgroundDuration: 60 * 5 });
// Download the update silently, and install optional updates
// on the next restart, but install mandatory updates on the next resume.
@@ -681,7 +683,7 @@ Contains details about an update that has been downloaded locally or already ins
- __packageSize__: The size of the code contained within the update, in bytes. *(Number)*
###### Methods
- __install(installMode: codePush.InstallMode = codePush.InstallMode.ON_NEXT_RESTART): Promise<void>__: Installs the update by saving it to the location on disk where the runtime expects to find the latest version of the app. The `installMode` parameter controls when the changes are actually presented to the end user. The default value is to wait until the next app restart to display the changes, but you can refer to the [`InstallMode`](#installmode) enum reference for a description of the available options and what they do.
- __install(installMode: codePush.InstallMode = codePush.InstallMode.ON_NEXT_RESTART, minimumBackgroundDuration = 0): Promise<void>__: Installs the update by saving it to the location on disk where the runtime expects to find the latest version of the app. The `installMode` parameter controls when the changes are actually presented to the end user. The default value is to wait until the next app restart to display the changes, but you can refer to the [`InstallMode`](#installmode) enum reference for a description of the available options and what they do. If the `installMode` parameter is set to `InstallMode.ON_NEXT_RESUME`, then the `minimumBackgroundDuration` parameter allows you to control how long the app must have been in the background before forcing the install after it is resumed.
##### RemotePackage

View File

@@ -12,6 +12,8 @@
@implementation CodePush {
BOOL _hasResumeListener;
BOOL _isFirstRunAfterUpdate;
int _minimumBackgroundDuration;
NSDate * _lastResignedDate;
}
RCT_EXPORT_MODULE()
@@ -380,6 +382,27 @@ static NSString *bundleResourceName = @"main";
[preferences synchronize];
}
#pragma mark - Application lifecycle event handlers
// These two handlers will only be registered when there is
// a resume-based update still pending installation.
- (void)applicationWillEnterForeground
{
// Determine how long the app was in the background and ensure
// that it meets the minimum amount of time requsted.
int durationInBackground = [[NSDate date] timeIntervalSinceDate:_lastResignedDate];
if (durationInBackground >= _minimumBackgroundDuration) {
[self loadBundle];
}
}
- (void)applicationWillResignActive
{
// Save the current time so that when the app is later
// resumed, we can detect how long it was in the background.
_lastResignedDate = [NSDate date];
}
#pragma mark - JavaScript-exported module methods
/*
@@ -522,16 +545,27 @@ RCT_EXPORT_METHOD(installUpdate:(NSDictionary*)updatePackage
[self savePendingUpdate:updatePackage[PackageHashKey]
isLoading:NO];
if (installMode == CodePushInstallModeOnNextResume && !_hasResumeListener) {
// Ensure we do not add the listener twice.
// Register for app resume notifications so that we
// can check for pending updates which support "restart on resume"
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(loadBundle)
name:UIApplicationWillEnterForegroundNotification
object:[UIApplication sharedApplication]];
_hasResumeListener = YES;
if (installMode == CodePushInstallModeOnNextResume) {
_minimumBackgroundDuration = minimumBackgroundDuration;
if (!_hasResumeListener) {
// Ensure we do not add the listener twice.
// Register for app resume notifications so that we
// can check for pending updates which support "restart on resume"
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationWillEnterForeground)
name:UIApplicationWillEnterForegroundNotification
object:[UIApplication sharedApplication]];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationWillResignActive)
name:UIApplicationWillResignActiveNotification
object:[UIApplication sharedApplication]];
_hasResumeListener = YES;
}
}
// Signal to JS that the update has been applied.
resolve(nil);
}

View File

@@ -37,9 +37,9 @@ module.exports = (NativeCodePush) => {
};
const local = {
async install(installMode = NativeCodePush.codePushInstallModeOnNextRestart, updateInstalledCallback) {
async install(installMode = NativeCodePush.codePushInstallModeOnNextRestart, minimumBackgroundDuration = 0, updateInstalledCallback) {
const localPackage = this;
await NativeCodePush.installUpdate(this, installMode);
await NativeCodePush.installUpdate(this, installMode, minimumBackgroundDuration);
updateInstalledCallback && updateInstalledCallback();
if (installMode == NativeCodePush.codePushInstallModeImmediate) {
NativeCodePush.restartApp(false);