From 83e8eb6a8e6247cf77944ab8b4051fd449824fcb Mon Sep 17 00:00:00 2001 From: Juan Carlos Carmona Calvo Date: Tue, 6 Feb 2024 12:23:31 -0700 Subject: [PATCH 01/17] fix: new approach for IOS Sync Backaground --- ios/ZingoMobile.xcodeproj/project.pbxproj | 12 ++ ios/ZingoMobile/AppDelegate.m | 166 ++++++++++++++++++++-- ios/ZingoMobile/Info.plist | 1 + 3 files changed, 168 insertions(+), 11 deletions(-) diff --git a/ios/ZingoMobile.xcodeproj/project.pbxproj b/ios/ZingoMobile.xcodeproj/project.pbxproj index 3c53c5f3a..18d7984e5 100644 --- a/ios/ZingoMobile.xcodeproj/project.pbxproj +++ b/ios/ZingoMobile.xcodeproj/project.pbxproj @@ -12,6 +12,9 @@ 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; 1F1CE02628C13DBD00A954D7 /* librustios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DB4DE513264B0EBA0084F17D /* librustios.a */; }; + 1F7D321D2B71D44800D2879C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F7D321C2B71D44800D2879C /* SystemConfiguration.framework */; }; + 1F7D32202B71D55600D2879C /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F7D321F2B71D55600D2879C /* Reachability.m */; }; + 1F7D32212B71D55600D2879C /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F7D321F2B71D55600D2879C /* Reachability.m */; }; 1FE8E9AC296B85FC004A256B /* BackgroundTasks.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE8E9AB296B85FC004A256B /* BackgroundTasks.framework */; }; 5F9FEE8650525C4AF43859AB /* libPods-ZingoMobile.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1794449599A63970811D5CF0 /* libPods-ZingoMobile.a */; }; 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; @@ -45,6 +48,9 @@ 1F26E03C28C0E45B009737D7 /* librustios.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = librustios.a; path = "../rust/target/aarch64-apple-ios-sim/release/librustios.a"; sourceTree = ""; }; 1F70326429905E6A001D70A2 /* ZingoMobile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = ZingoMobile.entitlements; path = ZingoMobile/ZingoMobile.entitlements; sourceTree = ""; }; 1F7638CA28BD7C3E0017F9B6 /* librustios.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = librustios.a; path = ../rust/target/universal/release/librustios.a; sourceTree = ""; }; + 1F7D321C2B71D44800D2879C /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + 1F7D321E2B71D54600D2879C /* Reachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Reachability.h; path = ../../../../Downloads/Reachability.h; sourceTree = ""; }; + 1F7D321F2B71D55600D2879C /* Reachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Reachability.m; path = ../../../../Downloads/Reachability.m; sourceTree = ""; }; 1FE8E9AB296B85FC004A256B /* BackgroundTasks.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = BackgroundTasks.framework; path = System/Library/Frameworks/BackgroundTasks.framework; sourceTree = SDKROOT; }; 57C30AB6DAB41A2ED2699835 /* libPods-ZingoMobile-ZingoMobileTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ZingoMobile-ZingoMobileTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 65B24C2E2D48C83D6B5DDF6E /* Pods-ZingoMobile-ZingoMobileTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ZingoMobile-ZingoMobileTests.debug.xcconfig"; path = "Target Support Files/Pods-ZingoMobile-ZingoMobileTests/Pods-ZingoMobile-ZingoMobileTests.debug.xcconfig"; sourceTree = ""; }; @@ -72,6 +78,7 @@ files = ( 1FE8E9AC296B85FC004A256B /* BackgroundTasks.framework in Frameworks */, 5F9FEE8650525C4AF43859AB /* libPods-ZingoMobile.a in Frameworks */, + 1F7D321D2B71D44800D2879C /* SystemConfiguration.framework in Frameworks */, 1F1CE02628C13DBD00A954D7 /* librustios.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -99,8 +106,10 @@ 13B07FAE1A68108700A75B9A /* ZingoMobile */ = { isa = PBXGroup; children = ( + 1F7D321F2B71D55600D2879C /* Reachability.m */, 1F70326429905E6A001D70A2 /* ZingoMobile.entitlements */, DB4DE516264B103E0084F17D /* RPCModule.h */, + 1F7D321E2B71D54600D2879C /* Reachability.h */, DB4DE517264B103E0084F17D /* RPCModule.m */, 13B07FAF1A68108700A75B9A /* AppDelegate.h */, 13B07FB01A68108700A75B9A /* AppDelegate.m */, @@ -115,6 +124,7 @@ 2D16E6871FA4F8E400B85C8A /* Frameworks */ = { isa = PBXGroup; children = ( + 1F7D321C2B71D44800D2879C /* SystemConfiguration.framework */, 1FE8E9AB296B85FC004A256B /* BackgroundTasks.framework */, DB4DE513264B0EBA0084F17D /* librustios.a */, 1F7638CA28BD7C3E0017F9B6 /* librustios.a */, @@ -423,6 +433,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 1F7D32212B71D55600D2879C /* Reachability.m in Sources */, 00E356F31AD99517003FC87E /* ZingoMobileTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -433,6 +444,7 @@ files = ( 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */, DB4DE518264B103E0084F17D /* RPCModule.m in Sources */, + 1F7D32202B71D55600D2879C /* Reachability.m in Sources */, 13B07FC11A68108700A75B9A /* main.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/ios/ZingoMobile/AppDelegate.m b/ios/ZingoMobile/AppDelegate.m index f53854398..9629671e7 100644 --- a/ios/ZingoMobile/AppDelegate.m +++ b/ios/ZingoMobile/AppDelegate.m @@ -8,6 +8,7 @@ #import #import "RPCModule.h" #import "rust.h" +#import "reachability.h" #ifdef FB_SONARKIT_ENABLED #import @@ -40,6 +41,8 @@ + (void)setSyncFinished:(BOOL)newSyncFinished { } static NSString* syncTask = @"Zingo_Processing_Task_ID"; +static NSString* syncSchedulerTask = @"Zingo_Processing_Scheduler_Task_ID"; +static BOOL isConnectedToWifi = false; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { @@ -59,6 +62,10 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( rootViewController.view = rootView; self.window.rootViewController = rootViewController; [self.window makeKeyAndVisible]; + + NSLog(@"handle background task"); + [self handleBackgroundTask]; + return YES; } @@ -89,8 +96,8 @@ - (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull N - (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions { if (@available(iOS 13.0, *)) { - NSLog(@"configureProcessingTask"); - [self configureProcessingTask]; + //NSLog(@"configureProcessingTask"); + //[self configureProcessingTask]; } return YES; } @@ -98,20 +105,26 @@ - (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions: - (void)applicationWillEnterForeground:(UIApplication *)application { // cancel existing task (if any) - NSLog(@"scheduleProcessingTask CANCEL - foreground"); - [self setSyncFinished:true]; - [BGTaskScheduler.sharedScheduler cancelTaskRequestWithIdentifier:syncTask]; + //NSLog(@"scheduleProcessingTask CANCEL - foreground"); + //[self setSyncFinished:true]; + //char *resp2 = execute("interrupt_sync_after_batch", "true"); + //NSString* respStr2 = [NSString stringWithUTF8String:resp2]; + //NSLog(@"interrupt syncing %@", respStr2); + //[BGTaskScheduler.sharedScheduler cancelTaskRequestWithIdentifier:syncTask]; } - (void)applicationDidEnterBackground:(UIApplication *)application { if (@available(iOS 13.0, *)) { - NSLog(@"scheduleProcessingTask"); - [self scheduleProcessingTask]; + //NSLog(@"scheduleBackgroundTask"); + //[self scheduleBackgroundTask]; + //NSLog(@"scheduleShedulerBackgroundTask"); + //[self scheduleSchedulerBackgroundTask]; + //[self handleBackgroundTask]; } } --(void)configureProcessingTask { +-(void)configureProcessingTask_old { if (@available(iOS 13.0, *)) { [[BGTaskScheduler sharedScheduler] registerForTaskWithIdentifier:syncTask usingQueue:nil @@ -144,7 +157,9 @@ -(void)syncingProcessBackgroundTask:(NSString *)noValue { NSLog(@"handleProcessingTask sync end %@", respStr2); [self setSyncFinished:true]; - + char *resp3 = execute("interrupt_sync_after_batch", "true"); + NSString* respStr3 = [NSString stringWithUTF8String:resp3]; + NSLog(@"interrupt syncing %@", respStr3); // the execute `sync` already save the wallet when finished } else { @@ -223,7 +238,7 @@ -(BOOL)wallet__exists { } } --(void)scheduleProcessingTask { +-(void)scheduleProcessingTask_old { if (@available(iOS 13.0, *)) { NSLog(@"schedulingProcessingTask"); NSError *error = NULL; @@ -235,7 +250,6 @@ -(void)scheduleProcessingTask { request.earliestBeginDate = nil; BOOL success = [[BGTaskScheduler sharedScheduler] submitTaskRequest:request error:&error]; if (!success) { - // Errorcodes https://stackoverflow.com/a/58224050/872051 NSLog(@"Failed to submit request: %@", error); } else { NSLog(@"Success submit request %@", request); @@ -244,4 +258,134 @@ -(void)scheduleProcessingTask { // No fallback } } + +// NEW BACKGROUND SCHEDULING TASK + +- (void)handleBackgroundTask { + // We require the background task to run when connected to the power and wifi + Reachability *reachability = [Reachability reachabilityForInternetConnection]; + NetworkStatus networkStatus = [reachability currentReachabilityStatus]; + + if (networkStatus == ReachableViaWiFi) { + isConnectedToWifi = true; + } else { + isConnectedToWifi = false; + } + NSLog(@"BGTask isConnectedToWifi %@", isConnectedToWifi ? @"true" : @"false"); + + [self registerTasks]; +} + +- (void)registerTasks { + BOOL bcgSyncTaskResult; + bcgSyncTaskResult = [[BGTaskScheduler sharedScheduler] registerForTaskWithIdentifier:syncTask usingQueue:dispatch_get_main_queue() launchHandler:^(BGTask * _Nonnull task) { + if (![task isKindOfClass:[BGProcessingTask class]]) { + return; + } + NSLog(@"BGTask BGTaskScheduler.shared.register SYNC called"); + [self startBackgroundTask:(BGProcessingTask *)task]; + }]; + + NSLog(@"BGTask SYNC registered %d", bcgSyncTaskResult); + + BOOL bcgSchedulerTaskResult; + bcgSchedulerTaskResult = [[BGTaskScheduler sharedScheduler] registerForTaskWithIdentifier:syncSchedulerTask usingQueue:dispatch_get_main_queue() launchHandler:^(BGTask * _Nonnull task) { + if (![task isKindOfClass:[BGProcessingTask class]]) { + return; + } + NSLog(@"BGTask BGTaskScheduler.shared.register SCHEDULER called"); + [self scheduleSchedulerBackgroundTask]; + [self scheduleBackgroundTask]; + [task setTaskCompletedWithSuccess:YES]; + }]; + + NSLog(@"BGTask SCHEDULER registered %d", bcgSchedulerTaskResult); +} + + +- (void)startBackgroundTask:(BGProcessingTask *)task { + NSLog(@"BGTask startBackgroundTask called"); + + // Schedule tasks for the next time + [self scheduleBackgroundTask]; + [self scheduleSchedulerBackgroundTask]; + + if (!isConnectedToWifi) { + NSLog(@"BGTask startBackgroundTask: not connected to the wifi"); + [task setTaskCompletedWithSuccess:NO]; + return; + } + + // Start the syncing + NSLog(@"configureProcessingTask run"); + [NSThread detachNewThreadSelector:@selector(syncingProcessBackgroundTask:) toTarget:self withObject:nil]; + [self syncingStatusProcessBackgroundTask:nil]; + + task.expirationHandler = ^{ + NSLog(@"BGTask startBackgroundTask expirationHandler called"); + // Stop the syncing because the allocated time is about to expire + NSLog(@"scheduleProcessingTask CANCEL - is about to expire"); + [self setSyncFinished:true]; + char *resp2 = execute("interrupt_sync_after_batch", "true"); + NSString* respStr2 = [NSString stringWithUTF8String:resp2]; + NSLog(@"interrupt syncing %@", respStr2); + }; +} + +- (void)scheduleBackgroundTask { + // This method can be called as many times as needed, the previously submitted + // request will be overridden by the new one. + NSLog(@"BGTask scheduleBackgroundTask called"); + + BGProcessingTaskRequest *request = [[BGProcessingTaskRequest alloc] initWithIdentifier:syncTask]; + + NSDate *today = [[NSCalendar currentCalendar] startOfDayForDate:[NSDate date]]; + NSDate *tomorrow = [[NSCalendar currentCalendar] dateByAddingUnit:NSCalendarUnitDay value:1 toDate:today options:0]; + + NSDateComponents *earlyMorningComponent = [[NSDateComponents alloc] init]; + earlyMorningComponent.hour = 3; + earlyMorningComponent.minute = arc4random_uniform(61); + NSDate *earlyMorning = [[NSCalendar currentCalendar] dateByAddingComponents:earlyMorningComponent toDate:tomorrow options:0]; + + request.earliestBeginDate = earlyMorning; + request.requiresExternalPower = YES; + request.requiresNetworkConnectivity = YES; + + NSError *error = nil; + [[BGTaskScheduler sharedScheduler] submitTaskRequest:request error:&error]; + if (error) { + NSLog(@"BGTask scheduleBackgroundTask failed to submit, error: %@", error); + } else { + NSLog(@"BGTask scheduleBackgroundTask succeeded to submit"); + } +} + +- (void)scheduleSchedulerBackgroundTask { + // This method can be called as many times as needed, the previously submitted + // request will be overridden by the new one. + NSLog(@"BGTask scheduleSchedulerBackgroundTask called"); + + BGProcessingTaskRequest *request = [[BGProcessingTaskRequest alloc] initWithIdentifier:syncSchedulerTask]; + + NSDate *today = [[NSCalendar currentCalendar] startOfDayForDate:[NSDate date]]; + NSDate *tomorrow = [[NSCalendar currentCalendar] dateByAddingUnit:NSCalendarUnitDay value:1 toDate:today options:0]; + + NSDateComponents *afternoonComponent = [[NSDateComponents alloc] init]; + afternoonComponent.hour = 14; + afternoonComponent.minute = arc4random_uniform(61); + NSDate *afternoon = [[NSCalendar currentCalendar] dateByAddingComponents:afternoonComponent toDate:tomorrow options:0]; + + request.earliestBeginDate = afternoon; + request.requiresExternalPower = NO; + request.requiresNetworkConnectivity = NO; + + NSError *error = nil; + [[BGTaskScheduler sharedScheduler] submitTaskRequest:request error:&error]; + if (error) { + NSLog(@"BGTask scheduleSchedulerBackgroundTask failed to submit, error: %@", error); + } else { + NSLog(@"BGTask scheduleSchedulerBackgroundTask succeeded to submit"); + } +} + @end diff --git a/ios/ZingoMobile/Info.plist b/ios/ZingoMobile/Info.plist index 014ac1986..575b627f5 100644 --- a/ios/ZingoMobile/Info.plist +++ b/ios/ZingoMobile/Info.plist @@ -7,6 +7,7 @@ com.transistorsoft.fetch Zingo_Refresh_Task_ID Zingo_Processing_Task_ID + Zingo_Processing_Scheduler_Task_ID CFBundleDevelopmentRegion en From dabe67ba3b06a4d638d2426d274f4a86d8685f38 Mon Sep 17 00:00:00 2001 From: Juan Carlos Carmona Calvo Date: Tue, 6 Feb 2024 13:46:35 -0700 Subject: [PATCH 02/17] fix: logging fixed --- ios/ZingoMobile/AppDelegate.m | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/ios/ZingoMobile/AppDelegate.m b/ios/ZingoMobile/AppDelegate.m index 9629671e7..0265a1ead 100644 --- a/ios/ZingoMobile/AppDelegate.m +++ b/ios/ZingoMobile/AppDelegate.m @@ -63,7 +63,7 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( self.window.rootViewController = rootViewController; [self.window makeKeyAndVisible]; - NSLog(@"handle background task"); + NSLog(@"BGTask handle background task"); [self handleBackgroundTask]; return YES; @@ -147,25 +147,25 @@ -(void)syncingProcessBackgroundTask:(NSString *)noValue { if (exists) { - NSLog(@"handleProcessingTask sync begin"); + NSLog(@"BGTask handleProcessingTask sync begin"); [self setSyncFinished:false]; char *resp2 = execute("sync", ""); NSString* respStr2 = [NSString stringWithUTF8String:resp2]; rust_free(resp2); - NSLog(@"handleProcessingTask sync end %@", respStr2); + NSLog(@"BGTask handleProcessingTask sync end %@", respStr2); [self setSyncFinished:true]; char *resp3 = execute("interrupt_sync_after_batch", "true"); NSString* respStr3 = [NSString stringWithUTF8String:resp3]; - NSLog(@"interrupt syncing %@", respStr3); + NSLog(@"BGTask interrupt syncing %@", respStr3); // the execute `sync` already save the wallet when finished } else { [self setSyncFinished:true]; - NSLog(@"handleProcessingTask No exists wallet"); + NSLog(@"BGTask handleProcessingTask No exists wallet"); } @@ -176,7 +176,7 @@ -(void)syncingProcessBackgroundTask:(NSString *)noValue { -(void)syncingStatusProcessBackgroundTask:(NSString *)noValue { @autoreleasepool { - NSLog(@"handleProcessingTask sync status begin %i", self.syncFinished); + NSLog(@"BGTask handleProcessingTask sync status begin %i", self.syncFinished); NSInteger prevBatch = -1; while(!self.syncFinished) { @@ -184,7 +184,7 @@ -(void)syncingStatusProcessBackgroundTask:(NSString *)noValue { char *resp = execute("syncstatus", ""); NSString* respStr = [NSString stringWithUTF8String:resp]; rust_free(resp); - NSLog(@"handleProcessingTask sync status response %i %@", self.syncFinished, respStr); + NSLog(@"BGTask handleProcessingTask sync status response %i %@", self.syncFinished, respStr); NSData *data = [respStr dataUsingEncoding:NSUTF8StringEncoding]; id jsonResp = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; @@ -192,7 +192,7 @@ -(void)syncingStatusProcessBackgroundTask:(NSString *)noValue { NSInteger batch = [batchStr integerValue]; BOOL progress = [jsonResp valueForKey:@"in_progress"]; - NSLog(@"handleProcessingTask batch number %i %@", self.syncFinished, batchStr); + NSLog(@"BGTask handleProcessingTask batch number %i %@", self.syncFinished, batchStr); if (prevBatch != -1 && batch > 0 && prevBatch != batch) { // save the wallet @@ -207,7 +207,7 @@ -(void)syncingStatusProcessBackgroundTask:(NSString *)noValue { NSString *jsonBackgroud = [NSString stringWithFormat: @"%@%@%@%@%@", @"{\"batches\": \"", batchStr, @"\", \"date\": \"", timeStampStr, @"\"}"]; [rpcmodule saveBackgroundFile:jsonBackgroud]; - NSLog(@"handleProcessingTask save wallet & background batch %i %@ %i %@", self.syncFinished, batchStr, progress, timeStampStr); + NSLog(@"BGTask handleProcessingTask save wallet & background batch %i %@ %i %@", self.syncFinished, batchStr, progress, timeStampStr); } prevBatch = batch; } @@ -317,18 +317,18 @@ - (void)startBackgroundTask:(BGProcessingTask *)task { } // Start the syncing - NSLog(@"configureProcessingTask run"); + NSLog(@"BGTask configureProcessingTask run"); [NSThread detachNewThreadSelector:@selector(syncingProcessBackgroundTask:) toTarget:self withObject:nil]; [self syncingStatusProcessBackgroundTask:nil]; task.expirationHandler = ^{ NSLog(@"BGTask startBackgroundTask expirationHandler called"); // Stop the syncing because the allocated time is about to expire - NSLog(@"scheduleProcessingTask CANCEL - is about to expire"); + NSLog(@"BGTask scheduleProcessingTask CANCEL - is about to expire"); [self setSyncFinished:true]; char *resp2 = execute("interrupt_sync_after_batch", "true"); NSString* respStr2 = [NSString stringWithUTF8String:resp2]; - NSLog(@"interrupt syncing %@", respStr2); + NSLog(@"BGTask interrupt syncing %@", respStr2); }; } From 26a7146d62189bb07b3df2f1df45faf754dfb133 Mon Sep 17 00:00:00 2001 From: JC Date: Tue, 6 Feb 2024 15:01:06 -0700 Subject: [PATCH 03/17] fix: applicationDidEnterBackground tasks scheduled --- ios/ZingoMobile/AppDelegate.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ios/ZingoMobile/AppDelegate.m b/ios/ZingoMobile/AppDelegate.m index 0265a1ead..be54afc24 100644 --- a/ios/ZingoMobile/AppDelegate.m +++ b/ios/ZingoMobile/AppDelegate.m @@ -116,10 +116,10 @@ - (void)applicationWillEnterForeground:(UIApplication *)application - (void)applicationDidEnterBackground:(UIApplication *)application { if (@available(iOS 13.0, *)) { - //NSLog(@"scheduleBackgroundTask"); - //[self scheduleBackgroundTask]; - //NSLog(@"scheduleShedulerBackgroundTask"); - //[self scheduleSchedulerBackgroundTask]; + NSLog(@"scheduleBackgroundTask"); + [self scheduleBackgroundTask]; + NSLog(@"scheduleShedulerBackgroundTask"); + [self scheduleSchedulerBackgroundTask]; //[self handleBackgroundTask]; } } From 7ea81a716e20b8f8d6a191969e6951c6d423addb Mon Sep 17 00:00:00 2001 From: Juan Carlos Carmona Calvo Date: Tue, 6 Feb 2024 16:43:47 -0700 Subject: [PATCH 04/17] fix: applicationWillEnterForeground finishing task --- ios/ZingoMobile/AppDelegate.m | 62 +++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/ios/ZingoMobile/AppDelegate.m b/ios/ZingoMobile/AppDelegate.m index be54afc24..f0acd0033 100644 --- a/ios/ZingoMobile/AppDelegate.m +++ b/ios/ZingoMobile/AppDelegate.m @@ -105,20 +105,20 @@ - (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions: - (void)applicationWillEnterForeground:(UIApplication *)application { // cancel existing task (if any) - //NSLog(@"scheduleProcessingTask CANCEL - foreground"); - //[self setSyncFinished:true]; - //char *resp2 = execute("interrupt_sync_after_batch", "true"); - //NSString* respStr2 = [NSString stringWithUTF8String:resp2]; - //NSLog(@"interrupt syncing %@", respStr2); - //[BGTaskScheduler.sharedScheduler cancelTaskRequestWithIdentifier:syncTask]; + NSLog(@"BGTask scheduleProcessingTask CANCEL - foreground"); + [self setSyncFinished:true]; + char *resp2 = execute("interrupt_sync_after_batch", "true"); + NSString* respStr2 = [NSString stringWithUTF8String:resp2]; + NSLog(@"BGTask interrupt syncing %@", respStr2); + [BGTaskScheduler.sharedScheduler cancelTaskRequestWithIdentifier:syncTask]; } - (void)applicationDidEnterBackground:(UIApplication *)application { if (@available(iOS 13.0, *)) { - NSLog(@"scheduleBackgroundTask"); + NSLog(@"BGTask scheduleBackgroundTask"); [self scheduleBackgroundTask]; - NSLog(@"scheduleShedulerBackgroundTask"); + NSLog(@"BGTask scheduleShedulerBackgroundTask"); [self scheduleSchedulerBackgroundTask]; //[self handleBackgroundTask]; } @@ -339,15 +339,22 @@ - (void)scheduleBackgroundTask { BGProcessingTaskRequest *request = [[BGProcessingTaskRequest alloc] initWithIdentifier:syncTask]; - NSDate *today = [[NSCalendar currentCalendar] startOfDayForDate:[NSDate date]]; - NSDate *tomorrow = [[NSCalendar currentCalendar] dateByAddingUnit:NSCalendarUnitDay value:1 toDate:today options:0]; + //NSDate *today = [[NSCalendar currentCalendar] startOfDayForDate:[NSDate date]]; + //NSDate *tomorrow = [[NSCalendar currentCalendar] dateByAddingUnit:NSCalendarUnitDay value:1 toDate:today options:0]; - NSDateComponents *earlyMorningComponent = [[NSDateComponents alloc] init]; - earlyMorningComponent.hour = 3; - earlyMorningComponent.minute = arc4random_uniform(61); - NSDate *earlyMorning = [[NSCalendar currentCalendar] dateByAddingComponents:earlyMorningComponent toDate:tomorrow options:0]; + //NSDateComponents *earlyMorningComponent = [[NSDateComponents alloc] init]; + //earlyMorningComponent.hour = 3; + //earlyMorningComponent.minute = arc4random_uniform(61); + //NSDate *earlyMorning = [[NSCalendar currentCalendar] dateByAddingComponents:earlyMorningComponent toDate:tomorrow options:0]; - request.earliestBeginDate = earlyMorning; + // Obtiene la fecha actual + NSDate *now = [NSDate date]; + + // Agrega 2 minutos a la fecha actual + NSDate *twoMinutesLater = [now dateByAddingTimeInterval:120]; // 2 minutos = 120 segundos + + //request.earliestBeginDate = earlyMorning; + request.earliestBeginDate = twoMinutesLater; request.requiresExternalPower = YES; request.requiresNetworkConnectivity = YES; @@ -367,17 +374,24 @@ - (void)scheduleSchedulerBackgroundTask { BGProcessingTaskRequest *request = [[BGProcessingTaskRequest alloc] initWithIdentifier:syncSchedulerTask]; - NSDate *today = [[NSCalendar currentCalendar] startOfDayForDate:[NSDate date]]; - NSDate *tomorrow = [[NSCalendar currentCalendar] dateByAddingUnit:NSCalendarUnitDay value:1 toDate:today options:0]; + //NSDate *today = [[NSCalendar currentCalendar] startOfDayForDate:[NSDate date]]; + //NSDate *tomorrow = [[NSCalendar currentCalendar] dateByAddingUnit:NSCalendarUnitDay value:1 toDate:today options:0]; - NSDateComponents *afternoonComponent = [[NSDateComponents alloc] init]; - afternoonComponent.hour = 14; - afternoonComponent.minute = arc4random_uniform(61); - NSDate *afternoon = [[NSCalendar currentCalendar] dateByAddingComponents:afternoonComponent toDate:tomorrow options:0]; + //NSDateComponents *afternoonComponent = [[NSDateComponents alloc] init]; + //afternoonComponent.hour = 14; + //afternoonComponent.minute = arc4random_uniform(61); + //NSDate *afternoon = [[NSCalendar currentCalendar] dateByAddingComponents:afternoonComponent toDate:tomorrow options:0]; - request.earliestBeginDate = afternoon; - request.requiresExternalPower = NO; - request.requiresNetworkConnectivity = NO; + // Obtiene la fecha actual + NSDate *now = [NSDate date]; + + // Agrega 2 minutos a la fecha actual + NSDate *twoMinutesLater = [now dateByAddingTimeInterval:120]; // 2 minutos = 120 segundos + + //request.earliestBeginDate = earlyMorning; + request.earliestBeginDate = twoMinutesLater; + request.requiresExternalPower = YES; + request.requiresNetworkConnectivity = YES; NSError *error = nil; [[BGTaskScheduler sharedScheduler] submitTaskRequest:request error:&error]; From c57fd00dbbc3fb4d6e90800c08eded9871dda8ac Mon Sep 17 00:00:00 2001 From: Juan Carlos Carmona Calvo Date: Tue, 6 Feb 2024 16:47:00 -0700 Subject: [PATCH 05/17] fix: some comments --- ios/ZingoMobile/AppDelegate.m | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ios/ZingoMobile/AppDelegate.m b/ios/ZingoMobile/AppDelegate.m index f0acd0033..2c35a468e 100644 --- a/ios/ZingoMobile/AppDelegate.m +++ b/ios/ZingoMobile/AppDelegate.m @@ -339,6 +339,7 @@ - (void)scheduleBackgroundTask { BGProcessingTaskRequest *request = [[BGProcessingTaskRequest alloc] initWithIdentifier:syncTask]; + // PRODUCTION //NSDate *today = [[NSCalendar currentCalendar] startOfDayForDate:[NSDate date]]; //NSDate *tomorrow = [[NSCalendar currentCalendar] dateByAddingUnit:NSCalendarUnitDay value:1 toDate:today options:0]; @@ -347,11 +348,10 @@ - (void)scheduleBackgroundTask { //earlyMorningComponent.minute = arc4random_uniform(61); //NSDate *earlyMorning = [[NSCalendar currentCalendar] dateByAddingComponents:earlyMorningComponent toDate:tomorrow options:0]; - // Obtiene la fecha actual + // DEVELOPMENT NSDate *now = [NSDate date]; - // Agrega 2 minutos a la fecha actual - NSDate *twoMinutesLater = [now dateByAddingTimeInterval:120]; // 2 minutos = 120 segundos + NSDate *twoMinutesLater = [now dateByAddingTimeInterval:120]; // 2 minutes = 120 seconds //request.earliestBeginDate = earlyMorning; request.earliestBeginDate = twoMinutesLater; @@ -374,6 +374,7 @@ - (void)scheduleSchedulerBackgroundTask { BGProcessingTaskRequest *request = [[BGProcessingTaskRequest alloc] initWithIdentifier:syncSchedulerTask]; + // PRODUCTION //NSDate *today = [[NSCalendar currentCalendar] startOfDayForDate:[NSDate date]]; //NSDate *tomorrow = [[NSCalendar currentCalendar] dateByAddingUnit:NSCalendarUnitDay value:1 toDate:today options:0]; @@ -382,11 +383,10 @@ - (void)scheduleSchedulerBackgroundTask { //afternoonComponent.minute = arc4random_uniform(61); //NSDate *afternoon = [[NSCalendar currentCalendar] dateByAddingComponents:afternoonComponent toDate:tomorrow options:0]; - // Obtiene la fecha actual + // DEVELOPMENT NSDate *now = [NSDate date]; - // Agrega 2 minutos a la fecha actual - NSDate *twoMinutesLater = [now dateByAddingTimeInterval:120]; // 2 minutos = 120 segundos + NSDate *twoMinutesLater = [now dateByAddingTimeInterval:120]; // 2 minutes = 120 seconds //request.earliestBeginDate = earlyMorning; request.earliestBeginDate = twoMinutesLater; From f3c6dac863ca997a54f03baf0e6153d4f2a54ec1 Mon Sep 17 00:00:00 2001 From: Juan Carlos Carmona Calvo Date: Wed, 7 Feb 2024 08:09:29 -0700 Subject: [PATCH 06/17] fix: small fix --- ios/ZingoMobile/AppDelegate.m | 44 +++++++++++++++++------------------ 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/ios/ZingoMobile/AppDelegate.m b/ios/ZingoMobile/AppDelegate.m index 2c35a468e..5f407bfb0 100644 --- a/ios/ZingoMobile/AppDelegate.m +++ b/ios/ZingoMobile/AppDelegate.m @@ -340,21 +340,21 @@ - (void)scheduleBackgroundTask { BGProcessingTaskRequest *request = [[BGProcessingTaskRequest alloc] initWithIdentifier:syncTask]; // PRODUCTION - //NSDate *today = [[NSCalendar currentCalendar] startOfDayForDate:[NSDate date]]; - //NSDate *tomorrow = [[NSCalendar currentCalendar] dateByAddingUnit:NSCalendarUnitDay value:1 toDate:today options:0]; + NSDate *today = [[NSCalendar currentCalendar] startOfDayForDate:[NSDate date]]; + NSDate *tomorrow = [[NSCalendar currentCalendar] dateByAddingUnit:NSCalendarUnitDay value:1 toDate:today options:0]; - //NSDateComponents *earlyMorningComponent = [[NSDateComponents alloc] init]; - //earlyMorningComponent.hour = 3; - //earlyMorningComponent.minute = arc4random_uniform(61); - //NSDate *earlyMorning = [[NSCalendar currentCalendar] dateByAddingComponents:earlyMorningComponent toDate:tomorrow options:0]; + NSDateComponents *earlyMorningComponent = [[NSDateComponents alloc] init]; + earlyMorningComponent.hour = 3; + earlyMorningComponent.minute = arc4random_uniform(61); + NSDate *earlyMorning = [[NSCalendar currentCalendar] dateByAddingComponents:earlyMorningComponent toDate:tomorrow options:0]; // DEVELOPMENT - NSDate *now = [NSDate date]; + //NSDate *now = [NSDate date]; - NSDate *twoMinutesLater = [now dateByAddingTimeInterval:120]; // 2 minutes = 120 seconds + //NSDate *twoMinutesLater = [now dateByAddingTimeInterval:120]; // 2 minutes = 120 seconds - //request.earliestBeginDate = earlyMorning; - request.earliestBeginDate = twoMinutesLater; + request.earliestBeginDate = earlyMorning; + //request.earliestBeginDate = twoMinutesLater; request.requiresExternalPower = YES; request.requiresNetworkConnectivity = YES; @@ -375,23 +375,23 @@ - (void)scheduleSchedulerBackgroundTask { BGProcessingTaskRequest *request = [[BGProcessingTaskRequest alloc] initWithIdentifier:syncSchedulerTask]; // PRODUCTION - //NSDate *today = [[NSCalendar currentCalendar] startOfDayForDate:[NSDate date]]; - //NSDate *tomorrow = [[NSCalendar currentCalendar] dateByAddingUnit:NSCalendarUnitDay value:1 toDate:today options:0]; + NSDate *today = [[NSCalendar currentCalendar] startOfDayForDate:[NSDate date]]; + NSDate *tomorrow = [[NSCalendar currentCalendar] dateByAddingUnit:NSCalendarUnitDay value:1 toDate:today options:0]; - //NSDateComponents *afternoonComponent = [[NSDateComponents alloc] init]; - //afternoonComponent.hour = 14; - //afternoonComponent.minute = arc4random_uniform(61); - //NSDate *afternoon = [[NSCalendar currentCalendar] dateByAddingComponents:afternoonComponent toDate:tomorrow options:0]; + NSDateComponents *afternoonComponent = [[NSDateComponents alloc] init]; + afternoonComponent.hour = 14; + afternoonComponent.minute = arc4random_uniform(61); + NSDate *afternoon = [[NSCalendar currentCalendar] dateByAddingComponents:afternoonComponent toDate:tomorrow options:0]; // DEVELOPMENT - NSDate *now = [NSDate date]; + //NSDate *now = [NSDate date]; - NSDate *twoMinutesLater = [now dateByAddingTimeInterval:120]; // 2 minutes = 120 seconds + //NSDate *twoMinutesLater = [now dateByAddingTimeInterval:120]; // 2 minutes = 120 seconds - //request.earliestBeginDate = earlyMorning; - request.earliestBeginDate = twoMinutesLater; - request.requiresExternalPower = YES; - request.requiresNetworkConnectivity = YES; + request.earliestBeginDate = afternoon; + //request.earliestBeginDate = twoMinutesLater; + request.requiresExternalPower = NO; + request.requiresNetworkConnectivity = NO; NSError *error = nil; [[BGTaskScheduler sharedScheduler] submitTaskRequest:request error:&error]; From 1a84627f8e5a13cca0652148907e0f6be386da2d Mon Sep 17 00:00:00 2001 From: Juan Carlos Carmona Calvo Date: Wed, 7 Feb 2024 08:56:21 -0700 Subject: [PATCH 07/17] fix: adding Reachability lib to check wifi --- ios/ZingoMobile.xcodeproj/project.pbxproj | 16 +- ios/ZingoMobile/Reachability.h | 103 +++++ ios/ZingoMobile/Reachability.m | 508 ++++++++++++++++++++++ 3 files changed, 619 insertions(+), 8 deletions(-) create mode 100644 ios/ZingoMobile/Reachability.h create mode 100644 ios/ZingoMobile/Reachability.m diff --git a/ios/ZingoMobile.xcodeproj/project.pbxproj b/ios/ZingoMobile.xcodeproj/project.pbxproj index 18d7984e5..dd3eb9c99 100644 --- a/ios/ZingoMobile.xcodeproj/project.pbxproj +++ b/ios/ZingoMobile.xcodeproj/project.pbxproj @@ -13,8 +13,8 @@ 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; 1F1CE02628C13DBD00A954D7 /* librustios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DB4DE513264B0EBA0084F17D /* librustios.a */; }; 1F7D321D2B71D44800D2879C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F7D321C2B71D44800D2879C /* SystemConfiguration.framework */; }; - 1F7D32202B71D55600D2879C /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F7D321F2B71D55600D2879C /* Reachability.m */; }; - 1F7D32212B71D55600D2879C /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F7D321F2B71D55600D2879C /* Reachability.m */; }; + 1F7D32272B73DF3800D2879C /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F7D32262B73DF3800D2879C /* Reachability.m */; }; + 1F7D32282B73DF3800D2879C /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F7D32262B73DF3800D2879C /* Reachability.m */; }; 1FE8E9AC296B85FC004A256B /* BackgroundTasks.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE8E9AB296B85FC004A256B /* BackgroundTasks.framework */; }; 5F9FEE8650525C4AF43859AB /* libPods-ZingoMobile.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1794449599A63970811D5CF0 /* libPods-ZingoMobile.a */; }; 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; @@ -49,8 +49,8 @@ 1F70326429905E6A001D70A2 /* ZingoMobile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = ZingoMobile.entitlements; path = ZingoMobile/ZingoMobile.entitlements; sourceTree = ""; }; 1F7638CA28BD7C3E0017F9B6 /* librustios.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = librustios.a; path = ../rust/target/universal/release/librustios.a; sourceTree = ""; }; 1F7D321C2B71D44800D2879C /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; - 1F7D321E2B71D54600D2879C /* Reachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Reachability.h; path = ../../../../Downloads/Reachability.h; sourceTree = ""; }; - 1F7D321F2B71D55600D2879C /* Reachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Reachability.m; path = ../../../../Downloads/Reachability.m; sourceTree = ""; }; + 1F7D32252B73DF1600D2879C /* Reachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Reachability.h; path = ZingoMobile/Reachability.h; sourceTree = ""; }; + 1F7D32262B73DF3800D2879C /* Reachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Reachability.m; path = ZingoMobile/Reachability.m; sourceTree = ""; }; 1FE8E9AB296B85FC004A256B /* BackgroundTasks.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = BackgroundTasks.framework; path = System/Library/Frameworks/BackgroundTasks.framework; sourceTree = SDKROOT; }; 57C30AB6DAB41A2ED2699835 /* libPods-ZingoMobile-ZingoMobileTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ZingoMobile-ZingoMobileTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 65B24C2E2D48C83D6B5DDF6E /* Pods-ZingoMobile-ZingoMobileTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ZingoMobile-ZingoMobileTests.debug.xcconfig"; path = "Target Support Files/Pods-ZingoMobile-ZingoMobileTests/Pods-ZingoMobile-ZingoMobileTests.debug.xcconfig"; sourceTree = ""; }; @@ -106,10 +106,10 @@ 13B07FAE1A68108700A75B9A /* ZingoMobile */ = { isa = PBXGroup; children = ( - 1F7D321F2B71D55600D2879C /* Reachability.m */, + 1F7D32262B73DF3800D2879C /* Reachability.m */, + 1F7D32252B73DF1600D2879C /* Reachability.h */, 1F70326429905E6A001D70A2 /* ZingoMobile.entitlements */, DB4DE516264B103E0084F17D /* RPCModule.h */, - 1F7D321E2B71D54600D2879C /* Reachability.h */, DB4DE517264B103E0084F17D /* RPCModule.m */, 13B07FAF1A68108700A75B9A /* AppDelegate.h */, 13B07FB01A68108700A75B9A /* AppDelegate.m */, @@ -433,7 +433,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 1F7D32212B71D55600D2879C /* Reachability.m in Sources */, + 1F7D32282B73DF3800D2879C /* Reachability.m in Sources */, 00E356F31AD99517003FC87E /* ZingoMobileTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -444,7 +444,7 @@ files = ( 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */, DB4DE518264B103E0084F17D /* RPCModule.m in Sources */, - 1F7D32202B71D55600D2879C /* Reachability.m in Sources */, + 1F7D32272B73DF3800D2879C /* Reachability.m in Sources */, 13B07FC11A68108700A75B9A /* main.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/ios/ZingoMobile/Reachability.h b/ios/ZingoMobile/Reachability.h new file mode 100644 index 000000000..73883c35b --- /dev/null +++ b/ios/ZingoMobile/Reachability.h @@ -0,0 +1,103 @@ +/* + Copyright (c) 2011, Tony Million. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#import +#import + +//! Project version number for MacOSReachability. +FOUNDATION_EXPORT double ReachabilityVersionNumber; + +//! Project version string for MacOSReachability. +FOUNDATION_EXPORT const unsigned char ReachabilityVersionString[]; + +/** + * Create NS_ENUM macro if it does not exist on the targeted version of iOS or OS X. + * + * @see http://nshipster.com/ns_enum-ns_options/ + **/ +#ifndef NS_ENUM +#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type +#endif + +extern NSString *const kReachabilityChangedNotification; + +typedef NS_ENUM(NSInteger, NetworkStatus) { + // Apple NetworkStatus Compatible Names. + NotReachable = 0, + ReachableViaWiFi = 2, + ReachableViaWWAN = 1 +}; + +@class Reachability; + +typedef void (^NetworkReachable)(Reachability * reachability); +typedef void (^NetworkUnreachable)(Reachability * reachability); +typedef void (^NetworkReachability)(Reachability * reachability, SCNetworkConnectionFlags flags); + + +@interface Reachability : NSObject + +@property (nonatomic, copy) NetworkReachable reachableBlock; +@property (nonatomic, copy) NetworkUnreachable unreachableBlock; +@property (nonatomic, copy) NetworkReachability reachabilityBlock; + +@property (nonatomic, assign) BOOL reachableOnWWAN; + + ++(instancetype)reachabilityWithHostname:(NSString*)hostname; +// This is identical to the function above, but is here to maintain +//compatibility with Apples original code. (see .m) ++(instancetype)reachabilityWithHostName:(NSString*)hostname; ++(instancetype)reachabilityForInternetConnection; ++(instancetype)reachabilityWithAddress:(void *)hostAddress; ++(instancetype)reachabilityForLocalWiFi; ++(instancetype)reachabilityWithURL:(NSURL*)url; + +-(instancetype)initWithReachabilityRef:(SCNetworkReachabilityRef)ref; + +-(BOOL)startNotifier; +-(void)stopNotifier; + +-(BOOL)isReachable; +-(BOOL)isReachableViaWWAN; +-(BOOL)isReachableViaWiFi; + +// WWAN may be available, but not active until a connection has been established. +// WiFi may require a connection for VPN on Demand. +-(BOOL)isConnectionRequired; // Identical DDG variant. +-(BOOL)connectionRequired; // Apple's routine. +// Dynamic, on demand connection? +-(BOOL)isConnectionOnDemand; +// Is user intervention required? +-(BOOL)isInterventionRequired; + +-(NetworkStatus)currentReachabilityStatus; +-(SCNetworkReachabilityFlags)reachabilityFlags; +-(NSString*)currentReachabilityString; +-(NSString*)currentReachabilityFlags; + +@end diff --git a/ios/ZingoMobile/Reachability.m b/ios/ZingoMobile/Reachability.m new file mode 100644 index 000000000..5324390d9 --- /dev/null +++ b/ios/ZingoMobile/Reachability.m @@ -0,0 +1,508 @@ +/* + Copyright (c) 2011, Tony Million. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#import "Reachability.h" + +#import +#import +#import +#import +#import +#import + + +NSString *const kReachabilityChangedNotification = @"kReachabilityChangedNotification"; + + +@interface Reachability () + +@property (nonatomic, assign) SCNetworkReachabilityRef reachabilityRef; +@property (nonatomic, strong) dispatch_queue_t reachabilitySerialQueue; +@property (nonatomic, strong) id reachabilityObject; + +-(void)reachabilityChanged:(SCNetworkReachabilityFlags)flags; +-(BOOL)isReachableWithFlags:(SCNetworkReachabilityFlags)flags; + +@end + + +static NSString *reachabilityFlags(SCNetworkReachabilityFlags flags) +{ + return [NSString stringWithFormat:@"%c%c %c%c%c%c%c%c%c", +#if TARGET_OS_IPHONE + (flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-', +#else + 'X', +#endif + (flags & kSCNetworkReachabilityFlagsReachable) ? 'R' : '-', + (flags & kSCNetworkReachabilityFlagsConnectionRequired) ? 'c' : '-', + (flags & kSCNetworkReachabilityFlagsTransientConnection) ? 't' : '-', + (flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-', + (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ? 'C' : '-', + (flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ? 'D' : '-', + (flags & kSCNetworkReachabilityFlagsIsLocalAddress) ? 'l' : '-', + (flags & kSCNetworkReachabilityFlagsIsDirect) ? 'd' : '-']; +} + +// Start listening for reachability notifications on the current run loop +static void TMReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info) +{ +#pragma unused (target) + + Reachability *reachability = ((__bridge Reachability*)info); + + // We probably don't need an autoreleasepool here, as GCD docs state each queue has its own autorelease pool, + // but what the heck eh? + @autoreleasepool + { + [reachability reachabilityChanged:flags]; + } +} + + +@implementation Reachability + +#pragma mark - Class Constructor Methods + ++(instancetype)reachabilityWithHostName:(NSString*)hostname +{ + return [Reachability reachabilityWithHostname:hostname]; +} + ++(instancetype)reachabilityWithHostname:(NSString*)hostname +{ + SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithName(NULL, [hostname UTF8String]); + if (ref) + { + id reachability = [[self alloc] initWithReachabilityRef:ref]; + + return reachability; + } + + return nil; +} + ++(instancetype)reachabilityWithAddress:(void *)hostAddress +{ + SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)hostAddress); + if (ref) + { + id reachability = [[self alloc] initWithReachabilityRef:ref]; + + return reachability; + } + + return nil; +} + ++(instancetype)reachabilityForInternetConnection +{ + struct sockaddr_in zeroAddress; + bzero(&zeroAddress, sizeof(zeroAddress)); + zeroAddress.sin_len = sizeof(zeroAddress); + zeroAddress.sin_family = AF_INET; + + return [self reachabilityWithAddress:&zeroAddress]; +} + ++(instancetype)reachabilityForLocalWiFi +{ + struct sockaddr_in localWifiAddress; + bzero(&localWifiAddress, sizeof(localWifiAddress)); + localWifiAddress.sin_len = sizeof(localWifiAddress); + localWifiAddress.sin_family = AF_INET; + // IN_LINKLOCALNETNUM is defined in as 169.254.0.0 + localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM); + + return [self reachabilityWithAddress:&localWifiAddress]; +} + ++(instancetype)reachabilityWithURL:(NSURL*)url +{ + id reachability; + + NSString *host = url.host; + BOOL isIpAddress = [self isIpAddress:host]; + + if (isIpAddress) + { + NSNumber *port = url.port ?: [url.scheme isEqualToString:@"https"] ? @(443) : @(80); + + struct sockaddr_in address; + address.sin_len = sizeof(address); + address.sin_family = AF_INET; + address.sin_port = htons([port intValue]); + address.sin_addr.s_addr = inet_addr([host UTF8String]); + + reachability = [self reachabilityWithAddress:&address]; + } + else + { + reachability = [self reachabilityWithHostname:host]; + } + + return reachability; +} + ++(BOOL)isIpAddress:(NSString*)host +{ + struct in_addr pin; + return 1 == inet_aton([host UTF8String], &pin); +} + + +// Initialization methods + +-(instancetype)initWithReachabilityRef:(SCNetworkReachabilityRef)ref +{ + self = [super init]; + if (self != nil) + { + self.reachableOnWWAN = YES; + self.reachabilityRef = ref; + + // We need to create a serial queue. + // We allocate this once for the lifetime of the notifier. + + self.reachabilitySerialQueue = dispatch_queue_create("com.tonymillion.reachability", NULL); + } + + return self; +} + +-(void)dealloc +{ + [self stopNotifier]; + + if(self.reachabilityRef) + { + CFRelease(self.reachabilityRef); + self.reachabilityRef = nil; + } + + self.reachableBlock = nil; + self.unreachableBlock = nil; + self.reachabilityBlock = nil; + self.reachabilitySerialQueue = nil; +} + +#pragma mark - Notifier Methods + +// Notifier +// NOTE: This uses GCD to trigger the blocks - they *WILL NOT* be called on THE MAIN THREAD +// - In other words DO NOT DO ANY UI UPDATES IN THE BLOCKS. +// INSTEAD USE dispatch_async(dispatch_get_main_queue(), ^{UISTUFF}) (or dispatch_sync if you want) + +-(BOOL)startNotifier +{ + // allow start notifier to be called multiple times + if(self.reachabilityObject && (self.reachabilityObject == self)) + { + return YES; + } + + + SCNetworkReachabilityContext context = { 0, NULL, NULL, NULL, NULL }; + context.info = (__bridge void *)self; + + if(SCNetworkReachabilitySetCallback(self.reachabilityRef, TMReachabilityCallback, &context)) + { + // Set it as our reachability queue, which will retain the queue + if(SCNetworkReachabilitySetDispatchQueue(self.reachabilityRef, self.reachabilitySerialQueue)) + { + // this should do a retain on ourself, so as long as we're in notifier mode we shouldn't disappear out from under ourselves + // woah + self.reachabilityObject = self; + return YES; + } + else + { +#ifdef DEBUG + NSLog(@"SCNetworkReachabilitySetDispatchQueue() failed: %s", SCErrorString(SCError())); +#endif + + // UH OH - FAILURE - stop any callbacks! + SCNetworkReachabilitySetCallback(self.reachabilityRef, NULL, NULL); + } + } + else + { +#ifdef DEBUG + NSLog(@"SCNetworkReachabilitySetCallback() failed: %s", SCErrorString(SCError())); +#endif + } + + // if we get here we fail at the internet + self.reachabilityObject = nil; + return NO; +} + +-(void)stopNotifier +{ + // First stop, any callbacks! + SCNetworkReachabilitySetCallback(self.reachabilityRef, NULL, NULL); + + // Unregister target from the GCD serial dispatch queue. + SCNetworkReachabilitySetDispatchQueue(self.reachabilityRef, NULL); + + self.reachabilityObject = nil; +} + +#pragma mark - reachability tests + +// This is for the case where you flick the airplane mode; +// you end up getting something like this: +//Reachability: WR ct----- +//Reachability: -- ------- +//Reachability: WR ct----- +//Reachability: -- ------- +// We treat this as 4 UNREACHABLE triggers - really apple should do better than this + +#define testcase (kSCNetworkReachabilityFlagsConnectionRequired | kSCNetworkReachabilityFlagsTransientConnection) + +-(BOOL)isReachableWithFlags:(SCNetworkReachabilityFlags)flags +{ + BOOL connectionUP = YES; + + if(!(flags & kSCNetworkReachabilityFlagsReachable)) + connectionUP = NO; + + if( (flags & testcase) == testcase ) + connectionUP = NO; + +#if TARGET_OS_IPHONE + if(flags & kSCNetworkReachabilityFlagsIsWWAN) + { + // We're on 3G. + if(!self.reachableOnWWAN) + { + // We don't want to connect when on 3G. + connectionUP = NO; + } + } +#endif + + return connectionUP; +} + +-(BOOL)isReachable +{ + SCNetworkReachabilityFlags flags; + + if(!SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags)) + return NO; + + return [self isReachableWithFlags:flags]; +} + +-(BOOL)isReachableViaWWAN +{ +#if TARGET_OS_IPHONE + + SCNetworkReachabilityFlags flags = 0; + + if(SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags)) + { + // Check we're REACHABLE + if(flags & kSCNetworkReachabilityFlagsReachable) + { + // Now, check we're on WWAN + if(flags & kSCNetworkReachabilityFlagsIsWWAN) + { + return YES; + } + } + } +#endif + + return NO; +} + +-(BOOL)isReachableViaWiFi +{ + SCNetworkReachabilityFlags flags = 0; + + if(SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags)) + { + // Check we're reachable + if((flags & kSCNetworkReachabilityFlagsReachable)) + { +#if TARGET_OS_IPHONE + // Check we're NOT on WWAN + if((flags & kSCNetworkReachabilityFlagsIsWWAN)) + { + return NO; + } +#endif + return YES; + } + } + + return NO; +} + + +// WWAN may be available, but not active until a connection has been established. +// WiFi may require a connection for VPN on Demand. +-(BOOL)isConnectionRequired +{ + return [self connectionRequired]; +} + +-(BOOL)connectionRequired +{ + SCNetworkReachabilityFlags flags; + + if(SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags)) + { + return (flags & kSCNetworkReachabilityFlagsConnectionRequired); + } + + return NO; +} + +// Dynamic, on demand connection? +-(BOOL)isConnectionOnDemand +{ + SCNetworkReachabilityFlags flags; + + if (SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags)) + { + return ((flags & kSCNetworkReachabilityFlagsConnectionRequired) && + (flags & (kSCNetworkReachabilityFlagsConnectionOnTraffic | kSCNetworkReachabilityFlagsConnectionOnDemand))); + } + + return NO; +} + +// Is user intervention required? +-(BOOL)isInterventionRequired +{ + SCNetworkReachabilityFlags flags; + + if (SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags)) + { + return ((flags & kSCNetworkReachabilityFlagsConnectionRequired) && + (flags & kSCNetworkReachabilityFlagsInterventionRequired)); + } + + return NO; +} + + +#pragma mark - reachability status stuff + +-(NetworkStatus)currentReachabilityStatus +{ + if([self isReachable]) + { + if([self isReachableViaWiFi]) + return ReachableViaWiFi; + +#if TARGET_OS_IPHONE + return ReachableViaWWAN; +#endif + } + + return NotReachable; +} + +-(SCNetworkReachabilityFlags)reachabilityFlags +{ + SCNetworkReachabilityFlags flags = 0; + + if(SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags)) + { + return flags; + } + + return 0; +} + +-(NSString*)currentReachabilityString +{ + NetworkStatus temp = [self currentReachabilityStatus]; + + if(temp == ReachableViaWWAN) + { + // Updated for the fact that we have CDMA phones now! + return NSLocalizedString(@"Cellular", @""); + } + if (temp == ReachableViaWiFi) + { + return NSLocalizedString(@"WiFi", @""); + } + + return NSLocalizedString(@"No Connection", @""); +} + +-(NSString*)currentReachabilityFlags +{ + return reachabilityFlags([self reachabilityFlags]); +} + +#pragma mark - Callback function calls this method + +-(void)reachabilityChanged:(SCNetworkReachabilityFlags)flags +{ + if([self isReachableWithFlags:flags]) + { + if(self.reachableBlock) + { + self.reachableBlock(self); + } + } + else + { + if(self.unreachableBlock) + { + self.unreachableBlock(self); + } + } + + if(self.reachabilityBlock) + { + self.reachabilityBlock(self, flags); + } + + // this makes sure the change notification happens on the MAIN THREAD + dispatch_async(dispatch_get_main_queue(), ^{ + [[NSNotificationCenter defaultCenter] postNotificationName:kReachabilityChangedNotification + object:self]; + }); +} + +#pragma mark - Debug Description + +- (NSString *) description +{ + NSString *description = [NSString stringWithFormat:@"<%@: %p (%@)>", + NSStringFromClass([self class]), self, [self currentReachabilityFlags]]; + return description; +} + +@end From d648635f326acbd2dca06f760afcabee8d9171fa Mon Sep 17 00:00:00 2001 From: Juan Carlos Carmona Calvo Date: Wed, 7 Feb 2024 12:59:49 -0700 Subject: [PATCH 08/17] fix: last version updated --- ios/ZingoMobile/AppDelegate.m | 104 ++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 49 deletions(-) diff --git a/ios/ZingoMobile/AppDelegate.m b/ios/ZingoMobile/AppDelegate.m index 5f407bfb0..f8bd35327 100644 --- a/ios/ZingoMobile/AppDelegate.m +++ b/ios/ZingoMobile/AppDelegate.m @@ -30,19 +30,11 @@ static void InitializeFlipper(UIApplication *application) { #endif @implementation AppDelegate -static BOOL _syncFinished = true; - -+ (BOOL)syncFinished { - return _syncFinished; -} - -+ (void)setSyncFinished:(BOOL)newSyncFinished { - _syncFinished = newSyncFinished; -} static NSString* syncTask = @"Zingo_Processing_Task_ID"; static NSString* syncSchedulerTask = @"Zingo_Processing_Scheduler_Task_ID"; static BOOL isConnectedToWifi = false; +static BOOL syncFinished = true; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { @@ -63,8 +55,10 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( self.window.rootViewController = rootViewController; [self.window makeKeyAndVisible]; - NSLog(@"BGTask handle background task"); - [self handleBackgroundTask]; + if (@available(iOS 13.0, *)) { + NSLog(@"BGTask handle background task"); + [self handleBackgroundTask]; + } return YES; } @@ -93,24 +87,30 @@ - (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull N restorationHandler:restorationHandler]; } -- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions -{ - if (@available(iOS 13.0, *)) { - //NSLog(@"configureProcessingTask"); - //[self configureProcessingTask]; - } - return YES; -} +//- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions +//{ +// if (@available(iOS 13.0, *)) { +// NSLog(@"configureProcessingTask"); +// [self configureProcessingTask]; +// } +// return YES; +//} - (void)applicationWillEnterForeground:(UIApplication *)application { - // cancel existing task (if any) - NSLog(@"BGTask scheduleProcessingTask CANCEL - foreground"); - [self setSyncFinished:true]; - char *resp2 = execute("interrupt_sync_after_batch", "true"); - NSString* respStr2 = [NSString stringWithUTF8String:resp2]; - NSLog(@"BGTask interrupt syncing %@", respStr2); - [BGTaskScheduler.sharedScheduler cancelTaskRequestWithIdentifier:syncTask]; + if (@available(iOS 13.0, *)) { + // cancel existing sync process + NSLog(@"BGTask sync finished %i", syncFinished); + if (!syncFinished) { + NSLog(@"BGTask scheduleProcessingTask CANCEL - foreground"); + syncFinished = true; + char *resp2 = execute("interrupt_sync_after_batch", "true"); + NSString* respStr2 = [NSString stringWithUTF8String:resp2]; + NSLog(@"BGTask interrupt syncing %@", respStr2); + } + // cancel the task (if any) + [BGTaskScheduler.sharedScheduler cancelTaskRequestWithIdentifier:syncTask]; + } } - (void)applicationDidEnterBackground:(UIApplication *)application @@ -147,16 +147,16 @@ -(void)syncingProcessBackgroundTask:(NSString *)noValue { if (exists) { - NSLog(@"BGTask handleProcessingTask sync begin"); - [self setSyncFinished:false]; + NSLog(@"BGTask handleProcessingTask sync BEGIN"); + //syncFinished = false; char *resp2 = execute("sync", ""); NSString* respStr2 = [NSString stringWithUTF8String:resp2]; rust_free(resp2); - NSLog(@"BGTask handleProcessingTask sync end %@", respStr2); + NSLog(@"BGTask handleProcessingTask sync END %@", respStr2); - [self setSyncFinished:true]; + syncFinished = true; char *resp3 = execute("interrupt_sync_after_batch", "true"); NSString* respStr3 = [NSString stringWithUTF8String:resp3]; NSLog(@"BGTask interrupt syncing %@", respStr3); @@ -164,7 +164,7 @@ -(void)syncingProcessBackgroundTask:(NSString *)noValue { } else { - [self setSyncFinished:true]; + syncFinished = true; NSLog(@"BGTask handleProcessingTask No exists wallet"); } @@ -176,15 +176,15 @@ -(void)syncingProcessBackgroundTask:(NSString *)noValue { -(void)syncingStatusProcessBackgroundTask:(NSString *)noValue { @autoreleasepool { - NSLog(@"BGTask handleProcessingTask sync status begin %i", self.syncFinished); + NSLog(@"BGTask handleProcessingTask sync status BEGIN %i", syncFinished); NSInteger prevBatch = -1; - while(!self.syncFinished) { + while(!syncFinished) { [NSThread sleepForTimeInterval: 2.0]; char *resp = execute("syncstatus", ""); NSString* respStr = [NSString stringWithUTF8String:resp]; rust_free(resp); - NSLog(@"BGTask handleProcessingTask sync status response %i %@", self.syncFinished, respStr); + NSLog(@"BGTask handleProcessingTask sync status response %i %@", syncFinished, respStr); NSData *data = [respStr dataUsingEncoding:NSUTF8StringEncoding]; id jsonResp = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; @@ -192,7 +192,7 @@ -(void)syncingStatusProcessBackgroundTask:(NSString *)noValue { NSInteger batch = [batchStr integerValue]; BOOL progress = [jsonResp valueForKey:@"in_progress"]; - NSLog(@"BGTask handleProcessingTask batch number %i %@", self.syncFinished, batchStr); + NSLog(@"BGTask handleProcessingTask batch number %i %@", syncFinished, batchStr); if (prevBatch != -1 && batch > 0 && prevBatch != batch) { // save the wallet @@ -207,11 +207,13 @@ -(void)syncingStatusProcessBackgroundTask:(NSString *)noValue { NSString *jsonBackgroud = [NSString stringWithFormat: @"%@%@%@%@%@", @"{\"batches\": \"", batchStr, @"\", \"date\": \"", timeStampStr, @"\"}"]; [rpcmodule saveBackgroundFile:jsonBackgroud]; - NSLog(@"BGTask handleProcessingTask save wallet & background batch %i %@ %i %@", self.syncFinished, batchStr, progress, timeStampStr); + NSLog(@"BGTask handleProcessingTask save wallet & background batch %i %@ %i %@", syncFinished, batchStr, progress, timeStampStr); } prevBatch = batch; } + NSLog(@"BGTask handleProcessingTask sync status END %i", syncFinished); + // we don't want to save if the sync is finished: // 1. OS kill the task -> to save is dangerous. // 2. When the App go to foreground -> same. @@ -259,7 +261,7 @@ -(void)scheduleProcessingTask_old { } } -// NEW BACKGROUND SCHEDULING TASK +// NEW BACKGROUND SCHEDULING TASKS - (void)handleBackgroundTask { // We require the background task to run when connected to the power and wifi @@ -318,17 +320,21 @@ - (void)startBackgroundTask:(BGProcessingTask *)task { // Start the syncing NSLog(@"BGTask configureProcessingTask run"); + syncFinished = false; [NSThread detachNewThreadSelector:@selector(syncingProcessBackgroundTask:) toTarget:self withObject:nil]; [self syncingStatusProcessBackgroundTask:nil]; + [task setTaskCompletedWithSuccess:YES]; task.expirationHandler = ^{ NSLog(@"BGTask startBackgroundTask expirationHandler called"); // Stop the syncing because the allocated time is about to expire - NSLog(@"BGTask scheduleProcessingTask CANCEL - is about to expire"); - [self setSyncFinished:true]; - char *resp2 = execute("interrupt_sync_after_batch", "true"); - NSString* respStr2 = [NSString stringWithUTF8String:resp2]; - NSLog(@"BGTask interrupt syncing %@", respStr2); + if (!syncFinished) { + NSLog(@"BGTask scheduleProcessingTask CANCEL - is about to expire"); + syncFinished = true; + char *resp2 = execute("interrupt_sync_after_batch", "true"); + NSString* respStr2 = [NSString stringWithUTF8String:resp2]; + NSLog(@"BGTask interrupt syncing %@", respStr2); + } }; } @@ -349,12 +355,12 @@ - (void)scheduleBackgroundTask { NSDate *earlyMorning = [[NSCalendar currentCalendar] dateByAddingComponents:earlyMorningComponent toDate:tomorrow options:0]; // DEVELOPMENT - //NSDate *now = [NSDate date]; + NSDate *now = [NSDate date]; - //NSDate *twoMinutesLater = [now dateByAddingTimeInterval:120]; // 2 minutes = 120 seconds + NSDate *twoMinutesLater = [now dateByAddingTimeInterval:120]; // 2 minutes = 120 seconds - request.earliestBeginDate = earlyMorning; - //request.earliestBeginDate = twoMinutesLater; + //request.earliestBeginDate = earlyMorning; + request.earliestBeginDate = twoMinutesLater; request.requiresExternalPower = YES; request.requiresNetworkConnectivity = YES; @@ -384,12 +390,12 @@ - (void)scheduleSchedulerBackgroundTask { NSDate *afternoon = [[NSCalendar currentCalendar] dateByAddingComponents:afternoonComponent toDate:tomorrow options:0]; // DEVELOPMENT - //NSDate *now = [NSDate date]; + NSDate *now = [NSDate date]; - //NSDate *twoMinutesLater = [now dateByAddingTimeInterval:120]; // 2 minutes = 120 seconds + NSDate *fiveMinutesLater = [now dateByAddingTimeInterval:300]; // 5 minutes = 300 seconds request.earliestBeginDate = afternoon; - //request.earliestBeginDate = twoMinutesLater; + //request.earliestBeginDate = fiveMinutesLater; request.requiresExternalPower = NO; request.requiresNetworkConnectivity = NO; From d4816f933968896b3f589346a3c0c82fed7bf330 Mon Sep 17 00:00:00 2001 From: Juan Carlos Carmona Calvo Date: Thu, 8 Feb 2024 10:40:14 -0700 Subject: [PATCH 09/17] fix: making work expirationHandler - no luck --- app/LoadedApp/LoadedApp.tsx | 2 + ios/ZingoMobile/AppDelegate.m | 83 +++++++++++++++++------------------ 2 files changed, 42 insertions(+), 43 deletions(-) diff --git a/app/LoadedApp/LoadedApp.tsx b/app/LoadedApp/LoadedApp.tsx index 9707effca..8a9617cb8 100644 --- a/app/LoadedApp/LoadedApp.tsx +++ b/app/LoadedApp/LoadedApp.tsx @@ -298,6 +298,8 @@ export class LoadedAppClass extends Component { if (this.state.appState.match(/inactive|background/) && nextAppState === 'active') { //console.log('App has come to the foreground!'); + // deactivate the interruption sync flag + await RPC.rpc_setInterruptSyncAfterBatch('false'); // reading background task info if (Platform.OS === 'ios') { // this file only exists in IOS BS. diff --git a/ios/ZingoMobile/AppDelegate.m b/ios/ZingoMobile/AppDelegate.m index f8bd35327..98e27b874 100644 --- a/ios/ZingoMobile/AppDelegate.m +++ b/ios/ZingoMobile/AppDelegate.m @@ -87,31 +87,21 @@ - (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull N restorationHandler:restorationHandler]; } -//- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions +//- (void)applicationWillEnterForeground:(UIApplication *)application //{ -// if (@available(iOS 13.0, *)) { -// NSLog(@"configureProcessingTask"); -// [self configureProcessingTask]; -// } -// return YES; -//} - -- (void)applicationWillEnterForeground:(UIApplication *)application -{ - if (@available(iOS 13.0, *)) { - // cancel existing sync process - NSLog(@"BGTask sync finished %i", syncFinished); - if (!syncFinished) { - NSLog(@"BGTask scheduleProcessingTask CANCEL - foreground"); - syncFinished = true; - char *resp2 = execute("interrupt_sync_after_batch", "true"); - NSString* respStr2 = [NSString stringWithUTF8String:resp2]; - NSLog(@"BGTask interrupt syncing %@", respStr2); - } + //if (@available(iOS 13.0, *)) { + // cancel existing sync background process. + // if (!syncFinished) { + // NSLog(@"BGTask scheduleProcessingTask CANCEL - foreground"); + // syncFinished = true; + // char *resp2 = execute("interrupt_sync_after_batch", "true"); + // NSString* respStr2 = [NSString stringWithUTF8String:resp2]; + // NSLog(@"BGTask interrupt syncing %@", respStr2); + // } // cancel the task (if any) - [BGTaskScheduler.sharedScheduler cancelTaskRequestWithIdentifier:syncTask]; - } -} + // [BGTaskScheduler.sharedScheduler cancelTaskRequestWithIdentifier:syncTask]; + //} +//} - (void)applicationDidEnterBackground:(UIApplication *)application { @@ -120,7 +110,6 @@ - (void)applicationDidEnterBackground:(UIApplication *)application [self scheduleBackgroundTask]; NSLog(@"BGTask scheduleShedulerBackgroundTask"); [self scheduleSchedulerBackgroundTask]; - //[self handleBackgroundTask]; } } @@ -148,8 +137,17 @@ -(void)syncingProcessBackgroundTask:(NSString *)noValue { if (exists) { NSLog(@"BGTask handleProcessingTask sync BEGIN"); - //syncFinished = false; + syncFinished = false; + // we need to sync without interruption, I run this just in case + char *resp = execute("interrupt_sync_after_batch", "false"); + NSString* respStr = [NSString stringWithUTF8String:resp]; + NSLog(@"BGTask interrupt syncing %@", respStr); + rust_free(resp); + + // the task is running here blocking this execution until this process finished: + // 1. finished the syncing. + // 2. interrupted by a flag then it finished the current batch. char *resp2 = execute("sync", ""); NSString* respStr2 = [NSString stringWithUTF8String:resp2]; rust_free(resp2); @@ -157,15 +155,12 @@ -(void)syncingProcessBackgroundTask:(NSString *)noValue { NSLog(@"BGTask handleProcessingTask sync END %@", respStr2); syncFinished = true; - char *resp3 = execute("interrupt_sync_after_batch", "true"); - NSString* respStr3 = [NSString stringWithUTF8String:resp3]; - NSLog(@"BGTask interrupt syncing %@", respStr3); // the execute `sync` already save the wallet when finished } else { syncFinished = true; - NSLog(@"BGTask handleProcessingTask No exists wallet"); + NSLog(@"BGTask handleProcessingTask No exists wallet file"); } @@ -173,7 +168,7 @@ -(void)syncingProcessBackgroundTask:(NSString *)noValue { } --(void)syncingStatusProcessBackgroundTask:(NSString *)noValue { +-(void)syncingStatusProcessBackgroundTask:(BGProcessingTask *)task { @autoreleasepool { NSLog(@"BGTask handleProcessingTask sync status BEGIN %i", syncFinished); @@ -208,12 +203,17 @@ -(void)syncingStatusProcessBackgroundTask:(NSString *)noValue { [rpcmodule saveBackgroundFile:jsonBackgroud]; NSLog(@"BGTask handleProcessingTask save wallet & background batch %i %@ %i %@", syncFinished, batchStr, progress, timeStampStr); + NSLog(@"TIME REMAINING ======= %f", [UIApplication sharedApplication].backgroundTimeRemaining); } prevBatch = batch; + } NSLog(@"BGTask handleProcessingTask sync status END %i", syncFinished); + // I need to end the Task ASAP + [task setTaskCompletedWithSuccess:YES]; + // we don't want to save if the sync is finished: // 1. OS kill the task -> to save is dangerous. // 2. When the App go to foreground -> same. @@ -231,7 +231,6 @@ -(BOOL)wallet__exists { NSString *fileName = [NSString stringWithFormat:@"%@/wallet.dat.txt", documentsDirectory]; BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:fileName]; - // RCTLogInfo(@"Wallet exists: %d", (int)fileExists); if (fileExists) { return true; @@ -322,19 +321,17 @@ - (void)startBackgroundTask:(BGProcessingTask *)task { NSLog(@"BGTask configureProcessingTask run"); syncFinished = false; [NSThread detachNewThreadSelector:@selector(syncingProcessBackgroundTask:) toTarget:self withObject:nil]; - [self syncingStatusProcessBackgroundTask:nil]; - [task setTaskCompletedWithSuccess:YES]; - + [self syncingStatusProcessBackgroundTask:task]; + task.expirationHandler = ^{ NSLog(@"BGTask startBackgroundTask expirationHandler called"); // Stop the syncing because the allocated time is about to expire - if (!syncFinished) { - NSLog(@"BGTask scheduleProcessingTask CANCEL - is about to expire"); - syncFinished = true; - char *resp2 = execute("interrupt_sync_after_batch", "true"); - NSString* respStr2 = [NSString stringWithUTF8String:resp2]; - NSLog(@"BGTask interrupt syncing %@", respStr2); - } + NSLog(@"BGTask scheduleProcessingTask CANCEL - is about to expire"); + char *resp2 = execute("interrupt_sync_after_batch", "true"); + NSString* respStr2 = [NSString stringWithUTF8String:resp2]; + NSLog(@"BGTask interrupt syncing %@", respStr2); + // maybe I don't need this, because the interrupt command is going to end the sync process ASAP-ish. + syncFinished = true; }; } @@ -390,9 +387,9 @@ - (void)scheduleSchedulerBackgroundTask { NSDate *afternoon = [[NSCalendar currentCalendar] dateByAddingComponents:afternoonComponent toDate:tomorrow options:0]; // DEVELOPMENT - NSDate *now = [NSDate date]; + //NSDate *now = [NSDate date]; - NSDate *fiveMinutesLater = [now dateByAddingTimeInterval:300]; // 5 minutes = 300 seconds + //NSDate *fiveMinutesLater = [now dateByAddingTimeInterval:300]; // 5 minutes = 300 seconds request.earliestBeginDate = afternoon; //request.earliestBeginDate = fiveMinutesLater; From da6c6afbfa4bf1442402e038c8a47bcf0daee132 Mon Sep 17 00:00:00 2001 From: Juan Carlos Carmona Calvo Date: Thu, 8 Feb 2024 17:09:34 -0700 Subject: [PATCH 10/17] fix: BS working --- ios/ZingoMobile/AppDelegate.m | 70 ++++++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 18 deletions(-) diff --git a/ios/ZingoMobile/AppDelegate.m b/ios/ZingoMobile/AppDelegate.m index 98e27b874..da61ba540 100644 --- a/ios/ZingoMobile/AppDelegate.m +++ b/ios/ZingoMobile/AppDelegate.m @@ -35,6 +35,7 @@ @implementation AppDelegate static NSString* syncSchedulerTask = @"Zingo_Processing_Scheduler_Task_ID"; static BOOL isConnectedToWifi = false; static BOOL syncFinished = true; +static BGProcessingTask *bgTask = nil; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { @@ -87,28 +88,32 @@ - (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull N restorationHandler:restorationHandler]; } -//- (void)applicationWillEnterForeground:(UIApplication *)application -//{ - //if (@available(iOS 13.0, *)) { +- (void)applicationWillEnterForeground:(UIApplication *)application +{ + if (@available(iOS 13.0, *)) { // cancel existing sync background process. - // if (!syncFinished) { - // NSLog(@"BGTask scheduleProcessingTask CANCEL - foreground"); - // syncFinished = true; - // char *resp2 = execute("interrupt_sync_after_batch", "true"); - // NSString* respStr2 = [NSString stringWithUTF8String:resp2]; - // NSLog(@"BGTask interrupt syncing %@", respStr2); - // } - // cancel the task (if any) - // [BGTaskScheduler.sharedScheduler cancelTaskRequestWithIdentifier:syncTask]; - //} -//} + if (!syncFinished) { + NSLog(@"BGTask scheduleProcessingTask CANCEL - foreground"); + char *resp2 = execute("interrupt_sync_after_batch", "true"); + NSString* respStr2 = [NSString stringWithUTF8String:resp2]; + NSLog(@"BGTask interrupt syncing %@", respStr2); + syncFinished = true; + } + // cancel bg task + if ([bgTask isKindOfClass:[BGProcessingTask class]]) { + [bgTask setTaskCompletedWithSuccess:NO]; + } + } +} - (void)applicationDidEnterBackground:(UIApplication *)application { if (@available(iOS 13.0, *)) { + bgTask = nil; + syncFinished = true; NSLog(@"BGTask scheduleBackgroundTask"); [self scheduleBackgroundTask]; - NSLog(@"BGTask scheduleShedulerBackgroundTask"); + NSLog(@"BGTask scheduleSchedulerBackgroundTask"); [self scheduleSchedulerBackgroundTask]; } } @@ -173,9 +178,29 @@ -(void)syncingStatusProcessBackgroundTask:(BGProcessingTask *)task { NSLog(@"BGTask handleProcessingTask sync status BEGIN %i", syncFinished); NSInteger prevBatch = -1; + NSLog(@"Time Remaining: %f", [[UIApplication sharedApplication] backgroundTimeRemaining]); + //NSInteger time = [[UIApplication sharedApplication] backgroundTimeRemaining]; + + // when this `time remaing` is cracy big, something wrong in happening. + // in my testing this time is always something like 300 seconds. (the famous 5 min). + + if ([UIApplication sharedApplication].backgroundTimeRemaining > 1000000) { + //time = 290; + // I prefer to end the task directly, and wait for the next scheduled task. + char *resp2 = execute("interrupt_sync_after_batch", "true"); + NSString* respStr2 = [NSString stringWithUTF8String:resp2]; + NSLog(@"BGTask interrupt syncing %@", respStr2); + syncFinished = true; + // waiting for sync finish + [NSThread sleepForTimeInterval: 5.0]; + [task setTaskCompletedWithSuccess:NO]; + return; + } while(!syncFinished) { [NSThread sleepForTimeInterval: 2.0]; + // sleep for 2 seconds before to check the status. 0.1 seconds of running. + //time = time - 1.9; char *resp = execute("syncstatus", ""); NSString* respStr = [NSString stringWithUTF8String:resp]; rust_free(resp); @@ -206,7 +231,14 @@ -(void)syncingStatusProcessBackgroundTask:(BGProcessingTask *)task { NSLog(@"TIME REMAINING ======= %f", [UIApplication sharedApplication].backgroundTimeRemaining); } prevBatch = batch; - + if ([UIApplication sharedApplication].backgroundTimeRemaining < 10) { + char *resp2 = execute("interrupt_sync_after_batch", "true"); + NSString* respStr2 = [NSString stringWithUTF8String:resp2]; + NSLog(@"BGTask interrupt syncing %@", respStr2); + } + if ([UIApplication sharedApplication].backgroundTimeRemaining < 5) { + syncFinished = true; + } } NSLog(@"BGTask handleProcessingTask sync status END %i", syncFinished); @@ -284,6 +316,7 @@ - (void)registerTasks { return; } NSLog(@"BGTask BGTaskScheduler.shared.register SYNC called"); + bgTask = (BGProcessingTask *)task; [self startBackgroundTask:(BGProcessingTask *)task]; }]; @@ -303,7 +336,6 @@ - (void)registerTasks { NSLog(@"BGTask SCHEDULER registered %d", bcgSchedulerTaskResult); } - - (void)startBackgroundTask:(BGProcessingTask *)task { NSLog(@"BGTask startBackgroundTask called"); @@ -321,8 +353,9 @@ - (void)startBackgroundTask:(BGProcessingTask *)task { NSLog(@"BGTask configureProcessingTask run"); syncFinished = false; [NSThread detachNewThreadSelector:@selector(syncingProcessBackgroundTask:) toTarget:self withObject:nil]; - [self syncingStatusProcessBackgroundTask:task]; + [self syncingStatusProcessBackgroundTask:(BGProcessingTask *)task]; + __weak BGTask* weakTask = task; task.expirationHandler = ^{ NSLog(@"BGTask startBackgroundTask expirationHandler called"); // Stop the syncing because the allocated time is about to expire @@ -332,6 +365,7 @@ - (void)startBackgroundTask:(BGProcessingTask *)task { NSLog(@"BGTask interrupt syncing %@", respStr2); // maybe I don't need this, because the interrupt command is going to end the sync process ASAP-ish. syncFinished = true; + [weakTask setTaskCompletedWithSuccess:NO]; }; } From 721f831fd518e82689aa305a38d5021c3538f245 Mon Sep 17 00:00:00 2001 From: Juan Carlos Carmona Calvo Date: Fri, 9 Feb 2024 15:58:05 -0700 Subject: [PATCH 11/17] fix: removing batches number from legend in Sync Report Screen --- app/translations/en.json | 2 +- app/translations/es.json | 2 +- components/SyncReport/SyncReport.tsx | 5 ++--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/app/translations/en.json b/app/translations/en.json index 2cdf17bc2..51f8f30b6 100644 --- a/app/translations/en.json +++ b/app/translations/en.json @@ -416,7 +416,7 @@ "processingblock": "Processing Block: ", "totalblocks": " of a TOTAL of Blocks: ", "lastbackgroundsync": "LAST BACKGROUND SYNCING", - "batches-date": " Batches at: ", + "batches-date": "Date: ", "networkstatus": "Network Status (Internet)", "nointernet": "No Internet Connection.", "cellulardata": "Only Cellular Data.", diff --git a/app/translations/es.json b/app/translations/es.json index ff15d6d7d..11725c3fa 100644 --- a/app/translations/es.json +++ b/app/translations/es.json @@ -416,7 +416,7 @@ "processingblock": "Procesando Bloque: ", "totalblocks": " de un TOTAL de Bloques: ", "lastbackgroundsync": "ULTIMA SINCRONIZACION EN SEGUNDO PLANO", - "batches-date": " Lotes en: ", + "batches-date": "Fecha: ", "networkstatus": "Estado de la Red (Internet)", "nointernet": "Sin conexión a Internet.", "cellulardata": "Usando solo Datos del Móvil.", diff --git a/components/SyncReport/SyncReport.tsx b/components/SyncReport/SyncReport.tsx index 8cde557fa..ac44c9176 100644 --- a/components/SyncReport/SyncReport.tsx +++ b/components/SyncReport/SyncReport.tsx @@ -49,7 +49,7 @@ const SyncReport: React.FunctionComponent = ({ closeModal }) => useEffect(() => { (async () => await RPC.rpc_setInterruptSyncAfterBatch('false'))(); - setTimeout(() => setShowBackgroundLegend(false), 5000); // 5 seconds only + setTimeout(() => setShowBackgroundLegend(false), 10000); // 10 seconds only }, []); // ref: https://github.com/zingolabs/zingo-mobile/issues/327 @@ -219,7 +219,7 @@ const SyncReport: React.FunctionComponent = ({ closeModal }) => /> )} - {background.batches > 0 && background.date > 0 && showBackgroundLegend && ( + {background.date > 0 && showBackgroundLegend && ( = ({ closeModal }) => Date: Sat, 10 Feb 2024 10:33:06 -0700 Subject: [PATCH 12/17] fix: IOS BS working for 300 secs & between 310 and 330 batches every night at 3 am with power & wifi --- ios/ZingoMobile/AppDelegate.m | 142 ++++++++++++++-------------------- 1 file changed, 57 insertions(+), 85 deletions(-) diff --git a/ios/ZingoMobile/AppDelegate.m b/ios/ZingoMobile/AppDelegate.m index da61ba540..03efff8e2 100644 --- a/ios/ZingoMobile/AppDelegate.m +++ b/ios/ZingoMobile/AppDelegate.m @@ -45,7 +45,7 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge - moduleName:@"Zingo!" + moduleName:@"Zingo!" initialProperties:nil]; rootView.backgroundColor = [[UIColor alloc] initWithRed:0.0f green:0.0f blue:0.0f alpha:1]; @@ -93,24 +93,26 @@ - (void)applicationWillEnterForeground:(UIApplication *)application if (@available(iOS 13.0, *)) { // cancel existing sync background process. if (!syncFinished) { - NSLog(@"BGTask scheduleProcessingTask CANCEL - foreground"); + NSLog(@"BGTask sync CANCEL - go to foreground"); char *resp2 = execute("interrupt_sync_after_batch", "true"); NSString* respStr2 = [NSString stringWithUTF8String:resp2]; - NSLog(@"BGTask interrupt syncing %@", respStr2); - syncFinished = true; + NSLog(@"BGTask foreground interrupt syncing %@", respStr2); } + syncFinished = true; // cancel bg task - if ([bgTask isKindOfClass:[BGProcessingTask class]]) { + if ([bgTask isKindOfClass:[BGTask class]]) { + NSLog(@"BGTask task CANCEL - go to foreground"); [bgTask setTaskCompletedWithSuccess:NO]; } + bgTask = nil; } } - (void)applicationDidEnterBackground:(UIApplication *)application { if (@available(iOS 13.0, *)) { - bgTask = nil; syncFinished = true; + bgTask = nil; NSLog(@"BGTask scheduleBackgroundTask"); [self scheduleBackgroundTask]; NSLog(@"BGTask scheduleSchedulerBackgroundTask"); @@ -118,54 +120,42 @@ - (void)applicationDidEnterBackground:(UIApplication *)application } } --(void)configureProcessingTask_old { - if (@available(iOS 13.0, *)) { - [[BGTaskScheduler sharedScheduler] registerForTaskWithIdentifier:syncTask - usingQueue:nil - launchHandler:^(BGTask *task) { - NSLog(@"configureProcessingTask run"); - [NSThread detachNewThreadSelector:@selector(syncingProcessBackgroundTask:) toTarget:self withObject:nil]; - [self syncingStatusProcessBackgroundTask:nil]; - - }]; - } else { - // No fallback - } -} -(void)syncingProcessBackgroundTask:(NSString *)noValue { //do things with task @autoreleasepool { + syncFinished = false; + BOOL exists = [self wallet__exists]; if (exists) { - NSLog(@"BGTask handleProcessingTask sync BEGIN"); - syncFinished = false; - // we need to sync without interruption, I run this just in case char *resp = execute("interrupt_sync_after_batch", "false"); NSString* respStr = [NSString stringWithUTF8String:resp]; - NSLog(@"BGTask interrupt syncing %@", respStr); + NSLog(@"BGTask syncingProcessBackgroundTask no interrupt syncing %@", respStr); rust_free(resp); // the task is running here blocking this execution until this process finished: // 1. finished the syncing. // 2. interrupted by a flag then it finished the current batch. + + NSLog(@"BGTask syncingProcessBackgroundTask sync BEGIN"); + char *resp2 = execute("sync", ""); NSString* respStr2 = [NSString stringWithUTF8String:resp2]; rust_free(resp2); - NSLog(@"BGTask handleProcessingTask sync END %@", respStr2); + NSLog(@"BGTask syncingProcessBackgroundTask sync END %@", respStr2); syncFinished = true; - // the execute `sync` already save the wallet when finished } else { - + + NSLog(@"BGTask syncingProcessBackgroundTask No exists wallet file END"); + syncFinished = true; - NSLog(@"BGTask handleProcessingTask No exists wallet file"); } @@ -173,38 +163,33 @@ -(void)syncingProcessBackgroundTask:(NSString *)noValue { } --(void)syncingStatusProcessBackgroundTask:(BGProcessingTask *)task { +-(void)syncingStatusProcessBackgroundTask:(NSString *)noValue { @autoreleasepool { - NSLog(@"BGTask handleProcessingTask sync status BEGIN %i", syncFinished); + NSLog(@"BGTask syncingStatusProcessBackgroundTask sync status BEGIN"); NSInteger prevBatch = -1; NSLog(@"Time Remaining: %f", [[UIApplication sharedApplication] backgroundTimeRemaining]); - //NSInteger time = [[UIApplication sharedApplication] backgroundTimeRemaining]; - // when this `time remaing` is cracy big, something wrong in happening. + // when this `time remaing` is cracy big, something wrong is happening. // in my testing this time is always something like 300 seconds. (the famous 5 min). if ([UIApplication sharedApplication].backgroundTimeRemaining > 1000000) { - //time = 290; // I prefer to end the task directly, and wait for the next scheduled task. char *resp2 = execute("interrupt_sync_after_batch", "true"); NSString* respStr2 = [NSString stringWithUTF8String:resp2]; - NSLog(@"BGTask interrupt syncing %@", respStr2); + NSLog(@"BGTask syncingStatusProcessBackgroundTask interrupt syncing %@", respStr2); syncFinished = true; - // waiting for sync finish - [NSThread sleepForTimeInterval: 5.0]; - [task setTaskCompletedWithSuccess:NO]; + [bgTask setTaskCompletedWithSuccess:NO]; + bgTask = nil; return; } while(!syncFinished) { [NSThread sleepForTimeInterval: 2.0]; - // sleep for 2 seconds before to check the status. 0.1 seconds of running. - //time = time - 1.9; char *resp = execute("syncstatus", ""); NSString* respStr = [NSString stringWithUTF8String:resp]; rust_free(resp); - NSLog(@"BGTask handleProcessingTask sync status response %i %@", syncFinished, respStr); + NSLog(@"BGTask syncingStatusProcessBackgroundTask sync status response %@", respStr); NSData *data = [respStr dataUsingEncoding:NSUTF8StringEncoding]; id jsonResp = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; @@ -212,7 +197,7 @@ -(void)syncingStatusProcessBackgroundTask:(BGProcessingTask *)task { NSInteger batch = [batchStr integerValue]; BOOL progress = [jsonResp valueForKey:@"in_progress"]; - NSLog(@"BGTask handleProcessingTask batch number %i %@", syncFinished, batchStr); + NSLog(@"BGTask syncingStatusProcessBackgroundTask batch number %@", batchStr); if (prevBatch != -1 && batch > 0 && prevBatch != batch) { // save the wallet @@ -227,25 +212,28 @@ -(void)syncingStatusProcessBackgroundTask:(BGProcessingTask *)task { NSString *jsonBackgroud = [NSString stringWithFormat: @"%@%@%@%@%@", @"{\"batches\": \"", batchStr, @"\", \"date\": \"", timeStampStr, @"\"}"]; [rpcmodule saveBackgroundFile:jsonBackgroud]; - NSLog(@"BGTask handleProcessingTask save wallet & background batch %i %@ %i %@", syncFinished, batchStr, progress, timeStampStr); + NSLog(@"BGTask syncingStatusProcessBackgroundTask save wallet & background batch %@ progress %i", batchStr, progress); NSLog(@"TIME REMAINING ======= %f", [UIApplication sharedApplication].backgroundTimeRemaining); } prevBatch = batch; if ([UIApplication sharedApplication].backgroundTimeRemaining < 10) { + NSLog(@"BGTask syncingStatusProcessBackgroundTask less than 10 secs"); char *resp2 = execute("interrupt_sync_after_batch", "true"); NSString* respStr2 = [NSString stringWithUTF8String:resp2]; - NSLog(@"BGTask interrupt syncing %@", respStr2); + NSLog(@"BGTask syncingStatusProcessBackgroundTask interrupt syncing %@", respStr2); } if ([UIApplication sharedApplication].backgroundTimeRemaining < 5) { + NSLog(@"BGTask syncingStatusProcessBackgroundTask less than 5 secs"); syncFinished = true; } } - NSLog(@"BGTask handleProcessingTask sync status END %i", syncFinished); + NSLog(@"BGTask syncingStatusProcessBackgroundTask sync status END %i", syncFinished); // I need to end the Task ASAP - [task setTaskCompletedWithSuccess:YES]; - + [bgTask setTaskCompletedWithSuccess:YES]; + bgTask = nil; + // we don't want to save if the sync is finished: // 1. OS kill the task -> to save is dangerous. // 2. When the App go to foreground -> same. @@ -271,27 +259,6 @@ -(BOOL)wallet__exists { } } --(void)scheduleProcessingTask_old { - if (@available(iOS 13.0, *)) { - NSLog(@"schedulingProcessingTask"); - NSError *error = NULL; - // cancel existing task (if any) - [BGTaskScheduler.sharedScheduler cancelTaskRequestWithIdentifier:syncTask]; - // new task - BGProcessingTaskRequest *request = [[BGProcessingTaskRequest alloc] initWithIdentifier:syncTask]; - request.requiresNetworkConnectivity = YES; - request.earliestBeginDate = nil; - BOOL success = [[BGTaskScheduler sharedScheduler] submitTaskRequest:request error:&error]; - if (!success) { - NSLog(@"Failed to submit request: %@", error); - } else { - NSLog(@"Success submit request %@", request); - } - } else { - // No fallback - } -} - // NEW BACKGROUND SCHEDULING TASKS - (void)handleBackgroundTask { @@ -311,20 +278,22 @@ - (void)handleBackgroundTask { - (void)registerTasks { BOOL bcgSyncTaskResult; - bcgSyncTaskResult = [[BGTaskScheduler sharedScheduler] registerForTaskWithIdentifier:syncTask usingQueue:dispatch_get_main_queue() launchHandler:^(BGTask * _Nonnull task) { - if (![task isKindOfClass:[BGProcessingTask class]]) { + bcgSyncTaskResult = [[BGTaskScheduler sharedScheduler] registerForTaskWithIdentifier:syncTask usingQueue:dispatch_get_main_queue() + launchHandler:^(BGTask *task) { + if (![task isKindOfClass:[BGTask class]]) { return; } NSLog(@"BGTask BGTaskScheduler.shared.register SYNC called"); bgTask = (BGProcessingTask *)task; - [self startBackgroundTask:(BGProcessingTask *)task]; + [self startBackgroundTask:nil]; }]; NSLog(@"BGTask SYNC registered %d", bcgSyncTaskResult); BOOL bcgSchedulerTaskResult; - bcgSchedulerTaskResult = [[BGTaskScheduler sharedScheduler] registerForTaskWithIdentifier:syncSchedulerTask usingQueue:dispatch_get_main_queue() launchHandler:^(BGTask * _Nonnull task) { - if (![task isKindOfClass:[BGProcessingTask class]]) { + bcgSchedulerTaskResult = [[BGTaskScheduler sharedScheduler] registerForTaskWithIdentifier:syncSchedulerTask usingQueue:dispatch_get_main_queue() + launchHandler:^(BGTask *task) { + if (![task isKindOfClass:[BGTask class]]) { return; } NSLog(@"BGTask BGTaskScheduler.shared.register SCHEDULER called"); @@ -336,7 +305,7 @@ - (void)registerTasks { NSLog(@"BGTask SCHEDULER registered %d", bcgSchedulerTaskResult); } -- (void)startBackgroundTask:(BGProcessingTask *)task { +- (void)startBackgroundTask:(NSString *)noValue { NSLog(@"BGTask startBackgroundTask called"); // Schedule tasks for the next time @@ -345,27 +314,30 @@ - (void)startBackgroundTask:(BGProcessingTask *)task { if (!isConnectedToWifi) { NSLog(@"BGTask startBackgroundTask: not connected to the wifi"); - [task setTaskCompletedWithSuccess:NO]; + [bgTask setTaskCompletedWithSuccess:NO]; + bgTask = nil; return; } // Start the syncing - NSLog(@"BGTask configureProcessingTask run"); + NSLog(@"BGTask startBackgroundTask run sync task"); syncFinished = false; [NSThread detachNewThreadSelector:@selector(syncingProcessBackgroundTask:) toTarget:self withObject:nil]; - [self syncingStatusProcessBackgroundTask:(BGProcessingTask *)task]; + [self syncingStatusProcessBackgroundTask:nil]; - __weak BGTask* weakTask = task; - task.expirationHandler = ^{ + // this trigger doesn't work, but if in some point works + // it finish the task properly. + __weak BGTask* weakTask = bgTask; + bgTask.expirationHandler = ^{ NSLog(@"BGTask startBackgroundTask expirationHandler called"); // Stop the syncing because the allocated time is about to expire - NSLog(@"BGTask scheduleProcessingTask CANCEL - is about to expire"); + NSLog(@"BGTask startBackgroundTask CANCEL - is about to expire"); char *resp2 = execute("interrupt_sync_after_batch", "true"); NSString* respStr2 = [NSString stringWithUTF8String:resp2]; - NSLog(@"BGTask interrupt syncing %@", respStr2); - // maybe I don't need this, because the interrupt command is going to end the sync process ASAP-ish. + NSLog(@"BGTask startBackgroundTask interrupt syncing %@", respStr2); syncFinished = true; [weakTask setTaskCompletedWithSuccess:NO]; + bgTask = nil; }; } @@ -386,12 +358,12 @@ - (void)scheduleBackgroundTask { NSDate *earlyMorning = [[NSCalendar currentCalendar] dateByAddingComponents:earlyMorningComponent toDate:tomorrow options:0]; // DEVELOPMENT - NSDate *now = [NSDate date]; + //NSDate *now = [NSDate date]; - NSDate *twoMinutesLater = [now dateByAddingTimeInterval:120]; // 2 minutes = 120 seconds + //NSDate *twoMinutesLater = [now dateByAddingTimeInterval:120]; // 2 minutes = 120 seconds - //request.earliestBeginDate = earlyMorning; - request.earliestBeginDate = twoMinutesLater; + request.earliestBeginDate = earlyMorning; + //request.earliestBeginDate = twoMinutesLater; request.requiresExternalPower = YES; request.requiresNetworkConnectivity = YES; From 5279d1283ecbacf8b601f4fc2b29f92beda5f980 Mon Sep 17 00:00:00 2001 From: Juan Carlos Carmona Calvo Date: Sat, 10 Feb 2024 13:29:40 -0700 Subject: [PATCH 13/17] fix: IOS BS working --- ios/ZingoMobile/AppDelegate.m | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/ios/ZingoMobile/AppDelegate.m b/ios/ZingoMobile/AppDelegate.m index 03efff8e2..b4aa57135 100644 --- a/ios/ZingoMobile/AppDelegate.m +++ b/ios/ZingoMobile/AppDelegate.m @@ -112,6 +112,11 @@ - (void)applicationDidEnterBackground:(UIApplication *)application { if (@available(iOS 13.0, *)) { syncFinished = true; + // cancel bg task (if any) + if ([bgTask isKindOfClass:[BGTask class]]) { + NSLog(@"BGTask task CANCEL - go to foreground"); + [bgTask setTaskCompletedWithSuccess:NO]; + } bgTask = nil; NSLog(@"BGTask scheduleBackgroundTask"); [self scheduleBackgroundTask]; @@ -168,21 +173,6 @@ -(void)syncingStatusProcessBackgroundTask:(NSString *)noValue { NSLog(@"BGTask syncingStatusProcessBackgroundTask sync status BEGIN"); NSInteger prevBatch = -1; - NSLog(@"Time Remaining: %f", [[UIApplication sharedApplication] backgroundTimeRemaining]); - - // when this `time remaing` is cracy big, something wrong is happening. - // in my testing this time is always something like 300 seconds. (the famous 5 min). - - if ([UIApplication sharedApplication].backgroundTimeRemaining > 1000000) { - // I prefer to end the task directly, and wait for the next scheduled task. - char *resp2 = execute("interrupt_sync_after_batch", "true"); - NSString* respStr2 = [NSString stringWithUTF8String:resp2]; - NSLog(@"BGTask syncingStatusProcessBackgroundTask interrupt syncing %@", respStr2); - syncFinished = true; - [bgTask setTaskCompletedWithSuccess:NO]; - bgTask = nil; - return; - } while(!syncFinished) { [NSThread sleepForTimeInterval: 2.0]; @@ -318,6 +308,17 @@ - (void)startBackgroundTask:(NSString *)noValue { bgTask = nil; return; } + + // I can check the time remaining here & make a choice + // when this `time remaing` is cracy big, something wrong is happening. + // in my testing this time is always something like 300 seconds. (the famous 5 min). + NSLog(@"BEFORE RUN TASKS - Time Remaining: %f", [[UIApplication sharedApplication] backgroundTimeRemaining]); + if ([[UIApplication sharedApplication] backgroundTimeRemaining] > 1000000000) { + NSLog(@"BGTask startBackgroundTask: time remainig TOO cracy high %f", [[UIApplication sharedApplication] backgroundTimeRemaining]); + [bgTask setTaskCompletedWithSuccess:NO]; + bgTask = nil; + return; + } // Start the syncing NSLog(@"BGTask startBackgroundTask run sync task"); From b68caa74754a227f39b457b904f7f5ff4f6314ab Mon Sep 17 00:00:00 2001 From: Juan Carlos Carmona Calvo Date: Sat, 10 Feb 2024 15:51:18 -0700 Subject: [PATCH 14/17] fix: reverting remove batches from sync report screen --- app/translations/en.json | 2 +- app/translations/es.json | 2 +- components/SyncReport/SyncReport.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/translations/en.json b/app/translations/en.json index 51f8f30b6..2cdf17bc2 100644 --- a/app/translations/en.json +++ b/app/translations/en.json @@ -416,7 +416,7 @@ "processingblock": "Processing Block: ", "totalblocks": " of a TOTAL of Blocks: ", "lastbackgroundsync": "LAST BACKGROUND SYNCING", - "batches-date": "Date: ", + "batches-date": " Batches at: ", "networkstatus": "Network Status (Internet)", "nointernet": "No Internet Connection.", "cellulardata": "Only Cellular Data.", diff --git a/app/translations/es.json b/app/translations/es.json index 11725c3fa..ff15d6d7d 100644 --- a/app/translations/es.json +++ b/app/translations/es.json @@ -416,7 +416,7 @@ "processingblock": "Procesando Bloque: ", "totalblocks": " de un TOTAL de Bloques: ", "lastbackgroundsync": "ULTIMA SINCRONIZACION EN SEGUNDO PLANO", - "batches-date": "Fecha: ", + "batches-date": " Lotes en: ", "networkstatus": "Estado de la Red (Internet)", "nointernet": "Sin conexión a Internet.", "cellulardata": "Usando solo Datos del Móvil.", diff --git a/components/SyncReport/SyncReport.tsx b/components/SyncReport/SyncReport.tsx index ac44c9176..aa48cb316 100644 --- a/components/SyncReport/SyncReport.tsx +++ b/components/SyncReport/SyncReport.tsx @@ -219,7 +219,7 @@ const SyncReport: React.FunctionComponent = ({ closeModal }) => /> )} - {background.date > 0 && showBackgroundLegend && ( + {background.batches > 0 && background.date > 0 && showBackgroundLegend && ( Date: Mon, 12 Feb 2024 12:36:50 -0700 Subject: [PATCH 15/17] fix: reverting sync report screen - num batches --- components/SyncReport/SyncReport.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/components/SyncReport/SyncReport.tsx b/components/SyncReport/SyncReport.tsx index aa48cb316..571387bb1 100644 --- a/components/SyncReport/SyncReport.tsx +++ b/components/SyncReport/SyncReport.tsx @@ -230,6 +230,7 @@ const SyncReport: React.FunctionComponent = ({ closeModal }) => Date: Tue, 13 Feb 2024 09:20:41 -0700 Subject: [PATCH 16/17] fix: expirationHandler working --- components/SyncReport/SyncReport.tsx | 6 +- ios/ZingoMobile/AppDelegate.m | 207 +++++++++++++-------------- 2 files changed, 102 insertions(+), 111 deletions(-) diff --git a/components/SyncReport/SyncReport.tsx b/components/SyncReport/SyncReport.tsx index 571387bb1..99b3e3ec8 100644 --- a/components/SyncReport/SyncReport.tsx +++ b/components/SyncReport/SyncReport.tsx @@ -219,7 +219,7 @@ const SyncReport: React.FunctionComponent = ({ closeModal }) => /> )} - {background.batches > 0 && background.date > 0 && showBackgroundLegend && ( + {background.date > 0 && showBackgroundLegend && ( = ({ closeModal }) => diff --git a/ios/ZingoMobile/AppDelegate.m b/ios/ZingoMobile/AppDelegate.m index b4aa57135..ab84b41eb 100644 --- a/ios/ZingoMobile/AppDelegate.m +++ b/ios/ZingoMobile/AppDelegate.m @@ -34,7 +34,6 @@ @implementation AppDelegate static NSString* syncTask = @"Zingo_Processing_Task_ID"; static NSString* syncSchedulerTask = @"Zingo_Processing_Scheduler_Task_ID"; static BOOL isConnectedToWifi = false; -static BOOL syncFinished = true; static BGProcessingTask *bgTask = nil; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions @@ -57,7 +56,7 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( [self.window makeKeyAndVisible]; if (@available(iOS 13.0, *)) { - NSLog(@"BGTask handle background task"); + NSLog(@"BGTask handleBackgroundTask"); [self handleBackgroundTask]; } @@ -91,145 +90,124 @@ - (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull N - (void)applicationWillEnterForeground:(UIApplication *)application { if (@available(iOS 13.0, *)) { - // cancel existing sync background process. - if (!syncFinished) { - NSLog(@"BGTask sync CANCEL - go to foreground"); - char *resp2 = execute("interrupt_sync_after_batch", "true"); - NSString* respStr2 = [NSString stringWithUTF8String:resp2]; - NSLog(@"BGTask foreground interrupt syncing %@", respStr2); - } - syncFinished = true; + // cancel existing sync process (if any). + NSLog(@"BGTask foreground"); + [self stopSyncingProcess:nil]; + // cancel bg task if ([bgTask isKindOfClass:[BGTask class]]) { - NSLog(@"BGTask task CANCEL - go to foreground"); - [bgTask setTaskCompletedWithSuccess:NO]; - } - bgTask = nil; + NSLog(@"BGTask foreground - sync task CANCEL"); + [bgTask setTaskCompletedWithSuccess:NO]; + } + bgTask = nil; } } - (void)applicationDidEnterBackground:(UIApplication *)application { if (@available(iOS 13.0, *)) { - syncFinished = true; - // cancel bg task (if any) + // cancel existing sync process (if any). + NSLog(@"BGTask background"); + [self stopSyncingProcess:nil]; + + // cancel bg task if ([bgTask isKindOfClass:[BGTask class]]) { - NSLog(@"BGTask task CANCEL - go to foreground"); + NSLog(@"BGTask background - sync task CANCEL"); [bgTask setTaskCompletedWithSuccess:NO]; } bgTask = nil; - NSLog(@"BGTask scheduleBackgroundTask"); + + NSLog(@"BGTask background - scheduleBackgroundTask"); [self scheduleBackgroundTask]; - NSLog(@"BGTask scheduleSchedulerBackgroundTask"); + NSLog(@"BGTask background - scheduleSchedulerBackgroundTask"); [self scheduleSchedulerBackgroundTask]; } } +-(void)stopSyncingProcess:(NSString *)noValue { + // if the in_progress from syncstatus is true + // there is a sync progress running somehow + // we need to stop it and the only tool I have is + // using the `interrupting` sync flag... + // and waiting for the end. + @autoreleasepool { + + NSLog(@"BGTask stopSyncingProcess"); + char *resp = execute("syncstatus", ""); + NSString* respStr = [NSString stringWithUTF8String:resp]; + rust_free(resp); + NSLog(@"BGTask stopSyncingProcess - status response %@", respStr); + + NSData *data = [respStr dataUsingEncoding:NSUTF8StringEncoding]; + id jsonResp = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; + NSString *inProgressStr = [jsonResp valueForKey:@"in_progress"]; + BOOL inProgress = [inProgressStr boolValue]; + + while(inProgress) { + char *resp2 = execute("interrupt_sync_after_batch", "true"); + NSString* respStr2 = [NSString stringWithUTF8String:resp2]; + NSLog(@"BGTask stopSyncingProcess - interrupt syncing %@", respStr2); + + [NSThread sleepForTimeInterval: 0.5]; + + char *resp = execute("syncstatus", ""); + NSString* respStr = [NSString stringWithUTF8String:resp]; + rust_free(resp); + NSLog(@"BGTask stopSyncingProcess - status response %@", respStr); + + NSData *data = [respStr dataUsingEncoding:NSUTF8StringEncoding]; + id jsonResp = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; + NSString *inProgressStr = [jsonResp valueForKey:@"in_progress"]; + inProgress = [inProgressStr boolValue]; + } + + NSLog(@"BGTask stopSyncingProcess - syncing process STOPPED"); + + } + +} -(void)syncingProcessBackgroundTask:(NSString *)noValue { //do things with task @autoreleasepool { - - syncFinished = false; + NSLog(@"BGTask syncingProcessBackgroundTask"); BOOL exists = [self wallet__exists]; if (exists) { + // stop syncing first, just in case. + [self stopSyncingProcess:nil]; // we need to sync without interruption, I run this just in case char *resp = execute("interrupt_sync_after_batch", "false"); NSString* respStr = [NSString stringWithUTF8String:resp]; - NSLog(@"BGTask syncingProcessBackgroundTask no interrupt syncing %@", respStr); + NSLog(@"BGTask syncingProcessBackgroundTask - no interrupt syncing %@", respStr); rust_free(resp); // the task is running here blocking this execution until this process finished: // 1. finished the syncing. // 2. interrupted by a flag then it finished the current batch. - NSLog(@"BGTask syncingProcessBackgroundTask sync BEGIN"); + NSLog(@"BGTask syncingProcessBackgroundTask - sync BEGIN"); char *resp2 = execute("sync", ""); NSString* respStr2 = [NSString stringWithUTF8String:resp2]; rust_free(resp2); - NSLog(@"BGTask syncingProcessBackgroundTask sync END %@", respStr2); - - syncFinished = true; + NSLog(@"BGTask syncingProcessBackgroundTask - sync END %@", respStr2); } else { - NSLog(@"BGTask syncingProcessBackgroundTask No exists wallet file END"); - - syncFinished = true; + NSLog(@"BGTask syncingProcessBackgroundTask - No exists wallet file END"); } } -} - --(void)syncingStatusProcessBackgroundTask:(NSString *)noValue { - @autoreleasepool { - - NSLog(@"BGTask syncingStatusProcessBackgroundTask sync status BEGIN"); - NSInteger prevBatch = -1; - - while(!syncFinished) { - [NSThread sleepForTimeInterval: 2.0]; - char *resp = execute("syncstatus", ""); - NSString* respStr = [NSString stringWithUTF8String:resp]; - rust_free(resp); - NSLog(@"BGTask syncingStatusProcessBackgroundTask sync status response %@", respStr); - - NSData *data = [respStr dataUsingEncoding:NSUTF8StringEncoding]; - id jsonResp = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; - NSString *batchStr = [jsonResp valueForKey:@"batch_num"]; - NSInteger batch = [batchStr integerValue]; - BOOL progress = [jsonResp valueForKey:@"in_progress"]; - - NSLog(@"BGTask syncingStatusProcessBackgroundTask batch number %@", batchStr); - - if (prevBatch != -1 && batch > 0 && prevBatch != batch) { - // save the wallet - RPCModule *rpcmodule = [RPCModule new]; - [rpcmodule saveWalletInternal]; - - // save info in background json - NSTimeInterval timeStamp = [[NSDate date] timeIntervalSince1970]; - // NSTimeInterval is defined as double - NSNumber *timeStampObj = [NSNumber numberWithDouble: timeStamp]; - NSString *timeStampStr = [timeStampObj stringValue]; - NSString *jsonBackgroud = [NSString stringWithFormat: @"%@%@%@%@%@", @"{\"batches\": \"", batchStr, @"\", \"date\": \"", timeStampStr, @"\"}"]; - [rpcmodule saveBackgroundFile:jsonBackgroud]; + NSLog(@"BGTask syncingProcessBackgroundTask - syncing task STOPPED"); + [bgTask setTaskCompletedWithSuccess:YES]; + bgTask = nil; - NSLog(@"BGTask syncingStatusProcessBackgroundTask save wallet & background batch %@ progress %i", batchStr, progress); - NSLog(@"TIME REMAINING ======= %f", [UIApplication sharedApplication].backgroundTimeRemaining); - } - prevBatch = batch; - if ([UIApplication sharedApplication].backgroundTimeRemaining < 10) { - NSLog(@"BGTask syncingStatusProcessBackgroundTask less than 10 secs"); - char *resp2 = execute("interrupt_sync_after_batch", "true"); - NSString* respStr2 = [NSString stringWithUTF8String:resp2]; - NSLog(@"BGTask syncingStatusProcessBackgroundTask interrupt syncing %@", respStr2); - } - if ([UIApplication sharedApplication].backgroundTimeRemaining < 5) { - NSLog(@"BGTask syncingStatusProcessBackgroundTask less than 5 secs"); - syncFinished = true; - } - } - - NSLog(@"BGTask syncingStatusProcessBackgroundTask sync status END %i", syncFinished); - - // I need to end the Task ASAP - [bgTask setTaskCompletedWithSuccess:YES]; - bgTask = nil; - - // we don't want to save if the sync is finished: - // 1. OS kill the task -> to save is dangerous. - // 2. When the App go to foreground -> same. - // 3. If sync is finished -> the wallet is already saved. - - } } -(BOOL)wallet__exists { @@ -322,23 +300,36 @@ - (void)startBackgroundTask:(NSString *)noValue { // Start the syncing NSLog(@"BGTask startBackgroundTask run sync task"); - syncFinished = false; - [NSThread detachNewThreadSelector:@selector(syncingProcessBackgroundTask:) toTarget:self withObject:nil]; - [self syncingStatusProcessBackgroundTask:nil]; + // in order to run only one task + dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), ^{ + [self syncingProcessBackgroundTask:nil]; + }); - // this trigger doesn't work, but if in some point works - // it finish the task properly. - __weak BGTask* weakTask = bgTask; bgTask.expirationHandler = ^{ - NSLog(@"BGTask startBackgroundTask expirationHandler called"); - // Stop the syncing because the allocated time is about to expire - NSLog(@"BGTask startBackgroundTask CANCEL - is about to expire"); + NSLog(@"BGTask startBackgroundTask - expirationHandler called"); + // interrupting the sync process, I can't wait to see if the process is over + // because I have no time enough to run all of this task char *resp2 = execute("interrupt_sync_after_batch", "true"); NSString* respStr2 = [NSString stringWithUTF8String:resp2]; - NSLog(@"BGTask startBackgroundTask interrupt syncing %@", respStr2); - syncFinished = true; - [weakTask setTaskCompletedWithSuccess:NO]; + NSLog(@"BGTask startBackgroundTask - expirationHandler interrupt syncing %@", respStr2); + + // save the wallet + RPCModule *rpcmodule = [RPCModule new]; + [rpcmodule saveWalletInternal]; + NSLog(@"BGTask startBackgroundTask - expirationHandler Save Wallet"); + + // save info in background json + NSTimeInterval timeStamp = [[NSDate date] timeIntervalSince1970]; + // NSTimeInterval is defined as double + NSNumber *timeStampObj = [NSNumber numberWithDouble: timeStamp]; + NSString *timeStampStr = [timeStampObj stringValue]; + NSString *jsonBackgroud = [NSString stringWithFormat: @"%@%@%@%@%@", @"{\"batches\": \"", @"0", @"\", \"date\": \"", timeStampStr, @"\"}"]; + [rpcmodule saveBackgroundFile:jsonBackgroud]; + NSLog(@"BGTask startBackgroundTask - expirationHandler Save background JSON"); + + [bgTask setTaskCompletedWithSuccess:NO]; bgTask = nil; + NSLog(@"BGTask startBackgroundTask - expirationHandler THE END"); }; } @@ -359,12 +350,12 @@ - (void)scheduleBackgroundTask { NSDate *earlyMorning = [[NSCalendar currentCalendar] dateByAddingComponents:earlyMorningComponent toDate:tomorrow options:0]; // DEVELOPMENT - //NSDate *now = [NSDate date]; + NSDate *now = [NSDate date]; - //NSDate *twoMinutesLater = [now dateByAddingTimeInterval:120]; // 2 minutes = 120 seconds + NSDate *twoMinutesLater = [now dateByAddingTimeInterval:120]; // 2 minutes = 120 seconds - request.earliestBeginDate = earlyMorning; - //request.earliestBeginDate = twoMinutesLater; + //request.earliestBeginDate = earlyMorning; + request.earliestBeginDate = twoMinutesLater; request.requiresExternalPower = YES; request.requiresNetworkConnectivity = YES; From 5bae067bc1aa1ee613d695e650d1fd9d9a4f5044 Mon Sep 17 00:00:00 2001 From: Juan Carlos Carmona Calvo Date: Tue, 13 Feb 2024 09:32:58 -0700 Subject: [PATCH 17/17] fix: adjusting the task for 3:00 am --- ios/ZingoMobile/AppDelegate.m | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ios/ZingoMobile/AppDelegate.m b/ios/ZingoMobile/AppDelegate.m index ab84b41eb..3b0591408 100644 --- a/ios/ZingoMobile/AppDelegate.m +++ b/ios/ZingoMobile/AppDelegate.m @@ -308,7 +308,7 @@ - (void)startBackgroundTask:(NSString *)noValue { bgTask.expirationHandler = ^{ NSLog(@"BGTask startBackgroundTask - expirationHandler called"); // interrupting the sync process, I can't wait to see if the process is over - // because I have no time enough to run all of this task + // because I have no time enough to run all of this task here. char *resp2 = execute("interrupt_sync_after_batch", "true"); NSString* respStr2 = [NSString stringWithUTF8String:resp2]; NSLog(@"BGTask startBackgroundTask - expirationHandler interrupt syncing %@", respStr2); @@ -350,12 +350,12 @@ - (void)scheduleBackgroundTask { NSDate *earlyMorning = [[NSCalendar currentCalendar] dateByAddingComponents:earlyMorningComponent toDate:tomorrow options:0]; // DEVELOPMENT - NSDate *now = [NSDate date]; + //NSDate *now = [NSDate date]; - NSDate *twoMinutesLater = [now dateByAddingTimeInterval:120]; // 2 minutes = 120 seconds + //NSDate *twoMinutesLater = [now dateByAddingTimeInterval:120]; // 2 minutes = 120 seconds - //request.earliestBeginDate = earlyMorning; - request.earliestBeginDate = twoMinutesLater; + request.earliestBeginDate = earlyMorning; + //request.earliestBeginDate = twoMinutesLater; request.requiresExternalPower = YES; request.requiresNetworkConnectivity = YES;