Ben Copsey

Added support for ASIHTTPRequests as background tasks

@@ -427,6 +427,11 @@ extern unsigned long const ASIWWANBandwidthThrottleAmount; @@ -427,6 +427,11 @@ extern unsigned long const ASIWWANBandwidthThrottleAmount;
427 427
428 // Set secondsToCache to use a custom time interval for expiring the response when it is stored in a cache 428 // Set secondsToCache to use a custom time interval for expiring the response when it is stored in a cache
429 NSTimeInterval secondsToCache; 429 NSTimeInterval secondsToCache;
  430 +
  431 + #if TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0
  432 + BOOL shouldContinueWhenAppEntersBackground;
  433 + UIBackgroundTaskIdentifier backgroundTask;
  434 + #endif
430 } 435 }
431 436
432 #pragma mark init / dealloc 437 #pragma mark init / dealloc
@@ -855,4 +860,7 @@ extern unsigned long const ASIWWANBandwidthThrottleAmount; @@ -855,4 +860,7 @@ extern unsigned long const ASIWWANBandwidthThrottleAmount;
855 @property (assign, readonly) BOOL didUseCachedResponse; 860 @property (assign, readonly) BOOL didUseCachedResponse;
856 @property (assign) NSTimeInterval secondsToCache; 861 @property (assign) NSTimeInterval secondsToCache;
857 @property (retain) NSArray *clientCertificates; 862 @property (retain) NSArray *clientCertificates;
  863 +#if TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0
  864 +@property (assign) BOOL shouldContinueWhenAppEntersBackground;
  865 +#endif
858 @end 866 @end
@@ -23,7 +23,7 @@ @@ -23,7 +23,7 @@
23 23
24 24
25 // Automatically set on build 25 // Automatically set on build
26 -NSString *ASIHTTPRequestVersion = @"v1.7-51 2010-08-18"; 26 +NSString *ASIHTTPRequestVersion = @"v1.7-52 2010-08-18";
27 27
28 NSString* const NetworkRequestErrorDomain = @"ASIHTTPRequestErrorDomain"; 28 NSString* const NetworkRequestErrorDomain = @"ASIHTTPRequestErrorDomain";
29 29
@@ -644,6 +644,24 @@ static NSOperationQueue *sharedQueue = nil; @@ -644,6 +644,24 @@ static NSOperationQueue *sharedQueue = nil;
644 644
645 [[self cancelledLock] lock]; 645 [[self cancelledLock] lock];
646 646
  647 + #if TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0
  648 + if ([[UIDevice currentDevice] isMultitaskingSupported] && [self shouldContinueWhenAppEntersBackground]) {
  649 + backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
  650 + // Synchronize the cleanup call on the main thread in case
  651 + // the task actually finishes at around the same time.
  652 + dispatch_async(dispatch_get_main_queue(), ^{
  653 + if (backgroundTask != UIBackgroundTaskInvalid)
  654 + {
  655 + [[UIApplication sharedApplication] endBackgroundTask:backgroundTask];
  656 + backgroundTask = UIBackgroundTaskInvalid;
  657 + [self cancel];
  658 + }
  659 + });
  660 + }];
  661 + }
  662 + #endif
  663 +
  664 +
647 // A HEAD request generated by an ASINetworkQueue may have set the error already. If so, we should not proceed. 665 // A HEAD request generated by an ASINetworkQueue may have set the error already. If so, we should not proceed.
648 if ([self error]) { 666 if ([self error]) {
649 [self setComplete:YES]; 667 [self setComplete:YES];
@@ -2903,6 +2921,16 @@ static NSOperationQueue *sharedQueue = nil; @@ -2903,6 +2921,16 @@ static NSOperationQueue *sharedQueue = nil;
2903 2921
2904 CFRunLoopStop(CFRunLoopGetCurrent()); 2922 CFRunLoopStop(CFRunLoopGetCurrent());
2905 2923
  2924 + #if TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0
  2925 + if ([[UIDevice currentDevice] isMultitaskingSupported] && [self shouldContinueWhenAppEntersBackground]) {
  2926 + dispatch_async(dispatch_get_main_queue(), ^{
  2927 + if (backgroundTask != UIBackgroundTaskInvalid) {
  2928 + [[UIApplication sharedApplication] endBackgroundTask:backgroundTask];
  2929 + backgroundTask = UIBackgroundTaskInvalid;
  2930 + }
  2931 + });
  2932 + }
  2933 + #endif
2906 [self release]; 2934 [self release];
2907 } 2935 }
2908 2936
@@ -4257,4 +4285,7 @@ static NSOperationQueue *sharedQueue = nil; @@ -4257,4 +4285,7 @@ static NSOperationQueue *sharedQueue = nil;
4257 @synthesize didUseCachedResponse; 4285 @synthesize didUseCachedResponse;
4258 @synthesize secondsToCache; 4286 @synthesize secondsToCache;
4259 @synthesize clientCertificates; 4287 @synthesize clientCertificates;
  4288 +#if TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0
  4289 +@synthesize shouldContinueWhenAppEntersBackground;
  4290 +#endif
