diff --git a/CHANGELOG.md b/CHANGELOG.md index eb9cc26f..0b5e0451 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,16 +22,19 @@ All notable changes to this project will be documented in this file. ### Changed - Added Support for Setting device token before SDK initialization as well. -##Version - 1.2.2 - 2021-12-06 +## Version - 1.2.2 - 2021-12-06 ### Changed - Added logic to filter out the property which are not set for Application Opened event. ## Version - 1.3.0 - 2021-12-29 ### Additions -- Added support for additional background run time through configuration. +- Added support for additional background run time through configuration on iOS, tvOS. - Added watchOS as a supported platform. ## Version - 1.3.1 - 2021-12-30 ### Changed - Optimized the GDPR by removing the un-necessary checks in the life cycle events tracking code. +## Version - 1.4.0 - 2021-12-29 +### Additions +- Added support for additional background run time through configuration on watchOS as well along with iOS, tvOS. diff --git a/Podfile.lock b/Podfile.lock index b7245f7e..b4e0a204 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -79,7 +79,7 @@ PODS: - nanopb/encode (1.30906.0) - PromisesObjC (1.2.12) - Protobuf (3.19.1) - - Rudder (1.3.1) + - Rudder (1.4.0) DEPENDENCIES: - Firebase/Analytics diff --git a/README.md b/README.md index cd9f8a35..d4672bf9 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ The iOS SDK is available through [**CocoaPods**](https://cocoapods.org), [**Cart To install the SDK, simply add the following line to your Podfile: ```xcode -pod 'Rudder', '1.3.1' +pod 'Rudder', '1.4.0' ``` ### Carthage @@ -47,7 +47,7 @@ pod 'Rudder', '1.3.1' For Carthage support, add the following line to your `Cartfile`: ```xcode -github "rudderlabs/rudder-sdk-ios" "v1.3.1" +github "rudderlabs/rudder-sdk-ios" "v1.4.0" ``` > Remember to include the following code in all `.m` and `.h` files where you want to refer to or use the RudderStack SDK classes, as shown: @@ -71,7 +71,7 @@ You can also add the RudderStack iOS SDK via Swift Package Mangaer, via one of t * Enter the package repository (`git@github.com:rudderlabs/rudder-sdk-ios.git`) in the search bar. -* In **Dependency Rule**, select **Up to Next Major Version** and enter `1.3.1` as the value, as shown: +* In **Dependency Rule**, select **Up to Next Major Version** and enter `1.4.0` as the value, as shown: ![Setting dependency](https://user-images.githubusercontent.com/59817155/145574696-8c849749-13e0-40d5-aacb-3fccb5c8e67d.png) @@ -99,7 +99,7 @@ let package = Package( ], dependencies: [ // Dependencies declare other packages that this package depends on. - .package(url: "git@github.com:rudderlabs/rudder-sdk-ios.git", from: "1.3.1") + .package(url: "git@github.com:rudderlabs/rudder-sdk-ios.git", from: "1.4.0") ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. diff --git a/Rudder.podspec b/Rudder.podspec index 1cc68907..0cc50982 100644 --- a/Rudder.podspec +++ b/Rudder.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'Rudder' - s.version = "1.3.1" + s.version = "1.4.0" s.summary = "Privacy and Security focused Segment-alternative. iOS ,tvOS and watchOS SDK" s.description = <<-DESC Rudder is a platform for collecting, storing and routing customer event data to dozens of tools. Rudder is open-source, can run in your cloud environment (AWS, GCP, Azure or even your data-centre) and provides a powerful transformation framework to process your event data on the fly. diff --git a/Sources/Classes/Public/RSConfigBuilder.h b/Sources/Classes/Public/RSConfigBuilder.h index 82064d7e..0faab215 100644 --- a/Sources/Classes/Public/RSConfigBuilder.h +++ b/Sources/Classes/Public/RSConfigBuilder.h @@ -29,9 +29,7 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype) withConfigRefreshInteval: (int) configRefreshInterval; - (instancetype) withTrackLifecycleEvens: (BOOL) trackLifecycleEvents; - (instancetype) withRecordScreenViews: (BOOL) recordScreenViews; -#if !TARGET_OS_WATCH - (instancetype) withEnableBackgroundMode:(BOOL) enableBackgroundMode; -#endif - (instancetype) withConfigPlaneUrl: (NSString*) configPlaneUrl __attribute((deprecated("Use withControlPlaneUrl instead."))); - (instancetype) withControlPlaneUrl: (NSString*) controlPlaneUrl; - (instancetype) withControlPlaneURL: (NSURL*) controlPlaneURL; diff --git a/Sources/Classes/Public/RSEventRepository.h b/Sources/Classes/Public/RSEventRepository.h index b12f3597..5d818496 100644 --- a/Sources/Classes/Public/RSEventRepository.h +++ b/Sources/Classes/Public/RSEventRepository.h @@ -22,6 +22,8 @@ NS_ASSUME_NONNULL_BEGIN RSConfig* config; #if !TARGET_OS_WATCH UIBackgroundTaskIdentifier backgroundTask; +#else + dispatch_semaphore_t semaphore; #endif RSDBPersistentManager* dbpersistenceManager; RSServerConfigManager* configManager; @@ -31,6 +33,7 @@ NS_ASSUME_NONNULL_BEGIN RSPreferenceManager *preferenceManager; BOOL firstForeGround; BOOL areFactoriesInitialized; + BOOL isSemaphoreReleased; BOOL isSDKInitialized; BOOL isSDKEnabled; } diff --git a/Sources/Classes/RSConstants.m b/Sources/Classes/RSConstants.m index aa2ffeb4..801844ca 100644 --- a/Sources/Classes/RSConstants.m +++ b/Sources/Classes/RSConstants.m @@ -18,5 +18,5 @@ @implementation RSConstants bool const RSTrackLifeCycleEvents = YES; bool const RSRecordScreenViews = NO; bool const RSEnableBackgroundMode = NO; -NSString *const RS_VERSION = @"1.3.1"; +NSString *const RS_VERSION = @"1.4.0"; @end diff --git a/Sources/Classes/RSEventRepository.m b/Sources/Classes/RSEventRepository.m index 165a3527..a11d0720 100644 --- a/Sources/Classes/RSEventRepository.m +++ b/Sources/Classes/RSEventRepository.m @@ -52,15 +52,16 @@ - (instancetype)init : (NSString*) _writeKey config:(RSConfig*) _config { writeKey = _writeKey; config = _config; -#if !TARGET_OS_WATCH - if(config.enableBackgroundMode) - { + + if(config.enableBackgroundMode) { [RSLogger logDebug:@"EventRepository: Enabling Background Mode"]; +#if !TARGET_OS_WATCH backgroundTask = UIBackgroundTaskInvalid; [self registerBackGroundTask]; - } +#else + [self askForAssertionWithSemaphore]; #endif - + } NSData *authData = [[[NSString alloc] initWithFormat:@"%@:", _writeKey] dataUsingEncoding:NSUTF8StringEncoding]; authToken = [authData base64EncodedStringWithOptions:0]; [RSLogger logDebug:[[NSString alloc] initWithFormat:@"EventRepository: authToken: %@", authToken]]; @@ -570,11 +571,14 @@ - (void)_applicationWillEnterForeground { return; } #endif -#if !TARGET_OS_WATCH + if(config.enableBackgroundMode) { +#if !TARGET_OS_WATCH [self registerBackGroundTask]; - } +#else + [self askForAssertionWithSemaphore]; #endif + } if (!self->config.trackLifecycleEvents) { return; @@ -605,10 +609,10 @@ - (void) registerBackGroundTask { if(backgroundTask != UIBackgroundTaskInvalid) { [self endBackGroundTask]; } - [RSLogger logDebug:@"EventRepository: registerBackGroundTask: Registering for Background Mode"]; + [RSLogger logDebug:@"EventRepository: registerBackGroundTask: Registering for Background Mode"]; backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ [self endBackGroundTask]; - }]; + }]; } - (void) endBackGroundTask { @@ -616,6 +620,33 @@ - (void) endBackGroundTask { backgroundTask = UIBackgroundTaskInvalid; } +#else + +- (void) askForAssertionWithSemaphore { + if(self->semaphore == nil) { + self->semaphore = dispatch_semaphore_create(0); + } else if (!self->isSemaphoreReleased) { + [self releaseAssertionWithSemaphore]; + } + + NSProcessInfo *processInfo = [NSProcessInfo processInfo]; + [processInfo performExpiringActivityWithReason:@"backgroundRunTime" usingBlock:^(BOOL expired) { + if (expired) { + [self releaseAssertionWithSemaphore]; + self->isSemaphoreReleased = YES; + } else { + [RSLogger logDebug:@"EventRepository: askForAssertionWithSemaphore: Asking Semaphore for Assertion to wait forever for backgroundMode"]; + self->isSemaphoreReleased = NO; + dispatch_semaphore_wait(self->semaphore, DISPATCH_TIME_FOREVER); + } + }]; +} + +- (void) releaseAssertionWithSemaphore { + [RSLogger logDebug:@"EventRepository: releaseAssertionWithSemaphore: Releasing Assertion on Semaphore for backgroundMode"]; + dispatch_semaphore_signal(self->semaphore); +} + #endif @end