Remove unnecessary files
This commit is contained in:
parent
38194af6e3
commit
c3885c195a
24 changed files with 0 additions and 1869 deletions
Binary file not shown.
|
@ -28,11 +28,6 @@ android {
|
|||
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
maven {
|
||||
url "$buildDir/repo"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
//
|
||||
// RNBackgroundFetchManager.h
|
||||
// RNBackgroundFetch
|
||||
//
|
||||
// Created by Christopher Scott on 2016-08-02.
|
||||
// Copyright © 2016 Christopher Scott. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <BackgroundTasks/BackgroundTasks.h>
|
||||
|
||||
@interface TSBackgroundFetch : NSObject
|
||||
|
||||
@property (nonatomic) BOOL stopOnTerminate;
|
||||
@property (readonly) BOOL configured;
|
||||
@property (readonly) BOOL active;
|
||||
@property (readonly) NSString *fetchTaskId;
|
||||
|
||||
+ (TSBackgroundFetch *)sharedInstance;
|
||||
|
||||
-(void) didFinishLaunching;
|
||||
-(void) registerAppRefreshTask;
|
||||
-(void) registerBGProcessingTask:(NSString*)identifier;
|
||||
|
||||
-(void) configure:(NSTimeInterval)delay callback:(void(^)(UIBackgroundRefreshStatus status))callback;
|
||||
|
||||
-(NSError*) scheduleProcessingTaskWithIdentifier:(NSString*)identifier delay:(NSTimeInterval)delay periodic:(BOOL)periodic callback:(void (^)(NSString* taskId, BOOL timeout))callback;
|
||||
|
||||
-(NSError*) scheduleProcessingTaskWithIdentifier:(NSString*)identifier delay:(NSTimeInterval)delay periodic:(BOOL)periodic requiresExternalPower:(BOOL)requiresExternalPower requiresNetworkConnectivity:(BOOL)requiresNetworkConnectivity callback:(void (^)(NSString* taskId, BOOL timeout))callback;
|
||||
|
||||
-(void) addListener:(NSString*)componentName callback:(void (^)(NSString* componentName))callback;
|
||||
-(void) addListener:(NSString*)componentName callback:(void (^)(NSString* componentName))callback timeout:(void (^)(NSString* componentName))timeout;
|
||||
-(void) removeListener:(NSString*)componentName;
|
||||
-(BOOL) hasListener:(NSString*)componentName;
|
||||
|
||||
-(NSError*) start:(NSString*)identifier;
|
||||
-(void) stop:(NSString*)identifier;
|
||||
-(void) finish:(NSString*)tag;
|
||||
-(void) status:(void(^)(UIBackgroundRefreshStatus status))callback;
|
||||
|
||||
// @deprecated API
|
||||
-(void) performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))handler applicationState:(UIApplicationState)state;
|
||||
@end
|
||||
|
Binary file not shown.
|
@ -1,6 +0,0 @@
|
|||
framework module TSBackgroundFetch {
|
||||
umbrella header "TSBackgroundFetch.h"
|
||||
|
||||
export *
|
||||
module * { export * }
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,151 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>files</key>
|
||||
<dict>
|
||||
<key>Headers/TSBackgroundFetch.h</key>
|
||||
<data>
|
||||
6IaHDuPW1C0nWBp03yKGD5PrgTY=
|
||||
</data>
|
||||
<key>Info.plist</key>
|
||||
<data>
|
||||
/q6b6t8hcxgtnV2U/r/pxyTm1is=
|
||||
</data>
|
||||
<key>Modules/module.modulemap</key>
|
||||
<data>
|
||||
4NbofBeHHFHeUWRZ1ZcIkl3/T3w=
|
||||
</data>
|
||||
</dict>
|
||||
<key>files2</key>
|
||||
<dict>
|
||||
<key>Headers/TSBackgroundFetch.h</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
6IaHDuPW1C0nWBp03yKGD5PrgTY=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
Q6MbZjcbrHTACLwceQDEESRGhY9/uOOu7bCb71fOAfk=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Modules/module.modulemap</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
4NbofBeHHFHeUWRZ1ZcIkl3/T3w=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
ZZoRDGe9SOWekYXO71UHMmkagz+I18vRneUTVMd0WnY=
|
||||
</data>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>rules</key>
|
||||
<dict>
|
||||
<key>^</key>
|
||||
<true/>
|
||||
<key>^.*\.lproj/</key>
|
||||
<dict>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1000</real>
|
||||
</dict>
|
||||
<key>^.*\.lproj/locversion.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1100</real>
|
||||
</dict>
|
||||
<key>^Base\.lproj/</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>1010</real>
|
||||
</dict>
|
||||
<key>^version.plist$</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>rules2</key>
|
||||
<dict>
|
||||
<key>.*\.dSYM($|/)</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>11</real>
|
||||
</dict>
|
||||
<key>^</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^(.*/)?\.DS_Store$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>2000</real>
|
||||
</dict>
|
||||
<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>
|
||||
<dict>
|
||||
<key>nested</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>10</real>
|
||||
</dict>
|
||||
<key>^.*</key>
|
||||
<true/>
|
||||
<key>^.*\.lproj/</key>
|
||||
<dict>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1000</real>
|
||||
</dict>
|
||||
<key>^.*\.lproj/locversion.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1100</real>
|
||||
</dict>
|
||||
<key>^Base\.lproj/</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>1010</real>
|
||||
</dict>
|
||||
<key>^Info\.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^PkgInfo$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^[^/]+$</key>
|
||||
<dict>
|
||||
<key>nested</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>10</real>
|
||||
</dict>
|
||||
<key>^embedded\.provisionprofile$</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^version\.plist$</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
Binary file not shown.
File diff suppressed because one or more lines are too long
|
@ -1,7 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:TSBackgroundFetch.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
|
@ -1,8 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
|
@ -1,8 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>BuildSystemType</key>
|
||||
<string>Latest</string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -1,26 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string></string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -1,39 +0,0 @@
|
|||
//
|
||||
// TSBGAppRefreshSubscriber.h
|
||||
// TSBackgroundFetch
|
||||
//
|
||||
// Created by Christopher Scott on 2020-02-07.
|
||||
// Copyright © 2020 Christopher Scott. All rights reserved.
|
||||
//
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <BackgroundTasks/BackgroundTasks.h>
|
||||
|
||||
@interface TSBGAppRefreshSubscriber : NSObject
|
||||
|
||||
+(void)load;
|
||||
+(NSMutableDictionary *)subscribers;
|
||||
+(void) add:(TSBGAppRefreshSubscriber*)tsTask;
|
||||
+(void) remove:(TSBGAppRefreshSubscriber*)tsTask;
|
||||
+(TSBGAppRefreshSubscriber*) get:(NSString*)identifier;
|
||||
+(void) execute;
|
||||
+(BOOL) onTimeout;
|
||||
|
||||
+(void)registerTaskScheduler API_AVAILABLE(ios(13));
|
||||
+(BOOL)useTaskScheduler;
|
||||
|
||||
@property (nonatomic) NSString* identifier;
|
||||
@property (copy) void (^callback) (NSString*);
|
||||
@property (copy) void (^timeout) (NSString*);
|
||||
@property (nonatomic, readonly) BOOL enabled;
|
||||
@property (nonatomic, readonly) BOOL executed;
|
||||
@property (nonatomic, readonly) BOOL finished;
|
||||
|
||||
-(instancetype) initWithIdentifier:(NSString*)identifier callback:(void (^)(NSString* taskId))callback timeout:(void (^)(NSString* taskId))timeout;
|
||||
-(void) execute;
|
||||
-(void) onTimeout;
|
||||
-(void) finish;
|
||||
-(void) destroy;
|
||||
|
||||
@end
|
||||
|
|
@ -1,188 +0,0 @@
|
|||
//
|
||||
// TSBGAppRefreshSubscriber.m
|
||||
// TSBackgroundFetch
|
||||
//
|
||||
// Created by Christopher Scott on 2020-02-07.
|
||||
// Copyright © 2020 Christopher Scott. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "TSBGAppRefreshSubscriber.h"
|
||||
#import "TSBackgroundFetch.h"
|
||||
|
||||
static NSString *const TAG = @"TSBGAppRefreshSubscriber";
|
||||
|
||||
static NSMutableDictionary *_subscribers;
|
||||
static BOOL _hasRegisteredTaskScheduler = NO;
|
||||
|
||||
@implementation TSBGAppRefreshSubscriber {
|
||||
|
||||
}
|
||||
|
||||
+(void)load {
|
||||
[[self class] subscribers];
|
||||
}
|
||||
|
||||
+ (NSMutableDictionary*)subscribers
|
||||
{
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
_subscribers = [NSMutableDictionary new];
|
||||
// Load the set of taskIds, eg: ["foo, "bar"]
|
||||
NSArray *subscribers = [defaults objectForKey:TAG];
|
||||
// Foreach taskId, load TSBGTask config from NSDefaults, eg: "TSBackgroundFetch:foo"
|
||||
for (NSString *identifier in subscribers) {
|
||||
TSBGAppRefreshSubscriber *subscriber = [[TSBGAppRefreshSubscriber alloc] initWithIdentifier:identifier];
|
||||
[_subscribers setObject:subscriber forKey:identifier];
|
||||
}
|
||||
NSLog(@"[%@ load]: %@", TAG, _subscribers);
|
||||
});
|
||||
return _subscribers;
|
||||
}
|
||||
|
||||
+ (TSBGAppRefreshSubscriber*) get:(NSString*)identifier {
|
||||
@synchronized (_subscribers) {
|
||||
return [_subscribers objectForKey:identifier];
|
||||
}
|
||||
}
|
||||
|
||||
+ (void) add:(TSBGAppRefreshSubscriber*)subscriber {
|
||||
@synchronized (_subscribers) {
|
||||
[_subscribers setObject:subscriber forKey:subscriber.identifier];
|
||||
}
|
||||
}
|
||||
|
||||
+ (void) remove:(TSBGAppRefreshSubscriber*)subscriber {
|
||||
@synchronized (_subscribers) {
|
||||
[_subscribers removeObjectForKey:subscriber.identifier];
|
||||
}
|
||||
}
|
||||
|
||||
+(void)registerTaskScheduler{
|
||||
_hasRegisteredTaskScheduler = YES;
|
||||
}
|
||||
|
||||
+(BOOL)useTaskScheduler {
|
||||
return _hasRegisteredTaskScheduler;
|
||||
}
|
||||
|
||||
+(void) execute {
|
||||
NSArray *subscribers = [[self subscribers] allValues];
|
||||
for (TSBGAppRefreshSubscriber *subscriber in subscribers) {
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
[subscriber execute];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+(BOOL) onTimeout {
|
||||
BOOL foundTimeoutHandler = NO;
|
||||
NSArray *subscribers = [[self subscribers] allValues];
|
||||
for (TSBGAppRefreshSubscriber *subscriber in subscribers) {
|
||||
foundTimeoutHandler = YES;
|
||||
if (subscriber.timeout) {
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
[subscriber onTimeout];
|
||||
});
|
||||
} else {
|
||||
[[TSBackgroundFetch sharedInstance] finish:subscriber.identifier];
|
||||
}
|
||||
}
|
||||
return foundTimeoutHandler;
|
||||
}
|
||||
|
||||
|
||||
-(instancetype)init {
|
||||
self = [super init];
|
||||
_enabled = YES;
|
||||
_finished = NO;
|
||||
_executed = NO;
|
||||
return self;
|
||||
}
|
||||
|
||||
-(instancetype) initWithIdentifier:(NSString*)identifier {
|
||||
self = [self init];
|
||||
if (self) {
|
||||
_identifier = identifier;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(instancetype) initWithIdentifier:(NSString*)identifier callback:(void (^)(NSString* taskId))callback timeout:(void (^)(NSString* taskId))timeout {
|
||||
self = [self init];
|
||||
if (self) {
|
||||
_identifier = identifier;
|
||||
_callback = callback;
|
||||
_timeout = timeout;
|
||||
[self save];
|
||||
@synchronized (_subscribers) {
|
||||
[_subscribers setObject:self forKey:identifier];
|
||||
}
|
||||
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void) execute {
|
||||
if (_executed || !_callback) return;
|
||||
|
||||
_executed = YES;
|
||||
_finished = NO;
|
||||
dispatch_async(dispatch_get_main_queue(), ^(void) {
|
||||
self.callback(self.identifier);
|
||||
});
|
||||
}
|
||||
|
||||
-(void) onTimeout {
|
||||
if (!_timeout) {
|
||||
[self finish];
|
||||
return;
|
||||
}
|
||||
if (!_finished) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^(void) {
|
||||
self.timeout(self.identifier);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
-(void) finish {
|
||||
_finished = YES;
|
||||
_executed = NO;
|
||||
}
|
||||
|
||||
-(void) destroy {
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
NSMutableArray *subscribers = [[defaults objectForKey:TAG] mutableCopy];
|
||||
|
||||
[TSBGAppRefreshSubscriber remove:self];
|
||||
|
||||
if (!subscribers) {
|
||||
subscribers = [NSMutableArray new];
|
||||
}
|
||||
if ([subscribers containsObject:_identifier]) {
|
||||
[subscribers removeObject:_identifier];
|
||||
[defaults setObject:subscribers forKey:TAG];
|
||||
}
|
||||
}
|
||||
-(void) save {
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
|
||||
NSMutableArray *subscribers = [[defaults objectForKey:TAG] mutableCopy];
|
||||
if (!subscribers) {
|
||||
subscribers = [NSMutableArray new];
|
||||
}
|
||||
|
||||
if ([subscribers containsObject:_identifier]) {
|
||||
return;
|
||||
}
|
||||
|
||||
[subscribers addObject:_identifier];
|
||||
[defaults setObject:subscribers forKey:TAG];
|
||||
}
|
||||
|
||||
-(NSString*) description {
|
||||
return [NSString stringWithFormat:@"<%@ identifier=%@, executed=%d, enabled=%d>", TAG, _identifier, _executed, _enabled];
|
||||
}
|
||||
@end
|
|
@ -1,52 +0,0 @@
|
|||
//
|
||||
// TSBGTask.h
|
||||
// TSBackgroundFetch
|
||||
//
|
||||
// Created by Christopher Scott on 2020-01-23.
|
||||
// Copyright © 2020 Christopher Scott. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <BackgroundTasks/BackgroundTasks.h>
|
||||
|
||||
@interface TSBGTask : NSObject
|
||||
|
||||
@property (nonatomic) BGTask* task API_AVAILABLE(ios(13.0));
|
||||
|
||||
@property (nonatomic) NSString* identifier;
|
||||
@property (copy) void (^callback)(NSString*, BOOL);
|
||||
@property (nonatomic) NSTimeInterval delay;
|
||||
@property (nonatomic, readonly) BOOL executed;
|
||||
@property (nonatomic) BOOL periodic;
|
||||
@property (nonatomic) BOOL enabled;
|
||||
@property (nonatomic, readonly) BOOL finished;
|
||||
@property (nonatomic) BOOL stopOnTerminate;
|
||||
@property (nonatomic) BOOL requiresExternalPower;
|
||||
@property (nonatomic) BOOL requiresNetworkConnectivity;
|
||||
|
||||
+(void)load;
|
||||
+(NSMutableArray *)tasks;
|
||||
+(void) add:(TSBGTask*)tsTask;
|
||||
+(void) remove:(TSBGTask*)tsTask;
|
||||
+(TSBGTask*) get:(NSString*)identifier;
|
||||
|
||||
+(void)registerForTaskWithIdentifier:(NSString*)identifier;
|
||||
+(BOOL)useProcessingTaskScheduler;
|
||||
|
||||
-(instancetype) initWithIdentifier:(NSString*)identifier delay:(NSTimeInterval)delay periodic:(BOOL)periodic callback:(void (^)(NSString* taskId, BOOL timeout))callback;
|
||||
-(instancetype) initWithIdentifier:(NSString*)identifier delay:(NSTimeInterval)delay periodic:(BOOL)periodic requiresExternalPower:(BOOL)requiresExternalPower requiresNetworkConnectivity:(BOOL)requiresNetworkConnectivity callback:(void (^)(NSString* taskId, BOOL timeout))callback;
|
||||
|
||||
-(instancetype) initWithDictionary:(NSDictionary*)config;
|
||||
|
||||
-(BOOL) execute;
|
||||
-(void) finish:(BOOL)success;
|
||||
|
||||
-(NSError*) schedule;
|
||||
-(void) stop;
|
||||
-(void) setTask:(BGProcessingTask*)task API_AVAILABLE(ios(13));
|
||||
-(void) destroy;
|
||||
-(void) save;
|
||||
|
||||
@end
|
||||
|
|
@ -1,297 +0,0 @@
|
|||
//
|
||||
// TSBGTask.m
|
||||
// TSBackgroundFetch
|
||||
//
|
||||
// Created by Christopher Scott on 2020-01-23.
|
||||
// Copyright © 2020 Christopher Scott. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "TSBGTask.h"
|
||||
|
||||
static NSString *const TAG = @"TSBackgroundFetch";
|
||||
static NSString *const TASKS_STORAGE_KEY = @"TSBackgroundFetch:tasks";
|
||||
|
||||
static BOOL _hasRegisteredProcessingTaskScheduler = NO;
|
||||
|
||||
static NSString *const ERROR_PROCESSING_TASK_NOT_REGISTERED = @"Background procssing task was not registered in AppDelegate didFinishLaunchingWithOptions. See iOS Setup Guide.";
|
||||
static NSString *const ERROR_PROCESSING_TASK_NOT_AVAILABLE = @"Background procssing tasks are only available with iOS 13+";
|
||||
|
||||
static NSMutableArray *_tasks;
|
||||
|
||||
@implementation TSBGTask {
|
||||
BOOL scheduled;
|
||||
}
|
||||
|
||||
#pragma mark Class Methods
|
||||
|
||||
+(void)registerForTaskWithIdentifier:(NSString*)identifier API_AVAILABLE(ios(13)) {
|
||||
_hasRegisteredProcessingTaskScheduler = YES;
|
||||
|
||||
NSLog(@"[%@ registerForTaskWithIdentifier: %@", TAG, identifier);
|
||||
|
||||
[[BGTaskScheduler sharedScheduler] registerForTaskWithIdentifier:identifier usingQueue:nil launchHandler:^(BGTask* task) {
|
||||
TSBGTask *tsTask = [self get:task.identifier];
|
||||
if (!tsTask) {
|
||||
NSLog(@"[%@ registerForTaskWithIdentifier launchHandler] ERROR: Failed to find TSBGTask in Fetch event: %@", TAG, task.identifier);
|
||||
[task setTaskCompletedWithSuccess:NO];
|
||||
return;
|
||||
}
|
||||
[tsTask setTask:(BGProcessingTask*)task];
|
||||
}];
|
||||
}
|
||||
|
||||
+(BOOL)useProcessingTaskScheduler {
|
||||
return _hasRegisteredProcessingTaskScheduler;
|
||||
}
|
||||
|
||||
+(void)load {
|
||||
[[self class] tasks];
|
||||
}
|
||||
|
||||
+ (NSMutableArray*)tasks
|
||||
{
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
_tasks = [NSMutableArray new];
|
||||
// Load the set of taskIds, eg: ["foo, "bar"]
|
||||
NSArray *taskIds = [defaults objectForKey:TASKS_STORAGE_KEY];
|
||||
// Foreach taskId, load TSBGTask config from NSDefaults, eg: "TSBackgroundFetch:foo"
|
||||
for (NSString *taskId in taskIds) {
|
||||
NSString *key = [NSString stringWithFormat:@"%@:%@", TAG, taskId];
|
||||
NSDictionary *config = [defaults objectForKey:key];
|
||||
TSBGTask *tsTask = [[TSBGTask alloc] initWithDictionary:config];
|
||||
[_tasks addObject:tsTask];
|
||||
}
|
||||
NSLog(@"[%@ load]: %@", TAG, _tasks);
|
||||
});
|
||||
@synchronized (_tasks) {
|
||||
return [_tasks copy];
|
||||
}
|
||||
}
|
||||
|
||||
+ (TSBGTask*) get:(NSString*)identifier {
|
||||
@synchronized (_tasks) {
|
||||
for (TSBGTask *tsTask in _tasks) {
|
||||
if ([tsTask.identifier isEqualToString:identifier]) {
|
||||
return tsTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (void) add:(TSBGTask*)tsTask {
|
||||
@synchronized (_tasks) {
|
||||
[_tasks addObject:tsTask];
|
||||
}
|
||||
}
|
||||
|
||||
+ (void) remove:(TSBGTask*)tsTask {
|
||||
@synchronized (_tasks) {
|
||||
[_tasks removeObject:tsTask];
|
||||
}
|
||||
}
|
||||
|
||||
# pragma mark Instance Methods
|
||||
|
||||
-(instancetype)init {
|
||||
self = [super init];
|
||||
scheduled = NO;
|
||||
|
||||
_enabled = NO;
|
||||
_executed = NO;
|
||||
_finished = NO;
|
||||
_requiresNetworkConnectivity = NO;
|
||||
_requiresExternalPower = NO;
|
||||
return self;
|
||||
}
|
||||
|
||||
/// @deprecated
|
||||
-(instancetype) initWithIdentifier:(NSString*)identifier delay:(NSTimeInterval)delay periodic:(BOOL)periodic callback:(void (^)(NSString* taskId, BOOL timeout))callback {
|
||||
return [self initWithIdentifier:identifier delay:delay periodic:periodic requiresExternalPower:NO requiresNetworkConnectivity:NO callback:callback];
|
||||
}
|
||||
|
||||
-(instancetype) initWithIdentifier:(NSString*)identifier delay:(NSTimeInterval)delay periodic:(BOOL)periodic requiresExternalPower:(BOOL)requiresExternalPower requiresNetworkConnectivity:(BOOL)requiresNetworkConnectivity callback:(void (^)(NSString* taskId, BOOL timeout))callback {
|
||||
|
||||
self = [self init];
|
||||
|
||||
if (self) {
|
||||
_identifier = identifier;
|
||||
_delay = delay;
|
||||
_periodic = periodic;
|
||||
_requiresExternalPower = requiresExternalPower;
|
||||
_requiresNetworkConnectivity = requiresNetworkConnectivity;
|
||||
[TSBGTask add:self];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(instancetype) initWithDictionary:(NSDictionary*)config {
|
||||
self = [self init];
|
||||
if (self) {
|
||||
_identifier = [config objectForKey:@"identifier"];
|
||||
_delay = [[config objectForKey:@"delay"] longValue];
|
||||
_periodic = [[config objectForKey:@"periodic"] boolValue];
|
||||
_enabled = [[config objectForKey:@"enabled"] boolValue];
|
||||
if ([config objectForKey:@"requiresExternalPower"]) {
|
||||
_requiresExternalPower = [[config objectForKey:@"requiresExternalPower"] boolValue];
|
||||
}
|
||||
if ([config objectForKey:@"requiresNetworkConnectivity"]) {
|
||||
_requiresNetworkConnectivity = [[config objectForKey:@"requiresNetworkConnectivity"] boolValue];
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSError*) schedule {
|
||||
if (@available (iOS 13.0, *)) {
|
||||
if (![TSBGTask useProcessingTaskScheduler]) {
|
||||
return [[NSError alloc] initWithDomain:TAG code:0 userInfo:@{NSLocalizedFailureReasonErrorKey:ERROR_PROCESSING_TASK_NOT_REGISTERED}];
|
||||
}
|
||||
|
||||
NSLog(@"[%@ scheduleProcessingTask] %@", TAG, self);
|
||||
|
||||
BGTaskScheduler *scheduler = [BGTaskScheduler sharedScheduler];
|
||||
|
||||
if (scheduled) {
|
||||
[[BGTaskScheduler sharedScheduler] cancelTaskRequestWithIdentifier:_identifier];
|
||||
}
|
||||
|
||||
BGProcessingTaskRequest *request = [[BGProcessingTaskRequest alloc] initWithIdentifier:_identifier];
|
||||
// TODO Configurable.
|
||||
request.requiresExternalPower = _requiresExternalPower;
|
||||
request.requiresNetworkConnectivity = _requiresNetworkConnectivity;
|
||||
request.earliestBeginDate = [NSDate dateWithTimeIntervalSinceNow:_delay];
|
||||
|
||||
NSError *error = nil;
|
||||
[scheduler submitTaskRequest:request error:&error];
|
||||
if (!error) {
|
||||
scheduled = YES;
|
||||
if (!_enabled) {
|
||||
_enabled = YES;
|
||||
[self save];
|
||||
}
|
||||
}
|
||||
return error;
|
||||
} else {
|
||||
return [[NSError alloc] initWithDomain:TAG code:-1 userInfo:@{NSLocalizedFailureReasonErrorKey:ERROR_PROCESSING_TASK_NOT_AVAILABLE}];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) stop {
|
||||
_enabled = NO;
|
||||
scheduled = NO;
|
||||
|
||||
[self destroy];
|
||||
|
||||
if (@available(iOS 13.0, *)) {
|
||||
[[BGTaskScheduler sharedScheduler] cancelTaskRequestWithIdentifier:_identifier];
|
||||
}
|
||||
}
|
||||
|
||||
-(void) setTask:(BGProcessingTask*)task {
|
||||
scheduled = NO;
|
||||
|
||||
_task = task;
|
||||
|
||||
task.expirationHandler = ^{
|
||||
NSLog(@"[%@ expirationHandler] WARNING: %@ '%@' expired before #finish was executed.", TAG, NSStringFromClass([self.task class]), self.identifier);
|
||||
[self onTimeout];
|
||||
// TODO Disabled with onTimeout implementation.
|
||||
//[self finish:NO];
|
||||
};
|
||||
|
||||
// If no callback registered for TSTask, the app was launched in background. The event will be handled once task is scheduled.
|
||||
if (_callback) {
|
||||
[self execute];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL) execute {
|
||||
if (@available(iOS 13.0, *)) {
|
||||
if ([TSBGTask useProcessingTaskScheduler] && _periodic && !scheduled) {
|
||||
[self schedule];
|
||||
}
|
||||
}
|
||||
_finished = NO;
|
||||
if (_callback) {
|
||||
_callback(_identifier, NO);
|
||||
_executed = YES;
|
||||
return YES;
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL) onTimeout {
|
||||
if (_callback) {
|
||||
_callback(_identifier, YES);
|
||||
return YES;
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
-(void) finish:(BOOL)success {
|
||||
[_task setTaskCompletedWithSuccess:success];
|
||||
_finished = YES;
|
||||
_executed = NO;
|
||||
_task = nil;
|
||||
if (!_periodic) {
|
||||
[self destroy];
|
||||
}
|
||||
}
|
||||
|
||||
-(void) save {
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
NSMutableArray *taskIds = [[defaults objectForKey:TASKS_STORAGE_KEY] mutableCopy];
|
||||
if (!taskIds) {
|
||||
taskIds = [NSMutableArray new];
|
||||
}
|
||||
if (![taskIds containsObject:_identifier]) {
|
||||
[taskIds addObject:_identifier];
|
||||
[defaults setObject:taskIds forKey:TASKS_STORAGE_KEY];
|
||||
}
|
||||
NSString *key = [NSString stringWithFormat:@"%@:%@", TAG, _identifier];
|
||||
NSLog(@"[TSBGTask save]: %@", self);
|
||||
[defaults setObject:[self toDictionary] forKey:key];
|
||||
}
|
||||
|
||||
-(void) destroy {
|
||||
[TSBGTask remove:self];
|
||||
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
NSMutableArray *taskIds = [[defaults objectForKey:TASKS_STORAGE_KEY] mutableCopy];
|
||||
if (!taskIds) {
|
||||
taskIds = [NSMutableArray new];
|
||||
}
|
||||
if ([taskIds containsObject:_identifier]) {
|
||||
[taskIds removeObject:_identifier];
|
||||
[defaults setObject:taskIds forKey:TASKS_STORAGE_KEY];
|
||||
}
|
||||
NSString *key = [NSString stringWithFormat:@"%@:%@", TAG, _identifier];
|
||||
if ([defaults objectForKey:key]) {
|
||||
[defaults removeObjectForKey:key];
|
||||
}
|
||||
NSLog(@"[TSBGTask destroy] %@", _identifier);
|
||||
}
|
||||
|
||||
-(NSDictionary*) toDictionary {
|
||||
return @{
|
||||
@"identifier": _identifier,
|
||||
@"delay": @(_delay),
|
||||
@"periodic": @(_periodic),
|
||||
@"enabled": @(_enabled),
|
||||
@"requiresExternalPower": @(_requiresExternalPower),
|
||||
@"requiresNetworkConnectivity": @(_requiresNetworkConnectivity)
|
||||
};
|
||||
}
|
||||
|
||||
-(NSString*) description {
|
||||
return [NSString stringWithFormat:@"<TSBGTask identifier=%@, delay=%ld, periodic=%d requiresNetworkConnectivity=%d requiresExternalPower=%d, enabled=%d>", _identifier, (long)_delay, _periodic, _requiresNetworkConnectivity, _requiresExternalPower, _enabled];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,47 +0,0 @@
|
|||
//
|
||||
// RNBackgroundFetchManager.h
|
||||
// RNBackgroundFetch
|
||||
//
|
||||
// Created by Christopher Scott on 2016-08-02.
|
||||
// Copyright © 2016 Christopher Scott. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <BackgroundTasks/BackgroundTasks.h>
|
||||
|
||||
@interface TSBackgroundFetch : NSObject
|
||||
|
||||
@property (nonatomic) BOOL stopOnTerminate;
|
||||
@property (readonly) BOOL configured;
|
||||
@property (readonly) BOOL active;
|
||||
@property (readonly) NSString *fetchTaskId;
|
||||
@property (copy) void (^completionHandler)(UIBackgroundFetchResult);
|
||||
@property (nonatomic) UIBackgroundTaskIdentifier backgroundTask;
|
||||
|
||||
+ (TSBackgroundFetch *)sharedInstance;
|
||||
|
||||
-(void) didFinishLaunching;
|
||||
-(void) registerAppRefreshTask;
|
||||
-(void) registerBGProcessingTask:(NSString*)identifier;
|
||||
|
||||
-(void) configure:(NSTimeInterval)delay callback:(void(^)(UIBackgroundRefreshStatus status))callback;
|
||||
|
||||
-(NSError*) scheduleProcessingTaskWithIdentifier:(NSString*)identifier delay:(NSTimeInterval)delay periodic:(BOOL)periodic callback:(void (^)(NSString* taskId, BOOL timeout))callback;
|
||||
|
||||
-(NSError*) scheduleProcessingTaskWithIdentifier:(NSString*)identifier delay:(NSTimeInterval)delay periodic:(BOOL)periodic requiresExternalPower:(BOOL)requiresExternalPower requiresNetworkConnectivity:(BOOL)requiresNetworkConnectivity callback:(void (^)(NSString* taskId, BOOL timeout))callback;
|
||||
|
||||
-(void) addListener:(NSString*)componentName callback:(void (^)(NSString* componentName))callback;
|
||||
-(void) addListener:(NSString*)componentName callback:(void (^)(NSString* componentName))callback timeout:(void (^)(NSString* componentName))timeout;
|
||||
-(void) removeListener:(NSString*)componentName;
|
||||
-(BOOL) hasListener:(NSString*)componentName;
|
||||
|
||||
-(NSError*) start:(NSString*)identifier;
|
||||
-(void) stop:(NSString*)identifier;
|
||||
-(void) finish:(NSString*)tag;
|
||||
-(void) status:(void(^)(UIBackgroundRefreshStatus status))callback;
|
||||
|
||||
// @deprecated API
|
||||
-(void) performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))handler applicationState:(UIApplicationState)state;
|
||||
@end
|
||||
|
|
@ -1,365 +0,0 @@
|
|||
//
|
||||
// RNBackgroundFetchManager.m
|
||||
// RNBackgroundFetch
|
||||
//
|
||||
// Created by Christopher Scott on 2016-08-02.
|
||||
// Copyright © 2016 Christopher Scott. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TSBackgroundFetch.h"
|
||||
#import "TSBGTask.h"
|
||||
#import "TSBGAppRefreshSubscriber.h"
|
||||
|
||||
static NSString *const TAG = @"TSBackgroundFetch";
|
||||
|
||||
static NSString *const BACKGROUND_REFRESH_TASK_ID = @"com.transistorsoft.fetch";
|
||||
static NSString *const PERMITTED_IDENTIFIERS_KEY = @"BGTaskSchedulerPermittedIdentifiers";
|
||||
|
||||
@implementation TSBackgroundFetch {
|
||||
BOOL enabled;
|
||||
|
||||
NSTimeInterval minimumFetchInterval;
|
||||
id bgAppRefreshTask;
|
||||
BOOL fetchScheduled;
|
||||
}
|
||||
|
||||
+ (TSBackgroundFetch *)sharedInstance
|
||||
{
|
||||
static TSBackgroundFetch *instance = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
[TSBGTask load];
|
||||
[TSBGAppRefreshSubscriber load];
|
||||
instance = [[self alloc] init];
|
||||
});
|
||||
return instance;
|
||||
}
|
||||
|
||||
-(instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
fetchScheduled = NO;
|
||||
minimumFetchInterval = UIApplicationBackgroundFetchIntervalMinimum;
|
||||
|
||||
_fetchTaskId = BACKGROUND_REFRESH_TASK_ID;
|
||||
_stopOnTerminate = YES;
|
||||
_configured = NO;
|
||||
_active = NO;
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppTerminate) name:UIApplicationWillTerminateNotification object:nil];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) didFinishLaunching {
|
||||
NSArray *permittedIdentifiers = [[NSBundle mainBundle] objectForInfoDictionaryKey:PERMITTED_IDENTIFIERS_KEY];
|
||||
if (!permittedIdentifiers) return;
|
||||
|
||||
for (NSString *identifier in permittedIdentifiers) {
|
||||
if ([identifier isEqualToString:BACKGROUND_REFRESH_TASK_ID]) {
|
||||
[self registerAppRefreshTask];
|
||||
} else {
|
||||
[self registerBGProcessingTask:identifier];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void) registerAppRefreshTask {
|
||||
if (@available(iOS 13.0, *)) {
|
||||
[TSBGAppRefreshSubscriber registerTaskScheduler];
|
||||
|
||||
[[BGTaskScheduler sharedScheduler] registerForTaskWithIdentifier:BACKGROUND_REFRESH_TASK_ID usingQueue:nil launchHandler:^(BGTask* task) {
|
||||
[self handleBGAppRefreshTask:(BGAppRefreshTask*)task];
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) registerBGProcessingTask:(NSString *)identifier {
|
||||
if (@available(iOS 13.0, *)) {
|
||||
[TSBGTask registerForTaskWithIdentifier:identifier];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSError*) scheduleBGAppRefresh {
|
||||
if (fetchScheduled) return nil;
|
||||
|
||||
NSLog(@"[%@ scheduleBGAppRefresh] %@", TAG, BACKGROUND_REFRESH_TASK_ID);
|
||||
|
||||
NSError *error = nil;
|
||||
|
||||
if (@available (iOS 13.0, *)) {
|
||||
if ([TSBGAppRefreshSubscriber useTaskScheduler]) {
|
||||
BGTaskScheduler *scheduler = [BGTaskScheduler sharedScheduler];
|
||||
BGAppRefreshTaskRequest *request = [[BGAppRefreshTaskRequest alloc] initWithIdentifier:BACKGROUND_REFRESH_TASK_ID];
|
||||
request.earliestBeginDate = [NSDate dateWithTimeIntervalSinceNow:minimumFetchInterval];
|
||||
|
||||
[scheduler submitTaskRequest:request error:&error];
|
||||
// Handle case for Simulator where BGTaskScheduler doesn't work.
|
||||
if ((error != nil) && (error.code == BGTaskSchedulerErrorCodeUnavailable)) {
|
||||
NSLog(@"[%@] BGTaskScheduler failed to register fetch-task and will fall-back to old API. This is likely due to running in the iOS Simulator (%@)", TAG, error);
|
||||
[self setMinimumFetchInterval];
|
||||
error = nil;
|
||||
}
|
||||
} else {
|
||||
[self setMinimumFetchInterval];
|
||||
}
|
||||
} else {
|
||||
[self setMinimumFetchInterval];
|
||||
}
|
||||
if (!error) {
|
||||
fetchScheduled = YES;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
-(void) cancelBGAppRefresh {
|
||||
if (@available (iOS 13.0, *)) {
|
||||
BGTaskScheduler *scheduler = [BGTaskScheduler sharedScheduler];
|
||||
[scheduler cancelTaskRequestWithIdentifier:BACKGROUND_REFRESH_TASK_ID];
|
||||
fetchScheduled = NO;
|
||||
} else {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalNever];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
-(void) setMinimumFetchInterval {
|
||||
__block NSTimeInterval interval = minimumFetchInterval;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:interval];
|
||||
});
|
||||
}
|
||||
|
||||
/// Callback from BGTaskScheduler
|
||||
-(void) handleBGAppRefreshTask:(BGAppRefreshTask*)task API_AVAILABLE(ios(13.0)) {
|
||||
NSLog(@"[%@ handleBGAppRefreshTask]", TAG);
|
||||
|
||||
__block BGAppRefreshTask *weakTask = task;
|
||||
task.expirationHandler = ^{
|
||||
NSLog(@"[%@ handleBGAppRefreshTask] WARNING: expired before #finish was executed.", TAG);
|
||||
// If any registered listeners has registered an onTimeout callback, let them run and execute #finish as desired. Otherwise, automatically setTaskCompleted immediately.
|
||||
if (![TSBGAppRefreshSubscriber onTimeout] && weakTask) [weakTask setTaskCompletedWithSuccess:NO];
|
||||
};
|
||||
|
||||
fetchScheduled = NO;
|
||||
[self scheduleBGAppRefresh];
|
||||
|
||||
bgAppRefreshTask = task;
|
||||
[TSBGAppRefreshSubscriber execute];
|
||||
}
|
||||
|
||||
/// @deprecated Old-syle fetch callback.
|
||||
- (void) performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))handler applicationState:(UIApplicationState)state {
|
||||
NSLog(@"[%@ performFetchWithCompletionHandler]", TAG);
|
||||
|
||||
fetchScheduled = NO;
|
||||
[self scheduleBGAppRefresh];
|
||||
|
||||
_completionHandler = handler;
|
||||
if (_backgroundTask != UIBackgroundTaskInvalid) [[UIApplication sharedApplication] endBackgroundTask:_backgroundTask];
|
||||
// Create a UIBackgroundTask for detecting task-expiration with old API.
|
||||
_backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
|
||||
if (self.completionHandler) {
|
||||
[TSBGAppRefreshSubscriber onTimeout];
|
||||
}
|
||||
@synchronized (self) {
|
||||
[[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
|
||||
self.backgroundTask = UIBackgroundTaskInvalid;
|
||||
}
|
||||
}];
|
||||
|
||||
[TSBGAppRefreshSubscriber execute];
|
||||
}
|
||||
|
||||
-(void) status:(void(^)(UIBackgroundRefreshStatus status))callback
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
callback([[UIApplication sharedApplication] backgroundRefreshStatus]);
|
||||
});
|
||||
}
|
||||
|
||||
-(void) configure:(NSTimeInterval)delay callback:(void(^)(UIBackgroundRefreshStatus status))callback {
|
||||
_configured = YES;
|
||||
minimumFetchInterval = delay;
|
||||
[self status:^(UIBackgroundRefreshStatus status) {
|
||||
if (status == UIBackgroundRefreshStatusAvailable) {
|
||||
[self scheduleBGAppRefresh];
|
||||
}
|
||||
callback(status);
|
||||
}];
|
||||
}
|
||||
|
||||
-(NSError*) scheduleProcessingTaskWithIdentifier:(NSString*)identifier delay:(NSTimeInterval)delay periodic:(BOOL)periodic callback:(void (^)(NSString* taskId, BOOL timeout))callback {
|
||||
return [self scheduleProcessingTaskWithIdentifier:identifier delay:delay periodic:periodic requiresExternalPower:NO requiresNetworkConnectivity:NO callback:callback];
|
||||
}
|
||||
|
||||
-(NSError*) scheduleProcessingTaskWithIdentifier:(NSString*)identifier delay:(NSTimeInterval)delay periodic:(BOOL)periodic requiresExternalPower:(BOOL)requiresExternalPower requiresNetworkConnectivity:(BOOL)requiresNetworkConnectivity callback:(void (^)(NSString* taskId, BOOL timeout))callback {
|
||||
|
||||
TSBGTask *tsTask = [TSBGTask get:identifier];
|
||||
if (tsTask) {
|
||||
tsTask.delay = delay;
|
||||
tsTask.periodic = periodic;
|
||||
tsTask.callback = callback;
|
||||
tsTask.requiresNetworkConnectivity = requiresNetworkConnectivity;
|
||||
tsTask.requiresExternalPower = requiresExternalPower;
|
||||
if (@available(iOS 13.0, *)) {
|
||||
if (tsTask.task && !tsTask.executed) {
|
||||
[tsTask execute];
|
||||
return nil;
|
||||
} else {
|
||||
return [tsTask schedule];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tsTask = [[TSBGTask alloc] initWithIdentifier:identifier
|
||||
delay:delay
|
||||
periodic:periodic
|
||||
requiresExternalPower:requiresExternalPower
|
||||
requiresNetworkConnectivity:requiresNetworkConnectivity
|
||||
callback:callback];
|
||||
tsTask.callback = callback;
|
||||
}
|
||||
|
||||
NSError *error = [tsTask schedule];
|
||||
if (error) {
|
||||
NSLog(@"[%@ scheduleTask] ERROR: Failed to submit task request: %@", TAG, error);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
/// @deprecated.
|
||||
-(void) addListener:(NSString*)componentName callback:(void (^)(NSString* componentName))callback {
|
||||
[self addListener:componentName callback:callback timeout:nil];
|
||||
}
|
||||
|
||||
-(void) addListener:(NSString*)componentName callback:(void (^)(NSString* componentName))callback timeout:(void (^)(NSString* componentName))timeout {
|
||||
TSBGAppRefreshSubscriber *subscriber = [TSBGAppRefreshSubscriber get:componentName];
|
||||
if (subscriber) {
|
||||
subscriber.callback = callback;
|
||||
subscriber.timeout = timeout;
|
||||
} else {
|
||||
subscriber = [[TSBGAppRefreshSubscriber alloc] initWithIdentifier:componentName callback:callback timeout:timeout];
|
||||
}
|
||||
if (bgAppRefreshTask || _completionHandler) {
|
||||
[subscriber execute];
|
||||
}
|
||||
}
|
||||
|
||||
-(BOOL) hasListener:(NSString*)identifier {
|
||||
return ([TSBGAppRefreshSubscriber get:identifier] != nil);
|
||||
}
|
||||
|
||||
-(void) removeListener:(NSString*)identifier {
|
||||
TSBGAppRefreshSubscriber *subscriber = [TSBGAppRefreshSubscriber get:identifier];
|
||||
if (!subscriber) {
|
||||
NSLog(@"[%@ removeListener] WARNING: Failed to find listener for identifier: %@", TAG, identifier);
|
||||
return;
|
||||
}
|
||||
[subscriber destroy];
|
||||
if ([[TSBGAppRefreshSubscriber subscribers] count] < 1) {
|
||||
[self cancelBGAppRefresh];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSError*) start:(NSString*)identifier {
|
||||
NSLog(@"[%@ start] %@", TAG, identifier);
|
||||
|
||||
if (!identifier) {
|
||||
return [self scheduleBGAppRefresh];
|
||||
} else {
|
||||
TSBGTask *tsTask = [TSBGTask get:identifier];
|
||||
if (!tsTask) {
|
||||
NSString *msg = [NSString stringWithFormat:@"Could not find TSBGTask %@", identifier];
|
||||
NSLog(@"[%@ start] ERROR: %@", TAG, msg);
|
||||
NSError *error = [[NSError alloc] initWithDomain:TAG code:-2 userInfo:@{NSLocalizedFailureReasonErrorKey:msg}];
|
||||
return error;
|
||||
}
|
||||
tsTask.enabled = YES;
|
||||
[tsTask save];
|
||||
return [tsTask schedule];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) stop:(NSString*)identifier {
|
||||
NSLog(@"[%@ stop] %@", TAG, identifier);
|
||||
if (!identifier) {
|
||||
NSArray *tsTasks = [TSBGTask tasks];
|
||||
for (TSBGTask *tsTask in tsTasks) {
|
||||
[tsTask stop];
|
||||
}
|
||||
} else {
|
||||
TSBGTask *tsTask = [TSBGTask get:identifier];
|
||||
[tsTask stop];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) finish:(NSString*)taskId {
|
||||
if (!taskId) { taskId = BACKGROUND_REFRESH_TASK_ID; }
|
||||
|
||||
TSBGTask *tsTask = [TSBGTask get:taskId];
|
||||
// Is it a scheduled-task?
|
||||
if (tsTask) {
|
||||
if (@available(iOS 13.0, *)) {
|
||||
[tsTask finish:YES];
|
||||
}
|
||||
// We're done.
|
||||
return;
|
||||
}
|
||||
|
||||
// Nope, it's a background-fetch event. We have to do subscriber-counting: when all subscribers have signalled #finish, we're done.
|
||||
if (!bgAppRefreshTask && !_completionHandler) {
|
||||
NSLog(@"[%@ finish] %@ Called without a task to finish. Ignoring.", TAG, taskId);
|
||||
return;
|
||||
}
|
||||
|
||||
TSBGAppRefreshSubscriber *subscriber = [TSBGAppRefreshSubscriber get:taskId];
|
||||
if (subscriber) {
|
||||
[subscriber finish];
|
||||
|
||||
NSArray *subscribers = [[TSBGAppRefreshSubscriber subscribers] allValues];
|
||||
long total = [subscribers count];
|
||||
long count = 0;
|
||||
|
||||
for (TSBGAppRefreshSubscriber *subscriber in subscribers) {
|
||||
if (subscriber.finished) count++;
|
||||
}
|
||||
|
||||
NSLog(@"[%@ finish] %@ (%ld of %ld)", TAG, subscriber.identifier, count, total);
|
||||
|
||||
if (total != count) return;
|
||||
|
||||
// If we arrive here without jumping out of foreach above, all subscribers are finished.
|
||||
if (bgAppRefreshTask) {
|
||||
// If we arrive here, all Fetch tasks must be finished.
|
||||
if (@available(iOS 13.0, *)) {
|
||||
[(BGAppRefreshTask*) bgAppRefreshTask setTaskCompletedWithSuccess:YES];
|
||||
}
|
||||
bgAppRefreshTask = nil;
|
||||
} else if (_completionHandler) {
|
||||
_completionHandler(UIBackgroundFetchResultNewData);
|
||||
_completionHandler = nil;
|
||||
@synchronized (self) {
|
||||
if (_backgroundTask != UIBackgroundTaskInvalid) {
|
||||
[[UIApplication sharedApplication] endBackgroundTask:_backgroundTask];
|
||||
_backgroundTask = UIBackgroundTaskInvalid;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
NSLog(@"[%@ finish] Failed to find Fetch subscriber %@", TAG, taskId);
|
||||
}
|
||||
}
|
||||
|
||||
- (void) onAppTerminate {
|
||||
NSLog(@"[%@ onAppTerminate]", TAG);
|
||||
if (_stopOnTerminate) {
|
||||
//[self stop];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) dealloc {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
@end
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -1,39 +0,0 @@
|
|||
//
|
||||
// TSBackgroundFetchTests.m
|
||||
// TSBackgroundFetchTests
|
||||
//
|
||||
// Created by Christopher Scott on 2016-08-03.
|
||||
// Copyright © 2016 Christopher Scott. All rights reserved.
|
||||
//
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
@interface TSBackgroundFetchTests : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation TSBackgroundFetchTests
|
||||
|
||||
- (void)setUp {
|
||||
[super setUp];
|
||||
// Put setup code here. This method is called before the invocation of each test method in the class.
|
||||
}
|
||||
|
||||
- (void)tearDown {
|
||||
// Put teardown code here. This method is called after the invocation of each test method in the class.
|
||||
[super tearDown];
|
||||
}
|
||||
|
||||
- (void)testExample {
|
||||
// This is an example of a functional test case.
|
||||
// Use XCTAssert and related functions to verify your tests produce the correct results.
|
||||
}
|
||||
|
||||
- (void)testPerformanceExample {
|
||||
// This is an example of a performance test case.
|
||||
[self measureBlock:^{
|
||||
// Put the code you want to measure the time of here.
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
Loading…
Add table
Reference in a new issue