diff --git a/CodePush.m b/CodePush.m index 8c41e85..95f6a9d 100644 --- a/CodePush.m +++ b/CodePush.m @@ -148,6 +148,7 @@ static NSString *bundleResourceName = @"main"; #pragma mark - Private API methods @synthesize bridge = _bridge; +@synthesize methodQueue = _methodQueue; + (NSURL *)binaryBundleURL { @@ -393,17 +394,17 @@ RCT_EXPORT_METHOD(downloadUpdate:(NSDictionary*)updatePackage resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { - dispatch_async(dispatch_get_main_queue(), ^{ - NSDictionary *mutableUpdatePackage = [updatePackage mutableCopy]; - NSURL *binaryBundleURL = [CodePush binaryBundleURL]; - if (binaryBundleURL != nil) { - [mutableUpdatePackage setValue:[CodePush modifiedDateStringOfFileAtURL:binaryBundleURL] - forKey:BinaryBundleDateKey]; - } - - [CodePushPackage downloadPackage:mutableUpdatePackage - // The download is progressing forward - progressCallback:^(long long expectedContentLength, long long receivedContentLength) { + NSDictionary *mutableUpdatePackage = [updatePackage mutableCopy]; + NSURL *binaryBundleURL = [CodePush binaryBundleURL]; + if (binaryBundleURL != nil) { + [mutableUpdatePackage setValue:[CodePush modifiedDateStringOfFileAtURL:binaryBundleURL] + forKey:BinaryBundleDateKey]; + } + + [CodePushPackage downloadPackage:mutableUpdatePackage + // The download is progressing forward + progressCallback:^(long long expectedContentLength, long long receivedContentLength) { + dispatch_async(_methodQueue, ^{ // Notify the script-side about the progress [self.bridge.eventDispatcher sendDeviceEventWithName:@"CodePushDownloadProgress" @@ -411,9 +412,11 @@ RCT_EXPORT_METHOD(downloadUpdate:(NSDictionary*)updatePackage @"totalBytes":[NSNumber numberWithLongLong:expectedContentLength], @"receivedBytes":[NSNumber numberWithLongLong:receivedContentLength] }]; - } - // The download completed - doneCallback:^{ + }); + } + // The download completed + doneCallback:^{ + dispatch_async(_methodQueue, ^{ NSError *err; NSDictionary *newPackage = [CodePushPackage getPackage:mutableUpdatePackage[PackageHashKey] error:&err]; @@ -422,16 +425,18 @@ RCT_EXPORT_METHOD(downloadUpdate:(NSDictionary*)updatePackage } resolve(newPackage); - } - // The download failed - failCallback:^(NSError *err) { + }); + } + // The download failed + failCallback:^(NSError *err) { + dispatch_async(_methodQueue, ^{ if ([CodePushPackage isCodePushError:err]) { [self saveFailedUpdate:mutableUpdatePackage]; } reject([NSString stringWithFormat: @"%lu", (long)err.code], err.localizedDescription, err); - }]; - }); + }); + }]; } /* @@ -452,21 +457,19 @@ RCT_EXPORT_METHOD(getConfiguration:(RCTPromiseResolveBlock)resolve RCT_EXPORT_METHOD(getCurrentPackage:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { - dispatch_async(dispatch_get_main_queue(), ^{ - NSError *error; - NSMutableDictionary *package = [[CodePushPackage getCurrentPackage:&error] mutableCopy]; - - if (error) { - reject([NSString stringWithFormat: @"%lu", (long)error.code], error.localizedDescription, error); - } - - // Add the "isPending" virtual property to the package at this point, so that - // the script-side doesn't need to immediately call back into native to populate it. - BOOL isPendingUpdate = [self isPendingUpdate:[package objectForKey:PackageHashKey]]; - [package setObject:@(isPendingUpdate) forKey:PackageIsPendingKey]; - - resolve(package); - }); + NSError *error; + NSMutableDictionary *package = [[CodePushPackage getCurrentPackage:&error] mutableCopy]; + + if (error) { + reject([NSString stringWithFormat: @"%lu", (long)error.code], error.localizedDescription, error); + } + + // Add the "isPending" virtual property to the package at this point, so that + // the script-side doesn't need to immediately call back into native to populate it. + BOOL isPendingUpdate = [self isPendingUpdate:[package objectForKey:PackageHashKey]]; + [package setObject:@(isPendingUpdate) forKey:PackageIsPendingKey]; + + resolve(package); } /* @@ -477,32 +480,30 @@ RCT_EXPORT_METHOD(installUpdate:(NSDictionary*)updatePackage resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - NSError *error; - [CodePushPackage installPackage:updatePackage - removePendingUpdate:[self isPendingUpdate:nil] - error:&error]; + NSError *error; + [CodePushPackage installPackage:updatePackage + removePendingUpdate:[self isPendingUpdate:nil] + error:&error]; + + if (error) { + reject([NSString stringWithFormat: @"%lu", (long)error.code], error.localizedDescription, error); + } else { + [self savePendingUpdate:updatePackage[PackageHashKey] + isLoading:NO]; - if (error) { - reject([NSString stringWithFormat: @"%lu", (long)error.code], error.localizedDescription, error); - } else { - [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; - } - // Signal to JS that the update has been applied. - resolve(nil); + 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; } - }); + // Signal to JS that the update has been applied. + resolve(nil); + } } /* @@ -551,33 +552,31 @@ RCT_EXPORT_METHOD(notifyApplicationReady:(RCTPromiseResolveBlock)resolve RCT_EXPORT_METHOD(getNewStatusReport:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - if (needToReportRollback) { - needToReportRollback = NO; - NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults]; - NSMutableArray *failedUpdates = [preferences objectForKey:FailedUpdatesKey]; - if (failedUpdates) { - NSDictionary *lastFailedPackage = [failedUpdates lastObject]; - if (lastFailedPackage) { - resolve([CodePushTelemetryManager getRollbackReport:lastFailedPackage]); - return; - } - } - } else if (_isFirstRunAfterUpdate) { - NSError *error; - NSDictionary *currentPackage = [CodePushPackage getCurrentPackage:&error]; - if (!error && currentPackage) { - resolve([CodePushTelemetryManager getUpdateReport:currentPackage]); + if (needToReportRollback) { + needToReportRollback = NO; + NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults]; + NSMutableArray *failedUpdates = [preferences objectForKey:FailedUpdatesKey]; + if (failedUpdates) { + NSDictionary *lastFailedPackage = [failedUpdates lastObject]; + if (lastFailedPackage) { + resolve([CodePushTelemetryManager getRollbackReport:lastFailedPackage]); return; } - } else if (isRunningBinaryVersion) { - NSString *appVersion = [[CodePushConfig current] appVersion]; - resolve([CodePushTelemetryManager getBinaryUpdateReport:appVersion]); + } + } else if (_isFirstRunAfterUpdate) { + NSError *error; + NSDictionary *currentPackage = [CodePushPackage getCurrentPackage:&error]; + if (!error && currentPackage) { + resolve([CodePushTelemetryManager getUpdateReport:currentPackage]); return; } - - resolve(nil); - }); + } else if (isRunningBinaryVersion) { + NSString *appVersion = [[CodePushConfig current] appVersion]; + resolve([CodePushTelemetryManager getBinaryUpdateReport:appVersion]); + return; + } + + resolve(nil); } /*