diff --git a/.travis.yml b/.travis.yml index cb1f494..c59f541 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: objective-c -osx_image: xcode7.1 +osx_image: xcode8.2 env: global: - "MODULE_NAME=ti.urlsession" @@ -8,7 +8,7 @@ before_install: install: - cd $MODULE_ROOT - curl -o install.sh https://raw.githubusercontent.com/appcelerator-modules/ci/master/travis/install.sh - - source install.sh -s "--branch 5_1_X" + - source install.sh -s "--branch 6_0_X" script: - curl -o script.sh https://raw.githubusercontent.com/appcelerator-modules/ci/master/travis/script.sh - source script.sh @@ -27,4 +27,4 @@ deploy: skip_cleanup: true on: repo: appcelerator-modules/ti.urlsession - branch: master \ No newline at end of file + branch: master diff --git a/apidoc/Session.yml b/apidoc/Session.yml new file mode 100644 index 0000000..8c57e08 --- /dev/null +++ b/apidoc/Session.yml @@ -0,0 +1,130 @@ +--- +name: Modules.URLSession.Session +summary: The session object used to start new tasks. +description: | + These APIs are supported on iOS 7 and later. + + The NSURLSession class and related classes provide an API for downloading content. + This API provides a rich set of delegate methods for supporting authentication and gives + your app the ability to perform background downloads when your app is not running or, in iOS, + while your app is suspended. + + [iOS Background Services guide](http://docs.appcelerator.com/titanium/latest/#!/guide/iOS_Background_Services). + +extends: Titanium.Module +osver: {ios: {min: "7.0"}} +platforms: [iphone, ipad] +since: 6.1.0 + +methods: + - name: finishTasksAndInvalidate + summary: Invalidates the given session object, allowing any outstanding tasks to finish. + description: | + This method returns immediately without waiting for tasks to finish. Once a session is invalidated, + new tasks cannot be created in the session, but existing tasks continue until completion. Once + invalidated, references to the events and callback objects are broken. Session objects cannot be + reused. To cancel all outstanding tasks, call `invalidateAndCancel` instead. + + - name: invalidateAndCancel + summary: Cancels all outstanding tasks and then invalidates the session object. + description: | + Once invalidated, references to the events and callback objects are broken. + Session objects cannot be reused. To allow outstanding tasks to run until + completion, call `finishTasksAndInvalidate` instead. + + - name: downloadTask + summary: | + Creates a download task for the specified URL, within the provided session + object and saves the results to a file. + description: | + Once this function is called, the download starts automatically. The progress + of the download can be monitored by listening to the `downloadprogress`, + `downloadcompleted`, `sessioneventscompleted` and `sessioncompleted` events. + parameters: + - name: args + summary: An object representing the arguments to add a new background task. + type: DownloadTaskType + returns: + summary: Task's identifier number. + type: String + + - name: uploadTask + summary: | + Creates a upload task for the specified URL, within the provided session + object and local data. + description: | + Once this function is called, the upload starts automatically. The progress + of the upload can be monitored by listening to the `uploadprogress` and + `sessioncompleted` events. + parameters: + - name: args + summary: An object representing the arguments to add a new upload task. + type: UploadTaskType + returns: + summary: Task's identifier number. + type: String + + - name: reset + summary: Empties all cookies, cache and credential stores, removes disk files, calls . + parameters: + - name: callback + summary: Callback to be invoked when the reset completes. + type: Callback + + - name: flush + summary: Flushes storage to disk and clear transient network caches. + parameters: + - name: callback + summary: Callback to be invoked when the reset completes. + type: Callback + +properties: + - name: configuration + summary: The configuration used for this url session. + description: | + Configuration options for an object. + When a session is created, a copy of the configuration object is made. + you cannot modify the configuration of a session after it has been created. + + The shared session uses the global singleton credential, cache + and cookie storage objects. + + An ephemeral session has no persistent disk storage for cookies, + cache or credentials. + + A background session can be used to perform networking operations + on behalf of a suspended application, within certain constraints. + optional: false + availability: creation + type: Modules.URLSession.SessionConfiguration + +--- +name: DownloadTaskType +summary: The parameter for [downloadTask](Modules.URLSession.Session.downloadTask) method. +properties: + - name: url + summary: The remote url used for this data task. + type: String + +--- +name: UploadTaskType +summary: The parameter for [uploadTask](Modules.URLSession.Session.uploadTask) method. +properties: + - name: url + summary: The remote url used for this data task. + type: String + optional: false + + - name: data + summary: The data blob used for this data task. + type: Titanium.Blob + optional: false + + - name: method + summary: The request method (e.g. POST or PUT) + default: POST + type: String + + - name: requestHeaders + summary: Additional request headers to pass to the request. + type: String diff --git a/apidoc/SessionConfiguration.yml b/apidoc/SessionConfiguration.yml new file mode 100644 index 0000000..a848142 --- /dev/null +++ b/apidoc/SessionConfiguration.yml @@ -0,0 +1,28 @@ +--- +name: Modules.URLSession.SessionConfiguration +summary: The session configuration object used to create new url sessions. +description: | + These APIs are supported on iOS 7 and later. + + An NSURLSessionConfiguration object defines the behavior and policies to use + when uploading and downloading data using an URLSession object. When uploading + or downloading data, creating a configuration object is always the first step + you must take. You use this object to configure the timeout values, caching + policies, connection requirements, and other types of information that you + intend to use with your URLSession object. + + [iOS Background Services guide](http://docs.appcelerator.com/titanium/latest/#!/guide/iOS_Background_Services). + +extends: Titanium.Module +osver: {ios: {min: "7.0"}} +platforms: [iphone, ipad] +since: 6.1.0 + +properties: + - name: identifier + summary: The unique identifier for the configuration object. + description: | + This parameter must not be non-null or an empty string. + optional: false + availability: creation + type: String diff --git a/apidoc/urlsession.yml b/apidoc/urlsession.yml index dd49803..268ef11 100644 --- a/apidoc/urlsession.yml +++ b/apidoc/urlsession.yml @@ -34,35 +34,6 @@ excludes: properties: [bubbleParent] methods: - - name: createURLSessionBackgroundConfiguration - summary: | - Creates a preconfigured session configuration object that can be used to create a URL session for - performing a background download task. - parameters: - - name: indentifier - summary: Arbitrary string used to identify the session in the events. - type: String - returns: - summary: Configuration object to pass to the method. - type: Object - - - name: createURLSession - summary: Creates a session with the specified session configuration. - description: | - If the session configuration was created with the identifier of a existing session, - then this function would return the pre-existing session. - - The session object keeps a strong reference until your app explicitly invalidates the - session. If you do not invalidate the session by calling the `invalidateAndCancel` or - `finishTasksAndInvalidate` method, your app leaks memory. - parameters: - - name: sessionConfiguration - summary: Session configuration object created with the - type: Object - returns: - summary: URL session object. - type: Object - - name: finishTasksAndInvalidate summary: Invalidates the given session object, allowing any outstanding tasks to finish. description: | @@ -74,6 +45,9 @@ methods: - name: session summary: URL session object. type: Object + deprecated: + since: 6.1.0 + notes: Use (on the session object) instead. - name: invalidateAndCancel summary: Cancels all outstanding tasks and then invalidates the session object. @@ -85,8 +59,14 @@ methods: - name: session summary: URL session object. type: Object + deprecated: + since: 6.1.0 + notes: Use (on the session object) instead. - name: backgroundDownloadTaskWithURL + deprecated: + since: 6.1.0 + notes: Use on the session directly. summary: | Creates a download task for the specified URL, within the provided session object and saves the results to a file. @@ -104,3 +84,23 @@ methods: returns: summary: Task's identifier number. type: String + +properties: + - name: configuration + summary: The configuration used for this url session. + description: | + Configuration options for an object. + When a session is created, a copy of the configuration object is made. + you cannot modify the configuration of a session after it has been created. + + The shared session uses the global singleton credential, cache + and cookie storage objects. + + An ephemeral session has no persistent disk storage for cookies, + cache or credentials. + + A background session can be used to perform networking operations + on behalf of a suspended application, within certain constraints. + optional: false + availability: creation + type: Modules.URLSession.SessionConfiguration diff --git a/documentation/changelog.md b/documentation/changelog.md index dc773fc..2c93ab2 100644 --- a/documentation/changelog.md +++ b/documentation/changelog.md @@ -1,5 +1,8 @@ # Change Log +## 2.1.0 +Add support for upload tasks and more advanced session configuration. + ## 2.0.0 Refactored module to work on iOS 9 and prevent app submission failture. [MOD-2150] diff --git a/documentation/index.md b/documentation/index.md index e23eaea..d40e482 100644 --- a/documentation/index.md +++ b/documentation/index.md @@ -59,16 +59,28 @@ To allow outstanding tasks to run until completion, call finishTasksAndInvalidat * Takes one argument, a session object : the session which the user wants to invalidate. -### backgroundDownloadTaskWithURL(session object, string) +### addBackgroundDownloadTask(args) Creates a download task for the specified URL, within the provided session object and saves the results to a file. Once this function is called, the download starts automatically. The progress of the download can be monitored by listening to `downloadprogress` , `downloadcompleted`, `sessioneventscompleted` and `sessioncompleted` events explained below. -* Takes two arguments, - * a session object : (Object created using createURLSession()) Session which with the new background task should be associated with. +* Takes an object of arguments, + * session[URLSession] : (Object created using createURLSession()) Session which with the new background task should be associated with. * url[string] : The string that provides the URL to be downloaded. - + + +### addBackgroundUploadTask(args) + +Creates an upload task for the specified URL, within the provided session object and the file-blob to upload. +Once this function is called, the upload starts automatically. The progress of the upload can be monitored by listening +to `uploadprogress` and `sessioncompleted` events explained below. + +* Takes an object of arguments, + * session[URLSession] : (Object created using createURLSession()) Session which with the new background task should be associated with. + * url[string] : The string that provides the URL to upload to. + * data[TiBlob] : The file-blob to be uploaded. + Returns the new created task's identifier number. ## Events @@ -113,7 +125,6 @@ usage : ### sessioncompleted - Informs the app that the task finished transferring data. ImportantThis event is exposed inside Ti.App.iOS Proxy. @@ -122,8 +133,8 @@ usage : The following event information will be provided: -* taskIdentifier[int] : The task identifier number for the download task that finished. -* success[boolean] : Indicates if the operation succeeded. Returns true if download succeeded, false otherwise. +* taskIdentifier[int] : The task identifier number for the download or upload task that finished. +* success[boolean] : Indicates if the operation succeeded. Returns true if download or upload succeeded, false otherwise. * errorCode[int] : The error code of the error, if any (potentially system-dependent). * message[string] : A string containing the localized description of the error. @@ -144,5 +155,5 @@ View the [change log](changelog.html) for this module. Please direct all questions, feedback, and concerns to [info@appcelerator.com](mailto:info@appcelerator.com?subject=iOS%20urlSesson%20Module). ## License -Copyright(c) 2010-2015 by Appcelerator, Inc. All Rights Reserved. Please see the LICENSE +Copyright(c) 2010-Present by Appcelerator, Inc. All Rights Reserved. Please see the LICENSE file included in the distribution for further details. diff --git a/ios/Classes/ComAppceleratorUrlSessionModule.h b/ios/Classes/ComAppceleratorUrlSessionModule.h index 13f737a..9854658 100644 --- a/ios/Classes/ComAppceleratorUrlSessionModule.h +++ b/ios/Classes/ComAppceleratorUrlSessionModule.h @@ -1,22 +1,30 @@ /** - * ti.urlsession - * - * Created by Your Name - * Copyright (c) 2015 Your Company. All rights reserved. + * Appcelerator Titanium Mobile + * Copyright (c) 2009-Present by Appcelerator, Inc. All Rights Reserved. + * Licensed under the terms of the Apache Public License + * Please see the LICENSE included with this distribution for details. */ #import "TiModule.h" -#import "SessionProxy.h" -#import "SessionConfigurationProxy.h" +#import "ComAppceleratorUrlSessionSessionProxy.h" +#import "ComAppceleratorUrlSessionSessionConfigurationProxy.h" #import #import @interface ComAppceleratorUrlSessionModule : TiModule {} --(SessionConfigurationProxy*)createURLSessionBackgroundConfiguration:(id)identifier; --(SessionProxy*)createURLSession:(id)sessionConfiguration; --(void)finishTasksAndInvalidate:(SessionProxy*)session; --(void)invalidateAndCancel:(SessionProxy*)session; --(NSNumber*)backgroundDownloadTaskWithURL:(id)args; +- (id)createURLSessionBackgroundConfiguration:(id)args; // Deprecated in 2.1.0: Use "createSessionConfiguration" instead. + +- (id)createURLSession:(id)args; // Deprecated in 2.1.0: Use "createSession" instead. + +- (id)backgroundDownloadTaskWithURL:(id)args; // Deprecated in 2.1.0: Use "addBackgroundDownloadTask" instead. + +- (void)finishTasksAndInvalidate:(id)value; // Deprecated in 2.1.0: Use "Session.finishTasksAndInvalidate" instead. + +- (void)invalidateAndCancel:(id)value; // Deprecated in 2.1.0: Use "Session.invalidateAndCancel" instead. + +- (id)createSessionConfiguration:(id)args; + +- (id)createSession:(id)args; @end diff --git a/ios/Classes/ComAppceleratorUrlSessionModule.m b/ios/Classes/ComAppceleratorUrlSessionModule.m index bcf51c9..a5402c7 100644 --- a/ios/Classes/ComAppceleratorUrlSessionModule.m +++ b/ios/Classes/ComAppceleratorUrlSessionModule.m @@ -1,128 +1,123 @@ /** - * ti.urlsession - * - * Created by Your Name - * Copyright (c) 2015 Your Company. All rights reserved. + * Appcelerator Titanium Mobile + * Copyright (c) 2009-Present by Appcelerator, Inc. All Rights Reserved. + * Licensed under the terms of the Apache Public License + * Please see the LICENSE included with this distribution for details. */ #import "ComAppceleratorUrlSessionModule.h" #import "TiBase.h" #import "TiHost.h" #import "TiUtils.h" +#import "TiBlob.h" @implementation ComAppceleratorUrlSessionModule #pragma mark Internal // this is generated for your module, please do not change it --(id)moduleGUID +- (id)moduleGUID { return @"276644d1-41e7-4c67-88a3-55d4fbfa0f24"; } // this is generated for your module, please do not change it --(NSString*)moduleId +- (NSString*)moduleId { return @"com.appcelerator.urlSession"; } #pragma mark Lifecycle --(void)startup +- (void)startup { // this method is called when the module is first loaded // you *must* call the superclass [super startup]; - NSLog(@"[INFO] %@ loaded",self); + NSLog(@"[DEBUG] %@ loaded",self); } --(void)shutdown:(id)sender -{ - // this method is called when the module is being unloaded - // typically this is during shutdown. make sure you don't do too - // much processing here or the app will be quit forceably - - // you *must* call the superclass - [super shutdown:sender]; -} - -#pragma Public APIs +#pragma mark Public APIs --(SessionConfigurationProxy*)createURLSessionBackgroundConfiguration:(id)identifier; +- (id)createSessionConfiguration:(id)args { - ENSURE_SINGLE_ARG(identifier, NSString); + ENSURE_SINGLE_ARG(args, NSDictionary); - if([identifier length] != 0) { - return [[SessionConfigurationProxy alloc] initWithIdentifier:[TiUtils stringValue:identifier]]; - } + id identifier = [args objectForKey:@"identifier"]; + ENSURE_TYPE(identifier, NSString); - NSLog(@"[ERROR] Need to specify a proper identifier to create a URLSessionConfiguration."); - return nil; + return [[ComAppceleratorUrlSessionSessionConfigurationProxy alloc] _initWithPageContext:[self pageContext] andArguments:args]; } --(SessionProxy*)createURLSession:(id)sessionConfiguration; +- (id)createSession:(id)args { - ENSURE_SINGLE_ARG(sessionConfiguration, SessionConfigurationProxy); + NSMutableDictionary *params = [NSMutableDictionary dictionary]; - if ([sessionConfiguration sessionConfiguration] != nil) { - return [[SessionProxy alloc] initWithSessionConfiguration:[sessionConfiguration sessionConfiguration]]; + if ([[args objectAtIndex:0] isKindOfClass:[ComAppceleratorUrlSessionSessionConfigurationProxy class]]) { + // Deprecated + NSLog(@"[WARN] Ti.URLSession: Providing the configuration as a single argument is deprecated in 2.1.0, please use the 'configuration' key instead."); + [params setObject:[args objectAtIndex:0] forKey:@"configuration"]; + } else if ([[args objectAtIndex:0] isKindOfClass:[NSDictionary class]]) { + params = (NSMutableDictionary*)[args objectAtIndex:0]; + } else { + NSLog(@"[ERROR] Ti.URLSession: Cannot create URLSession. Please provide a proper SessionConfiguration object."); + return [NSNull null]; } - NSLog(@"[ERROR] Cannot create URLSession. Please provide a proper session configuration object."); - return nil; + return [[ComAppceleratorUrlSessionSessionProxy alloc] _initWithPageContext:[self pageContext] andArguments:params]; } --(void)finishTasksAndInvalidate:(id)value -{ - ENSURE_SINGLE_ARG(value, SessionProxy); +#pragma mark - Deprecated - NSURLSession *session = [(SessionProxy*)value session]; +- (id)createURLSessionBackgroundConfiguration:(id)args +{ + NSLog(@"[WARN] Ti.URLSession: 'createURLSessionBackgroundConfiguration()' has been deprecated and replaced with 'createSessionConfiguration({identifier: })' in 2.1.0"); - if (session != nil) { - [session finishTasksAndInvalidate]; + if ([[args objectAtIndex:0] isKindOfClass:[NSString class]]) { + NSDictionary *params = @{@"identifier": [args objectAtIndex:0]}; + return [self createSessionConfiguration:@[params]]; } else { - NSLog(@"[ERROR] Provided session is empty. Please provide a proper session to invalidate."); + NSLog(@"[ERROR] Ti.URLSession: Need to specify a proper identifier to create a URLSessionConfiguration."); + return [NSNull null]; } } --(void)invalidateAndCancel:(id)value +- (id)createURLSession:(id)args { - ENSURE_SINGLE_ARG(value, SessionProxy); + DEPRECATED_REPLACED(@"URLSession.createURLSession", @"2.1.0", @"URLSession.createSession"); - NSURLSession *session = [(SessionProxy*)value session]; - - if (session != nil) { - [session invalidateAndCancel]; - } else { - NSLog(@"[ERROR] Provided session is empty. Please provide a proper session to invalidate."); - } + return [self createSession:args]; } --(NSNumber*)backgroundDownloadTaskWithURL:(id)args +- (id)backgroundDownloadTaskWithURL:(id)args { + DEPRECATED_REPLACED(@"URLSession.backgroundDownloadTaskWithURL", @"2.1.0", @"URLSession.Session.downloadTask"); + ENSURE_ARG_COUNT(args, 2); - SessionProxy *session = nil; - NSString *url = nil; + ComAppceleratorUrlSessionSessionProxy *session; + ENSURE_ARG_AT_INDEX(session, args, 0, ComAppceleratorUrlSessionSessionProxy); + ENSURE_TYPE([args objectAtIndex:1], NSString); - ENSURE_ARG_AT_INDEX(session, args, 0, SessionProxy); - ENSURE_ARG_AT_INDEX(url, args, 1, NSString); + return [session downloadTask:@{@"url": [TiUtils stringValue:[args objectAtIndex:1]]}]; +} + +- (void)finishTasksAndInvalidate:(id)value +{ + DEPRECATED_REPLACED(@"URLSession.finishTasksAndInvalidate", @"2.1.0", @"URLSession.Session.finishTasksAndInvalidate"); + + ENSURE_SINGLE_ARG(value, ComAppceleratorUrlSessionSessionProxy); - if ([(SessionProxy*)session session] != nil) { - if ([url length] != 0) { - NSURLSessionDownloadTask *task = [[(SessionProxy*)session session] downloadTaskWithURL:[NSURL URLWithString:url]]; - [task resume]; - - return NUMINTEGER([task taskIdentifier]); - } else { - NSLog(@"[ERROR] The specified url for background download task is empty. Please provide a proper url."); - } - } else { - NSLog(@"[ERROR] Need to specify a proper URLSession to start a background download task."); - } + [value finishTasksAndInvalidate:nil]; +} - return nil; +- (void)invalidateAndCancel:(id)value +{ + ENSURE_SINGLE_ARG(value, ComAppceleratorUrlSessionSessionProxy); + DEPRECATED_REPLACED(@"URLSession.invalidateAndCancel", @"2.1.0", @"URLSession.Session.invalidateAndCancel"); + + [value invalidateAndCancel:nil]; } @end diff --git a/ios/Classes/ComAppceleratorUrlSessionSessionConfigurationProxy.h b/ios/Classes/ComAppceleratorUrlSessionSessionConfigurationProxy.h new file mode 100644 index 0000000..017ca4c --- /dev/null +++ b/ios/Classes/ComAppceleratorUrlSessionSessionConfigurationProxy.h @@ -0,0 +1,21 @@ +/** + * Appcelerator Titanium Mobile + * Copyright (c) 2009-Present by Appcelerator, Inc. All Rights Reserved. + * Licensed under the terms of the Apache Public License + * Please see the LICENSE included with this distribution for details. + */ +#import "TiProxy.h" +#import "TiModule.h" + +@interface ComAppceleratorUrlSessionSessionConfigurationProxy : TiProxy { +@private + NSURLSessionConfiguration *sessionConfiguration; +} + +- (NSURLSessionConfiguration*)sessionConfiguration; +- (id)_initWithPageContext:(id)context andArguments:(NSDictionary*)args; + +- (void)setHTTPHeaderFields:(id)args; +- (id)HTTPHeaderFields; + +@end diff --git a/ios/Classes/ComAppceleratorUrlSessionSessionConfigurationProxy.m b/ios/Classes/ComAppceleratorUrlSessionSessionConfigurationProxy.m new file mode 100644 index 0000000..0f558a9 --- /dev/null +++ b/ios/Classes/ComAppceleratorUrlSessionSessionConfigurationProxy.m @@ -0,0 +1,57 @@ +/** + * Appcelerator Titanium Mobile + * Copyright (c) 2009-Present by Appcelerator, Inc. All Rights Reserved. + * Licensed under the terms of the Apache Public License + * Please see the LICENSE included with this distribution for details. + */ + +#import "ComAppceleratorUrlSessionSessionConfigurationProxy.h" + +@implementation ComAppceleratorUrlSessionSessionConfigurationProxy + +#pragma mark Internal API's + +- (id)_initWithPageContext:(id)context andArguments:(NSDictionary*)args +{ + if (self = [super _initWithPageContext:context]) { + NSString *identifier = [args objectForKey:@"identifier"]; + + if ([TiUtils isIOS8OrGreater] == YES) { + sessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:identifier]; + } else { + sessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfiguration:identifier]; + } + } + return self; +} + +- (NSURLSessionConfiguration*)sessionConfiguration +{ + if (sessionConfiguration == nil) { + NSLog(@"[ERROR] Ti.URLSession: sessionConfiguration should not be nil at this point!!"); + } + + return sessionConfiguration; +} + +#pragma mark Public API's + +- (void)setHTTPHeaderFields:(id)args +{ + ENSURE_TYPE(args, NSDictionary); + + // Keys and values need to be strings + for (id key in [args allKeys]) { + ENSURE_TYPE(key, NSString); + ENSURE_TYPE([args objectForKey:key], NSString); + } + + [sessionConfiguration setHTTPAdditionalHeaders:args]; +} + +- (id)HTTPHeaderFields +{ + return [sessionConfiguration HTTPAdditionalHeaders] ?: @{}; +} + +@end diff --git a/ios/Classes/ComAppceleratorUrlSessionSessionProxy.h b/ios/Classes/ComAppceleratorUrlSessionSessionProxy.h new file mode 100644 index 0000000..cbdc94b --- /dev/null +++ b/ios/Classes/ComAppceleratorUrlSessionSessionProxy.h @@ -0,0 +1,36 @@ +/** + * Appcelerator Titanium Mobile + * Copyright (c) 2009-Present by Appcelerator, Inc. All Rights Reserved. + * Licensed under the terms of the Apache Public License + * Please see the LICENSE included with this distribution for details. + */ +#import "TiProxy.h" +#import "TiModule.h" +#import "ComAppceleratorUrlSessionSessionConfigurationProxy.h" + +@interface ComAppceleratorUrlSessionSessionProxy : TiProxy { +@private + ComAppceleratorUrlSessionSessionConfigurationProxy *sessionConfiguration; +} + +#pragma mark Proxy Handling + +@property(nonatomic, strong) NSURLSession *session; + +- (id)_initWithPageContext:(id)context andArguments:(NSDictionary*)args; + +#pragma mark Public API's + +- (id)uploadTask:(id)args; + +- (id)downloadTask:(id)args; + +- (void)finishTasksAndInvalidate:(id)unused; + +- (void)invalidateAndCancel:(id)unused; + +- (void)reset:(id)value; + +- (void)flush:(id)value; + +@end diff --git a/ios/Classes/ComAppceleratorUrlSessionSessionProxy.m b/ios/Classes/ComAppceleratorUrlSessionSessionProxy.m new file mode 100644 index 0000000..fb85349 --- /dev/null +++ b/ios/Classes/ComAppceleratorUrlSessionSessionProxy.m @@ -0,0 +1,140 @@ +/** + * Appcelerator Titanium Mobile + * Copyright (c) 2009-Present by Appcelerator, Inc. All Rights Reserved. + * Licensed under the terms of the Apache Public License + * Please see the LICENSE included with this distribution for details. + */ + +#import "ComAppceleratorUrlSessionSessionProxy.h" + +@implementation ComAppceleratorUrlSessionSessionProxy + +@synthesize session = _session; + +#pragma mark Internal API's + +- (id)_initWithPageContext:(id)context andArguments:(NSDictionary*)args +{ + if (self = [super _initWithPageContext:context]) { + sessionConfiguration = [args objectForKey:@"configuration"]; + [self rememberProxy:sessionConfiguration]; + + _session = [NSURLSession sessionWithConfiguration:[sessionConfiguration sessionConfiguration] + delegate:(id)[[UIApplication sharedApplication] delegate] + delegateQueue:nil]; + } + + return self; +} + +- (NSURLSession*)session +{ + if (_session == nil) { + NSLog(@"[ERROR] Ti.URLSession: session should not be nil at this point!!"); + } + + return _session; +} + +#pragma mark Public API's + +- (id)uploadTask:(id)args +{ + ENSURE_SINGLE_ARG(args, NSDictionary); + + NSURLSessionUploadTask *task = nil; + NSString *url = nil; + NSString *method = nil; + NSURL *fileURL = nil; + NSDictionary *headers = nil; + id data = [args objectForKey:@"data"];; + + ENSURE_ARG_FOR_KEY(url, args, @"url", NSString); + ENSURE_ARG_OR_NIL_FOR_KEY(method, args, @"method", NSString); + ENSURE_ARG_OR_NIL_FOR_KEY(headers, args, @"requestHeaders", NSDictionary); + + if ([url length] != 0) { + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]]; + + // HTTP method + [request setHTTPMethod:(method ?: @"POST")]; + + // Optional request headers + if (headers) { + for (id key in headers) { + ENSURE_TYPE(key, NSString); + ENSURE_TYPE([headers objectForKey:key], NSString); + + [request setValue:[headers objectForKey:key] forHTTPHeaderField:key]; + } + } + + if ([data isKindOfClass:[NSString class]]) { + fileURL = [TiUtils toURL:data proxy:self]; + task = [_session uploadTaskWithRequest:request fromFile:fileURL]; + } else if ([data isMemberOfClass:[TiBlob class]]) { + task = [_session uploadTaskWithRequest:request fromData:[data data]]; + } else { + NSLog(@"[ERROR] Ti.URLSession: The specified data for background upload task is incorrect. Please provide a file path or a blob."); + return [NSNull null]; + } + + [task resume]; + + return NUMINTEGER([task taskIdentifier]); + } else { + NSLog(@"[ERROR] Ti.URLSession: The specified URL for this background upload task is empty. Please provide a valid URL."); + } + + return nil; +} + +- (id)downloadTask:(id)args +{ + ENSURE_SINGLE_ARG(args, NSDictionary); + + NSString *url = [TiUtils stringValue:@"url" properties:args]; + + if ([url length]) { + NSURLSessionDownloadTask *task = [_session downloadTaskWithURL:[NSURL URLWithString:url]]; + [task resume]; + + return NUMINTEGER([task taskIdentifier]); + } else { + NSLog(@"[ERROR] Ti.URLSession: The specified url for background download task is empty. Please provide a proper url."); + } + + return nil; +} + +- (void)finishTasksAndInvalidate:(id)unused +{ + [_session finishTasksAndInvalidate]; +} + +- (void)invalidateAndCancel:(id)unused +{ + [_session invalidateAndCancel]; +} + +- (void)reset:(id)value +{ + ENSURE_SINGLE_ARG(value, KrollCallback); + + [_session resetWithCompletionHandler:^{ + NSDictionary * propertiesDict = @{@"completed": NUMBOOL(YES)}; + [value call:[[NSArray alloc] initWithObjects:&propertiesDict count:1] thisObject:self]; + }]; +} + +- (void)flush:(id)value +{ + ENSURE_SINGLE_ARG(value, KrollCallback); + + [_session flushWithCompletionHandler:^{ + NSDictionary * propertiesDict = @{@"completed": NUMBOOL(YES)}; + [(KrollCallback*)value call:[[NSArray alloc] initWithObjects:&propertiesDict count:1] thisObject:self]; + }]; +} + +@end diff --git a/ios/Classes/SessionProxy.h b/ios/Classes/SessionProxy.h deleted file mode 100644 index b42e656..0000000 --- a/ios/Classes/SessionProxy.h +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Appcelerator Titanium Mobile - * Copyright (c) 2009-2015 by Appcelerator, Inc. All Rights Reserved. - * Licensed under the terms of the Apache Public License - * Please see the LICENSE included with this distribution for details. - */ -#import "TiProxy.h" -#import - -@interface SessionProxy : TiProxy - -@property(nonatomic,retain) NSURLSession* session; - --(instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration*)sessionConfiguration; - -@end diff --git a/ios/Classes/SessionProxy.m b/ios/Classes/SessionProxy.m deleted file mode 100644 index fa2ca71..0000000 --- a/ios/Classes/SessionProxy.m +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Appcelerator Titanium Mobile - * Copyright (c) 2009-2015 by Appcelerator, Inc. All Rights Reserved. - * Licensed under the terms of the Apache Public License - * Please see the LICENSE included with this distribution for details. - */ - -#import "SessionProxy.h" - -@implementation SessionProxy - --(instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration*)sessionConfiguration -{ - if(self = [super init]) { - id delegate = (id)[[UIApplication sharedApplication] delegate]; - [self setSession:[NSURLSession sessionWithConfiguration:sessionConfiguration delegate:delegate delegateQueue:nil]]; - } - - return self; -} - -@end diff --git a/ios/README b/ios/README deleted file mode 100644 index fbbb94a..0000000 --- a/ios/README +++ /dev/null @@ -1,151 +0,0 @@ -Appcelerator Titanium iPhone Module Project -=========================================== - -This is a skeleton Titanium Mobile iPhone module project. Modules can be -used to extend the functionality of Titanium by providing additional native -code that is compiled into your application at build time and can expose certain -APIs into JavaScript. - -MODULE NAMING --------------- - -Choose a unique module id for your module. This ID usually follows a namespace -convention using DNS notation. For example, com.appcelerator.module.test. This -ID can only be used once by all public modules in Titanium. - - -COMPONENTS ------------ - -Components that are exposed by your module must follow a special naming convention. -A component (widget, proxy, etc) must be named with the pattern: - - TiProxy - -For example, if you component was called Foo, your proxy would be named: - - TiMyfirstFooProxy - -For view proxies or widgets, you must create both a view proxy and a view implementation. -If you widget was named proxy, you would create the following files: - - TiMyfirstFooProxy.h - TiMyfirstFooProxy.m - TiMyfirstFoo.h - TiMyfirstFoo.m - -The view implementation is named the same except it does contain the suffix `Proxy`. - -View implementations extend the Titanium base class `TiUIView`. View Proxies extend the -Titanium base class `TiUIViewProxy` or `TiUIWidgetProxy`. - -For proxies that are simply native objects that can be returned to JavaScript, you can -simply extend `TiProxy` and no view implementation is required. - - -GET STARTED ------------- - -1. Edit manifest with the appropriate details about your module. -2. Edit LICENSE to add your license details. -3. Place any assets (such as PNG files) that are required in the assets folder. -4. Edit the titanium.xcconfig and make sure you're building for the right Titanium version. -5. Code and build. - -BUILD TIME COMPILER CONFIG --------------------------- - -You can edit the file `module.xcconfig` to include any build time settings that should be -set during application compilation that your module requires. This file will automatically get `#include` in the main application project. - -For more information about this file, please see the Apple documentation at: - - - - -DOCUMENTATION FOR YOUR MODULE ------------------------------ - -You should provide at least minimal documentation for your module in `documentation` folder using the Markdown syntax. - -For more information on the Markdown syntax, refer to this documentation at: - - - - -TEST HARNESS EXAMPLE FOR YOUR MODULE ------------------------------------- - -The `example` directory contains a skeleton application test harness that can be -used for testing and providing an example of usage to the users of your module. - - -INSTALL YOUR MODULE --------------------- - -1. Run `build.py` which creates your distribution -2. cd to `/Library/Application Support/Titanium` -3. copy this zip file into the folder of your Titanium SDK - -REGISTER YOUR MODULE ---------------------- - -Register your module with your application by editing `tiapp.xml` and adding your module. -Example: - - - __MODULE_ID__ - - -When you run your project, the compiler will know automatically compile in your module -dependencies and copy appropriate image assets into the application. - -USING YOUR MODULE IN CODE -------------------------- - -To use your module in code, you will need to require it. - -For example, - - var my_module = require('__MODULE_ID__'); - my_module.foo(); - -WRITING PURE JS NATIVE MODULES ------------------------------- - -You can write a pure JavaScript "natively compiled" module. This is nice if you -want to distribute a JS module pre-compiled. - -To create a module, create a file named __MODULE_ID__.js under the assets folder. -This file must be in the Common JS format. For example: - - exports.echo = function(s) - { - return s; - }; - -Any functions and properties that are exported will be made available as part of your -module. All other code inside your JS will be private to your module. - -For pure JS module, you don't need to modify any of the Objective-C module code. You -can leave it as-is and build. - -TESTING YOUR MODULE -------------------- - -Run the `titanium.py` script to test your module or test from within XCode. -To test with the script, execute: - - titanium run --dir=YOURMODULEDIR - - -This will execute the app.js in the example folder as a Titanium application. - - -DISTRIBUTING YOUR MODULE -------------------------- - -Currently, you will need to manually distribution your module distribution zip file directly. However, in the near future, we will make module distribution and sharing built-in to Titanium Developer and in the Titanium Marketplace! - - -Cheers! diff --git a/ios/SessionConfigurationProxy.h b/ios/SessionConfigurationProxy.h deleted file mode 100644 index 1c9bbce..0000000 --- a/ios/SessionConfigurationProxy.h +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Appcelerator Titanium Mobile - * Copyright (c) 2009-2015 by Appcelerator, Inc. All Rights Reserved. - * Licensed under the terms of the Apache Public License - * Please see the LICENSE included with this distribution for details. - */ -#import "TiProxy.h" -#import "TiModule.h" -#import - -@interface SessionConfigurationProxy : TiProxy - -@property(nonatomic, retain) NSURLSessionConfiguration *sessionConfiguration; - --(instancetype)initWithIdentifier:(NSString*)identifier; - -@end diff --git a/ios/SessionConfigurationProxy.m b/ios/SessionConfigurationProxy.m deleted file mode 100644 index 6ec0d2d..0000000 --- a/ios/SessionConfigurationProxy.m +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Appcelerator Titanium Mobile - * Copyright (c) 2009-2015 by Appcelerator, Inc. All Rights Reserved. - * Licensed under the terms of the Apache Public License - * Please see the LICENSE included with this distribution for details. - */ - -#import "SessionConfigurationProxy.h" - -@implementation SessionConfigurationProxy - --(instancetype)initWithIdentifier:(NSString *)identifier -{ - if(self = [super init]) { - - // TODO: Remove backgroundSessionConfiguration after we make iOS8 as the minimum SDK. - if ([TiUtils isIOS8OrGreater] == YES) { - [self setSessionConfiguration:[NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:identifier]]; - } else { - [self setSessionConfiguration:[NSURLSessionConfiguration backgroundSessionConfiguration:identifier]]; - } - } - - return self; -} - -@end diff --git a/ios/build.py b/ios/build.py old mode 100755 new mode 100644 diff --git a/ios/example/app.js b/ios/example/app.js index bc195b7..a38dfba 100644 --- a/ios/example/app.js +++ b/ios/example/app.js @@ -1,190 +1,243 @@ -//This is a more rudimentary test to ensure that downloads continue while in the background of the app. -//global variables -var bgDownload = require("com.appcelerator.urlSession"); -Ti.App.iOS.setMinimumBackgroundFetchInterval(Ti.App.iOS.BACKGROUNDFETCHINTERVAL_MIN); +var URLSession = require('com.appcelerator.urlSession'); + var bgHandlerID, - sessionConfig, - session, - appUI = {}, - dlProgress = 0, - dlStarted = false, - isBGTransferMode = false, - UIready = false, - bgSessionCreated = false; - -Ti.App.iOS.addEventListener('backgroundfetch', function(event){ - Ti.API.info("Backgroundfetch Event Fired !!! :: " + JSON.stringify(event)); - - //When this function is called always create a session variable so that events are propagated to it. - bgHandlerID = event.handlerId; - sessionConfig = bgDownload.createURLSessionBackgroundConfiguration("com.test.test2"); - session = bgDownload.createURLSession(sessionConfig); - var taskIdentifier = bgDownload.backgroundDownloadTaskWithURL(session,"http://yourshot.nationalgeographic.com/exposure/content/photo/photo/1879122_uploadsmember258527yourshot-258527-1879122jpg_z5n3nv2g7piofy6fkaewns5su56efp7ahougetfp4dbeloye3ueq_2880x1922.jpg"); - var pendingDL = Ti.App.Properties.getObject('pendingDL'); - if (pendingDL == null){ - pendingDL = []; - } - pendingDL.push(taskIdentifier); - Ti.App.Properties.setObject('pendingDL',pendingDL); - - //Start download and end the task. - Ti.App.iOS.endBackgroundHandler(bgHandlerID); + sessionConfig, + session, + dlProgress = 0, + dlStarted = false, + isBGTransferMode = false, + UIready = false, + bgSessionCreated = false; + +/** Create UI **/ + +var window = Ti.UI.createWindow({ + backgroundColor: 'white', + title: 'Ti.URLSession' +}); +var nav = Ti.UI.iOS.createNavigationWindow({ + window: window }); -Ti.App.iOS.addEventListener('backgroundtransfer', function(event){ - Ti.API.info("Backgroundtransfer Event Fired !!! :: " + JSON.stringify(event)); - if (!bgSessionCreated && session == null) { - //When this function is called always create a session variable so that events are propagated to it. - bgHandlerID = event.handlerId; - sessionConfig = bgDownload.createURLSessionBackgroundConfiguration("com.test.test2"); - session = bgDownload.createURLSession(sessionConfig); - isBGTransferMode =true; - bgSessionCreated = true; - } +var triggerButton = Titanium.UI.createButton({ + title: 'Start Download' +}); + +var listView = Ti.UI.createListView({ + style: Ti.UI.iOS.ListViewStyle.GROUPED, + sections: refreshSection() +}); + +triggerButton.addEventListener('click', triggerDownload); + +window.addEventListener('open', function() { + UIready = true; +}); + +window.setRightNavButton(triggerButton); +window.add(listView); + +nav.open(); + +/** Create Handlers **/ + +Ti.App.iOS.setMinimumBackgroundFetchInterval(Ti.App.iOS.BACKGROUNDFETCHINTERVAL_MIN); + +Ti.App.iOS.addEventListener('backgroundfetch', function(event) { + Ti.API.info('Backgroundfetch Event Fired !!! :: ' + JSON.stringify(event)); + + // When this function is called always create a session variable so that events are propagated to it. + bgHandlerID = event.handlerId; + sessionConfig = URLSession.createSessionConfiguration({ + identifier: 'com.test.test2' + }); + session = URLSession.createSession({ + configuration: sessionConfig + }); + var taskIdentifier = session.downloadTask({ + url: 'http://yourshot.nationalgeographic.com/exposure/content/photo/photo/1879122_uploadsmember258527yourshot-258527-1879122jpg_z5n3nv2g7piofy6fkaewns5su56efp7ahougetfp4dbeloye3ueq_2880x1922.jpg' + }); + var pendingDL = Ti.App.Properties.getObject('pendingDL'); + if (pendingDL == null) { + pendingDL = []; + } + pendingDL.push(taskIdentifier); + Ti.App.Properties.setObject('pendingDL', pendingDL); + + // Start download and end the task. + Ti.App.iOS.endBackgroundHandler(bgHandlerID); }); + +Ti.App.iOS.addEventListener('backgroundtransfer', function(event) { + Ti.API.info('Backgroundtransfer Event Fired !!! :: ' + JSON.stringify(event)); + if (!bgSessionCreated && session == null) { + //When this function is called always create a session variable so that events are propagated to it. + bgHandlerID = event.handlerId; + sessionConfig = URLSession.createSessionConfiguration({ + identifier: 'com.test.test2' + }); + session = URLSession.createSession({ + configuration: sessionConfig + }); + isBGTransferMode = true; + bgSessionCreated = true; + } +}); -Ti.App.iOS.addEventListener('downloadprogress' ,function (event){ - if (!dlStarted) { - dlStarted = true; - } - Ti.API.info("downloadprogress Event Fired !!! :: " + JSON.stringify(event)); - dlProgress = (event.totalBytesWritten/event.totalBytesExpectedToWrite) * 100; - Ti.API.info("Completed : " + dlProgress + '% of task number :' + event.taskIdentifier); +Ti.App.iOS.addEventListener('downloadprogress', function(event) { + if (!dlStarted) { + dlStarted = true; + } + Ti.API.info('downloadprogress Event Fired !!! :: ' + JSON.stringify(event)); + Ti.API.info('Completed : ' + dlProgress + '% of task number :' + event.taskIdentifier); + + dlProgress = (event.totalBytesWritten / event.totalBytesExpectedToWrite) * 100; }); -Ti.App.iOS.addEventListener('downloadcompleted' ,function (event){ - Ti.API.info("downloadcompleted Event Fired !!! :: " + JSON.stringify(event)); +Ti.App.iOS.addEventListener('downloadcompleted', function(event) { + Ti.API.info('downloadcompleted Event Fired !!! :: ' + JSON.stringify(event)); + var timestamp = new Date().getTime(); - var filename = Titanium.Filesystem.applicationDataDirectory + "/"+ 'downloadedfile' + new Date().getTime() + ".png"; - var result = Titanium.Filesystem.getFile(filename); + var filename = Titanium.Filesystem.applicationDataDirectory + '/' + 'downloadedfile' + new Date().getTime() + '.png'; + var result = Titanium.Filesystem.getFile(filename); + result.write(event.data); - }); -Ti.App.iOS.addEventListener('sessioncompleted' ,function (event){ - Ti.API.info("sessioncompleted Event Fired !!! :: " + JSON.stringify(event)); +Ti.App.iOS.addEventListener('sessioncompleted', function(event) { + Ti.API.info('sessioncompleted Event Fired !!! :: ' + JSON.stringify(event)); + var pendingDL = Ti.App.Properties.getObject('pendingDL'); - for (var i = 0; i < pendingDL.length ; i++) { - if (pendingDL[i] == event.taskIdentifier) { - pendingDL.splice(i,1); - } - } - Ti.App.Properties.setObject('pendingDL',pendingDL); + for (var i = 0; i < pendingDL.length; i++) { + if (pendingDL[i] == event.taskIdentifier) { + pendingDL.splice(i, 1); + } + } + + Ti.App.Properties.setObject('pendingDL', pendingDL); + if (UIready) { - appUI.listView.setSections(refreshSection()); - } - //This is where you check for errors. - - //handle case where download failed due to connection failure - /* Eg : { - * "errorCode":-1009, - * "taskIdentifier":0, - * "message":"The Internet connection appears to be offline.", - * "success":false - * } - */ - - Ti.API.info("Download task :"+ event.taskIdentifier+" completed, success ? : " + event.success); + listView.setSections(refreshSection()); + } -}); + // Handle case where download failed due to connection failure + /* Eg : { + * 'errorCode':-1009, + * 'taskIdentifier':0, + * 'message':'The Internet connection appears to be offline.', + * 'success':false + * } + */ -Ti.App.iOS.addEventListener('sessioneventscompleted' ,function (event){ - //This is where you call your backgroundTransfer endBackgroundHandler - - Ti.API.info("sessioneventscompleted Event Fired !!! :: " + JSON.stringify(event)); - if(isBGTransferMode) { - var pendingDL = Ti.App.Properties.getObject('pendingDL'); - if (pendingDL == null){ - pendingDL = []; - } - if (pendingDL.length == 0) { - Ti.App.iOS.endBackgroundHandler(bgHandlerID); - } - } - var notification = Ti.App.iOS.scheduleLocalNotification({ - alertBody:"sessioneventscompleted event Fired", - date:new Date().getTime() - }); + Ti.API.info('Download task :' + event.taskIdentifier + ' completed, success: ' + event.success); }); -appUI.keyWindow = Ti.UI.createWindow({backgroundColor:"white"}); -appUI.b1 = Titanium.UI.createButton({ - title:'Download Image (url)', - height:40, - width:200, - top:70 -}); -appUI.keyWindow.add(appUI.b1); +Ti.App.iOS.addEventListener('sessioneventscompleted', function(event) { + // This is where you call your backgroundTransfer endBackgroundHandler -function getpendingdata(){ + Ti.API.info('sessioneventscompleted Event Fired !!! :: ' + JSON.stringify(event)); + + if (isBGTransferMode) { + var pendingDL = Ti.App.Properties.getObject('pendingDL'); + if (pendingDL == null) { + pendingDL = []; + } + if (pendingDL.length == 0) { + Ti.App.iOS.endBackgroundHandler(bgHandlerID); + } + } + + var notification = Ti.App.iOS.scheduleLocalNotification({ + alertBody: 'sessioneventscompleted event Fired', + date: new Date().getTime() + }); +}); +function getPendingData() { var data = []; var pendingDL = Ti.App.Properties.getObject('pendingDL'); var length = pendingDL == null ? 0 : pendingDL.length; - for(var i = 0; i < length; i++) - { - data.push({template:Ti.UI.LIST_ITEM_TEMPLATE_DEFAULT, properties: {title:'task ID : ' + pendingDL[i],color:'yellow'}}); + + for (var i = 0; i < length; i++) { + data.push({ + properties: { + title: 'Downloading with Task ID ' + pendingDL[i] + ' ...', + color: 'orange' + } + }); } + + if (data.length == 0) { + data.push({ + properties: { + title: 'No pending Downloads', + selectionStyle: Ti.UI.iOS.ListViewCellSelectionStyle.NONE + } + }); + } + return data; } -function getDataFromDataDirectory(){ - var data = []; - var dirTest = Titanium.Filesystem.getFile(Titanium.Filesystem.applicationDataDirectory); - var dirList = dirTest.getDirectoryListing(); - for ( i = 0; i < dirList.length; ++i){ - if (dirList[i].match(/^downloadedfile\d*\.png$/)) { - data.push({template:Ti.UI.LIST_ITEM_TEMPLATE_DEFAULT, properties: {title:dirList[i],color:'green'}}); - } - } - return data; +function getDataFromDataDirectory() { + var data = []; + var dirTest = Titanium.Filesystem.getFile(Titanium.Filesystem.applicationDataDirectory); + var dirList = dirTest.getDirectoryListing(); + + for (i = 0; i < dirList.length; ++i) { + if (dirList[i].match(/^downloadedfile\d*\.png$/)) { + data.push({ + properties: { + title: dirList[i], + selectionStyle: Ti.UI.iOS.ListViewCellSelectionStyle.NONE + } + }); + } + } + + return data; } -function refreshSection(){ - var listSection1 = Ti.UI.createListSection({ - headerTitle:'PENDING DOWNLOADS' +function refreshSection() { + var listSection1 = Ti.UI.createListSection({ + headerTitle: 'Pending Downloads' }); - listSection1.setItems(getpendingdata()); - - var listSection2 = Ti.UI.createListSection({ - headerTitle:'DOWNLOADED FILES' - }); - listSection2.setItems(getDataFromDataDirectory()); - var sections = []; - sections.push(listSection1); - sections.push(listSection2); - return sections; + listSection1.setItems(getPendingData()); + + var listSection2 = Ti.UI.createListSection({ + headerTitle: 'Downloaded Files' + }); + listSection2.setItems(getDataFromDataDirectory()); + + return [listSection1, listSection2]; } -appUI.b1.addEventListener('click', function() -{ - - sessionConfig = bgDownload.createURLSessionBackgroundConfiguration("com.test.test2"); - session = bgDownload.createURLSession(sessionConfig); + +function triggerDownload() { + sessionConfig = URLSession.createSessionConfiguration({ + identifier: 'com.test.test2' + }); + + session = URLSession.createSession({ + configuration: sessionConfig + }); + bgSessionCreated = true; + if (session != null) { - //alternate smaller file = "http://yourshot.nationalgeographic.com/exposure/content/photo/photo/1879122_uploadsmember258527yourshot-258527-1879122jpg_z5n3nv2g7piofy6fkaewns5su56efp7ahougetfp4dbeloye3ueq_2880x1922.jpg" - var taskIdentifier = bgDownload.backgroundDownloadTaskWithURL(session,"https://www.dropbox.com/s/x9pud64xo7s1pb6/IMG_20130715_181727.jpg"); - var pendingDL = Ti.App.Properties.getObject('pendingDL'); - if (pendingDL == null){ - pendingDL = []; - } - pendingDL.push(taskIdentifier); - Ti.App.Properties.setObject('pendingDL',pendingDL); - appUI.listView.setSections(refreshSection()); - } - -}); -appUI.keyWindow.addEventListener('open', function(){ - UIready = true; -}); - -appUI.view = Ti.UI.createView({top: 150,height:300, width: 300}); -appUI.keyWindow.add(appUI.view); -appUI.listView = Ti.UI.createListView(); -appUI.listView.setSections(refreshSection()); -appUI.view.add(appUI.listView); -appUI.keyWindow.open(); + // Alternate smaller file = 'http://yourshot.nationalgeographic.com/exposure/content/photo/photo/1879122_uploadsmember258527yourshot-258527-1879122jpg_z5n3nv2g7piofy6fkaewns5su56efp7ahougetfp4dbeloye3ueq_2880x1922.jpg' + var taskIdentifier = session.downloadTask({ + url: 'https://www.dropbox.com/s/x9pud64xo7s1pb6/IMG_20130715_181727.jpg' + }); + var pendingDL = Ti.App.Properties.getObject('pendingDL'); + if (pendingDL == null) { + pendingDL = []; + } + pendingDL.push(taskIdentifier); + Ti.App.Properties.setObject('pendingDL', pendingDL); + listView.setSections(refreshSection()); + } +} diff --git a/ios/manifest b/ios/manifest index ccf7399..b48cdb5 100644 --- a/ios/manifest +++ b/ios/manifest @@ -2,7 +2,7 @@ # this is your module manifest and used by Titanium # during compilation, packaging, distribution, etc. # -version: 2.0.0 +version: 2.1.0 apiversion: 2 architectures: armv7 arm64 i386 x86_64 description: ti.urlsession diff --git a/ios/metadata.json b/ios/metadata.json new file mode 100644 index 0000000..43a62e5 --- /dev/null +++ b/ios/metadata.json @@ -0,0 +1 @@ +{"exports":[]} \ No newline at end of file diff --git a/ios/ti.urlsession.xcodeproj/project.pbxproj b/ios/ti.urlsession.xcodeproj/project.pbxproj index 0a788e4..731c7f5 100644 --- a/ios/ti.urlsession.xcodeproj/project.pbxproj +++ b/ios/ti.urlsession.xcodeproj/project.pbxproj @@ -26,12 +26,12 @@ 24DD6CFA1134B3F500162E58 /* ComAppceleratorUrlSessionModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 24DD6CF81134B3F500162E58 /* ComAppceleratorUrlSessionModule.m */; }; 24DE9E1111C5FE74003F90F6 /* ComAppceleratorUrlSessionModuleAssets.h in Headers */ = {isa = PBXBuildFile; fileRef = 24DE9E0F11C5FE74003F90F6 /* ComAppceleratorUrlSessionModuleAssets.h */; }; 24DE9E1211C5FE74003F90F6 /* ComAppceleratorUrlSessionModuleAssets.m in Sources */ = {isa = PBXBuildFile; fileRef = 24DE9E1011C5FE74003F90F6 /* ComAppceleratorUrlSessionModuleAssets.m */; }; - 3AE6391B1BDEAA4600A3796A /* SessionProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AE639191BDEAA4600A3796A /* SessionProxy.h */; }; - 3AE6391C1BDEAA4600A3796A /* SessionProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3AE6391A1BDEAA4600A3796A /* SessionProxy.m */; }; - 3AE6391F1BDEAA9100A3796A /* SessionConfigurationProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AE6391D1BDEAA9100A3796A /* SessionConfigurationProxy.h */; }; - 3AE639201BDEAA9100A3796A /* SessionConfigurationProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3AE6391E1BDEAA9100A3796A /* SessionConfigurationProxy.m */; }; AA747D9F0F9514B9006C5449 /* ComAppceleratorUrlSession_Prefix.pch in Headers */ = {isa = PBXBuildFile; fileRef = AA747D9E0F9514B9006C5449 /* ComAppceleratorUrlSession_Prefix.pch */; }; AACBBE4A0F95108600F1A2B1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AACBBE490F95108600F1A2B1 /* Foundation.framework */; }; + DB19DF7F1DC7D01500FEA769 /* ComAppceleratorUrlSessionSessionConfigurationProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = DB19DF7B1DC7D01500FEA769 /* ComAppceleratorUrlSessionSessionConfigurationProxy.h */; }; + DB19DF801DC7D01500FEA769 /* ComAppceleratorUrlSessionSessionConfigurationProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = DB19DF7C1DC7D01500FEA769 /* ComAppceleratorUrlSessionSessionConfigurationProxy.m */; }; + DB19DF811DC7D01500FEA769 /* ComAppceleratorUrlSessionSessionProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = DB19DF7D1DC7D01500FEA769 /* ComAppceleratorUrlSessionSessionProxy.h */; }; + DB19DF821DC7D01500FEA769 /* ComAppceleratorUrlSessionSessionProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = DB19DF7E1DC7D01500FEA769 /* ComAppceleratorUrlSessionSessionProxy.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -50,13 +50,13 @@ 24DD6D1B1134B66800162E58 /* titanium.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = titanium.xcconfig; sourceTree = ""; }; 24DE9E0F11C5FE74003F90F6 /* ComAppceleratorUrlSessionModuleAssets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ComAppceleratorUrlSessionModuleAssets.h; path = Classes/ComAppceleratorUrlSessionModuleAssets.h; sourceTree = ""; }; 24DE9E1011C5FE74003F90F6 /* ComAppceleratorUrlSessionModuleAssets.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ComAppceleratorUrlSessionModuleAssets.m; path = Classes/ComAppceleratorUrlSessionModuleAssets.m; sourceTree = ""; }; - 3AE639191BDEAA4600A3796A /* SessionProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SessionProxy.h; path = Classes/SessionProxy.h; sourceTree = ""; }; - 3AE6391A1BDEAA4600A3796A /* SessionProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SessionProxy.m; path = Classes/SessionProxy.m; sourceTree = ""; }; - 3AE6391D1BDEAA9100A3796A /* SessionConfigurationProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SessionConfigurationProxy.h; sourceTree = ""; }; - 3AE6391E1BDEAA9100A3796A /* SessionConfigurationProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SessionConfigurationProxy.m; sourceTree = ""; }; AA747D9E0F9514B9006C5449 /* ComAppceleratorUrlSession_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ComAppceleratorUrlSession_Prefix.pch; sourceTree = SOURCE_ROOT; }; AACBBE490F95108600F1A2B1 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; D2AAC07E0554694100DB518D /* libComAppceleratorUrlSession.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libComAppceleratorUrlSession.a; sourceTree = BUILT_PRODUCTS_DIR; }; + DB19DF7B1DC7D01500FEA769 /* ComAppceleratorUrlSessionSessionConfigurationProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ComAppceleratorUrlSessionSessionConfigurationProxy.h; path = Classes/ComAppceleratorUrlSessionSessionConfigurationProxy.h; sourceTree = ""; }; + DB19DF7C1DC7D01500FEA769 /* ComAppceleratorUrlSessionSessionConfigurationProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ComAppceleratorUrlSessionSessionConfigurationProxy.m; path = Classes/ComAppceleratorUrlSessionSessionConfigurationProxy.m; sourceTree = ""; }; + DB19DF7D1DC7D01500FEA769 /* ComAppceleratorUrlSessionSessionProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ComAppceleratorUrlSessionSessionProxy.h; path = Classes/ComAppceleratorUrlSessionSessionProxy.h; sourceTree = ""; }; + DB19DF7E1DC7D01500FEA769 /* ComAppceleratorUrlSessionSessionProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ComAppceleratorUrlSessionSessionProxy.m; path = Classes/ComAppceleratorUrlSessionSessionProxy.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -105,10 +105,10 @@ 24DE9E1011C5FE74003F90F6 /* ComAppceleratorUrlSessionModuleAssets.m */, 24DD6CF71134B3F500162E58 /* ComAppceleratorUrlSessionModule.h */, 24DD6CF81134B3F500162E58 /* ComAppceleratorUrlSessionModule.m */, - 3AE6391D1BDEAA9100A3796A /* SessionConfigurationProxy.h */, - 3AE6391E1BDEAA9100A3796A /* SessionConfigurationProxy.m */, - 3AE639191BDEAA4600A3796A /* SessionProxy.h */, - 3AE6391A1BDEAA4600A3796A /* SessionProxy.m */, + DB19DF7B1DC7D01500FEA769 /* ComAppceleratorUrlSessionSessionConfigurationProxy.h */, + DB19DF7C1DC7D01500FEA769 /* ComAppceleratorUrlSessionSessionConfigurationProxy.m */, + DB19DF7D1DC7D01500FEA769 /* ComAppceleratorUrlSessionSessionProxy.h */, + DB19DF7E1DC7D01500FEA769 /* ComAppceleratorUrlSessionSessionProxy.m */, ); name = Classes; sourceTree = ""; @@ -129,11 +129,11 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + DB19DF7F1DC7D01500FEA769 /* ComAppceleratorUrlSessionSessionConfigurationProxy.h in Headers */, AA747D9F0F9514B9006C5449 /* ComAppceleratorUrlSession_Prefix.pch in Headers */, - 3AE6391F1BDEAA9100A3796A /* SessionConfigurationProxy.h in Headers */, 24DD6CF91134B3F500162E58 /* ComAppceleratorUrlSessionModule.h in Headers */, - 3AE6391B1BDEAA4600A3796A /* SessionProxy.h in Headers */, 24DE9E1111C5FE74003F90F6 /* ComAppceleratorUrlSessionModuleAssets.h in Headers */, + DB19DF811DC7D01500FEA769 /* ComAppceleratorUrlSessionSessionProxy.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -207,9 +207,9 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 3AE639201BDEAA9100A3796A /* SessionConfigurationProxy.m in Sources */, + DB19DF821DC7D01500FEA769 /* ComAppceleratorUrlSessionSessionProxy.m in Sources */, 24DD6CFA1134B3F500162E58 /* ComAppceleratorUrlSessionModule.m in Sources */, - 3AE6391C1BDEAA4600A3796A /* SessionProxy.m in Sources */, + DB19DF801DC7D01500FEA769 /* ComAppceleratorUrlSessionSessionConfigurationProxy.m in Sources */, 24DE9E1211C5FE74003F90F6 /* ComAppceleratorUrlSessionModuleAssets.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/ios/titanium.xcconfig b/ios/titanium.xcconfig index 81e2d7a..491bf88 100644 --- a/ios/titanium.xcconfig +++ b/ios/titanium.xcconfig @@ -4,7 +4,7 @@ // OF YOUR TITANIUM SDK YOU'RE BUILDING FOR // // -TITANIUM_SDK_VERSION = 5.0.2.GA +TITANIUM_SDK_VERSION = 5.5.1.GA //