4260 @end 4291 @end
@@ -20,6 +20,9 @@ @@ -20,6 +20,9 @@
20 [request setPostValue:@"test" forKey:@"value2"]; 20 [request setPostValue:@"test" forKey:@"value2"];
21 [request setPostValue:@"test" forKey:@"value3"]; 21 [request setPostValue:@"test" forKey:@"value3"];
22 [request setTimeOutSeconds:20]; 22 [request setTimeOutSeconds:20];
  23 + #if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0
  24 + [request setShouldContinueWhenAppEntersBackground:YES];
  25 + #endif
23 [request setUploadProgressDelegate:progressIndicator]; 26 [request setUploadProgressDelegate:progressIndicator];
24 [request setDelegate:self]; 27 [request setDelegate:self];
25 [request setDidFailSelector:@selector(uploadFailed:)]; 28 [request setDidFailSelector:@selector(uploadFailed:)];
@@ -53,6 +56,23 @@ @@ -53,6 +56,23 @@
53 - (void)uploadFinished:(ASIHTTPRequest *)theRequest 56 - (void)uploadFinished:(ASIHTTPRequest *)theRequest
54 { 57 {
55 [resultView setText:[NSString stringWithFormat:@"Finished uploading %llu bytes of data",[theRequest postLength]]]; 58 [resultView setText:[NSString stringWithFormat:@"Finished uploading %llu bytes of data",[theRequest postLength]]];
  59 +
  60 + #if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0
  61 + // Clear out the old notification before scheduling a new one.
  62 + if ([[[UIApplication sharedApplication] scheduledLocalNotifications] count] > 0)
  63 + [[UIApplication sharedApplication] cancelAllLocalNotifications];
  64 +
  65 + // Create a new notification
  66 + UILocalNotification* alarm = [[[UILocalNotification alloc] init] autorelease];
  67 + if (alarm) {
  68 + [alarm setFireDate:[NSDate date]];
  69 + [alarm setTimeZone:[NSTimeZone defaultTimeZone]];
  70 + [alarm setRepeatInterval:0];
  71 + [alarm setSoundName:@"alarmsound.caf"];
  72 + [alarm setAlertBody:@"Boom!\r\n\r\nUpload is finished!"];
  73 + [[UIApplication sharedApplication] scheduleLocalNotification:alarm];
  74 + }
  75 + #endif
56 } 76 }
57 77
58 - (void)dealloc 78 - (void)dealloc
@@ -78,7 +98,7 @@ @@ -78,7 +98,7 @@
78 98
79 } 99 }
80 100
81 -static NSString *intro = @"Demonstrates POSTing content to a URL, showing upload progress.\nYou'll only see accurate progress for uploads when the request body is larger than 128KB (in 2.2.1 SDK), or when the request body is larger than 32KB (in 3.0 SDK)"; 101 +static NSString *intro = @"Demonstrates POSTing content to a URL, showing upload progress.\nYou'll only see accurate progress for uploads when the request body is larger than 128KB (in 2.2.1 SDK), or when the request body is larger than 32KB (in 3.0 SDK)\n\nThis request is also setup to run when the app enters the background on devices running on iOS4. In the delegate method that is called when the request finishes, we show a local notification to let the user know the upload is finished.";
82 102
83 - (UIView *)tableView:(UITableView *)theTableView viewForHeaderInSection:(NSInteger)section 103 - (UIView *)tableView:(UITableView *)theTableView viewForHeaderInSection:(NSInteger)section
84 { 104 {