Skip to content

Commit fc1a997

Browse files
authored
Merge pull request #341 from Countly/server_config
feat: server config
2 parents 13d2caf + e5b41ff commit fc1a997

20 files changed

+571
-101
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
## XX.XX.XX
2+
* Extended server configuration capabilities of the SDK.
3+
14
## 25.1.1
25
* Removed Android v1 embedding support
36

android/src/main/java/ly/count/dart/countly_flutter/CountlyFlutterPlugin.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1636,6 +1636,11 @@ private void populateConfig(JSONObject _config) throws JSONException {
16361636
if (_config.has("starRatingTextDismiss")) {
16371637
this.config.setStarRatingTextDismiss(_config.getString("starRatingTextDismiss"));
16381638
}
1639+
1640+
if (_config.has("sdkBehaviorSettings")) {
1641+
this.config.setSDKBehaviorSettings(_config.getString("sdkBehaviorSettings"));
1642+
}
1643+
16391644
// APM ------------------------------------------------
16401645
if (_config.has("trackAppStartTime")) {
16411646
this.config.apm.enableAppStartTimeTracking();

ios/Classes/CountlyFlutterPlugin.m

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1644,6 +1644,11 @@ - (void)populateConfig:(NSDictionary *)_config {
16441644
[config.apm setAppStartTimestampOverride:[startTSOverride longLongValue]];
16451645
}
16461646

1647+
NSString *sdkBehaviorSettings = _config[@"sdkBehaviorSettings"];
1648+
if(sdkBehaviorSettings) {
1649+
config.sdkBehaviorSettings = sdkBehaviorSettings;
1650+
}
1651+
16471652
// Internal Limits ---------------------
16481653
NSNumber *maxKeyLength = _config[@"maxKeyLength"];
16491654
if (maxKeyLength) {

ios/Classes/CountlyiOS/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
## XX.XX.XX
2+
* Deprecated the experimental configuration function enableServerConfiguration and it will do nothing. It is now enabled by default and can be controlled directly from the server.
3+
4+
* Extended server configuration capabilities of the SDK.
5+
6+
## 25.1.2
7+
* Mitigated an issue where the safe area resolution was not correctly calculated for the content zone on certain iOS devices.
8+
19
## 25.1.1
210
* Mitigated an issue while setting zone timer interval for content.
311

ios/Classes/CountlyiOS/Countly.m

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ - (void)startWithConfig:(CountlyConfig *)config
9292

9393
config = [self checkAndFixInternalLimitsConfig:config];
9494

95+
[CountlyServerConfig.sharedInstance retrieveServerConfigFromStorage: config.serverConfiguration];
96+
9597
CountlyCommon.sharedInstance.maxKeyLength = config.sdkInternalLimits.getMaxKeyLength;
9698
CountlyCommon.sharedInstance.maxValueLength = config.sdkInternalLimits.getMaxValueSize;
9799
CountlyCommon.sharedInstance.maxSegmentationValues = config.sdkInternalLimits.getMaxSegmentationValues;
@@ -165,14 +167,8 @@ - (void)startWithConfig:(CountlyConfig *)config
165167
CountlyDeviceInfo.sharedInstance.customMetrics = [customMetricsTruncated cly_limited:@"Custom metric"];
166168

167169
[Countly.user save];
168-
169-
CountlyCommon.sharedInstance.enableServerConfiguration = config.enableServerConfiguration;
170-
171-
// Fetch server configs if 'enableServerConfiguration' is true.
172-
if (config.enableServerConfiguration)
173-
{
174-
[CountlyServerConfig.sharedInstance fetchServerConfig];
175-
}
170+
// If something added related to server config, make sure to check CountlyServerConfig.notifySdkConfigChange
171+
[CountlyServerConfig.sharedInstance fetchServerConfig: config];
176172

177173
#if (TARGET_OS_IOS)
178174
CountlyFeedbacksInternal.sharedInstance.message = config.starRatingMessage;
@@ -231,14 +227,20 @@ - (void)startWithConfig:(CountlyConfig *)config
231227
if ([config.features containsObject:CLYCrashReporting])
232228
{
233229
CountlyCrashReporter.sharedInstance.isEnabledOnInitialConfig = YES;
234-
[CountlyCrashReporter.sharedInstance startCrashReporting];
230+
231+
if (CountlyServerConfig.sharedInstance.crashReportingEnabled) {
232+
[CountlyCrashReporter.sharedInstance startCrashReporting];
233+
}
235234
}
236235

237236
#if (TARGET_OS_IOS || TARGET_OS_TV )
238237
if (config.enableAutomaticViewTracking || [config.features containsObject:CLYAutoViewTracking])
239238
{
240239
// Print deprecation flag for feature
241240
CountlyViewTrackingInternal.sharedInstance.isEnabledOnInitialConfig = YES;
241+
if (CountlyServerConfig.sharedInstance.viewTrackingEnabled) {
242+
[CountlyViewTrackingInternal.sharedInstance startAutoViewTracking];
243+
}
242244
[CountlyViewTrackingInternal.sharedInstance startAutoViewTracking];
243245
}
244246
if (config.automaticViewTrackingExclusionList) {
@@ -255,6 +257,7 @@ - (void)startWithConfig:(CountlyConfig *)config
255257
if (config.globalViewSegmentation) {
256258
[CountlyViewTrackingInternal.sharedInstance setGlobalViewSegmentation:config.globalViewSegmentation];
257259
}
260+
258261
timer = [NSTimer timerWithTimeInterval:config.updateSessionPeriod target:self selector:@selector(onTimer:) userInfo:nil repeats:YES];
259262
[NSRunLoop.mainRunLoop addTimer:timer forMode:NSRunLoopCommonModes];
260263

@@ -444,6 +447,7 @@ - (void)resume
444447
- (void)applicationDidBecomeActive:(NSNotification *)notification
445448
{
446449
CLY_LOG_D(@"App enters foreground");
450+
[CountlyServerConfig.sharedInstance fetchServerConfigIfTimeIsUp];
447451
[self resume];
448452
}
449453

@@ -857,6 +861,12 @@ - (void)recordEvent:(NSString *)key segmentation:(NSDictionary *)segmentation co
857861
CLY_LOG_W(@"A reserved event detected for key: '%@', event will not be recorded.", key);
858862
return;
859863
}
864+
865+
if (!CountlyServerConfig.sharedInstance.customEventTrackingEnabled)
866+
{
867+
CLY_LOG_D(@"'recordEvent' is aborted: Custom Event Tracking is disabled from server config!");
868+
return;
869+
}
860870

861871
NSDictionary* truncated = [segmentation cly_truncated:@"Event segmentation"];
862872
segmentation = [truncated cly_limited:@"Event segmentation"];

ios/Classes/CountlyiOS/CountlyCommon.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ extern NSString* const kCountlySDKName;
8888
@property (nonatomic) BOOL manualSessionHandling;
8989
@property (nonatomic) BOOL enableManualSessionControlHybridMode;
9090
@property (nonatomic) BOOL enableOrientationTracking;
91-
@property (nonatomic) BOOL enableServerConfiguration;
9291

9392
@property (nonatomic) BOOL enableVisibiltyTracking;
9493

ios/Classes/CountlyiOS/CountlyConfig.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,13 +662,21 @@ typedef enum : NSUInteger
662662
*/
663663
@property (nonatomic) BOOL enableOrientationTracking;
664664

665+
#pragma mark -
666+
665667
/**
666668
* This is an experimental feature and it can have breaking changes
667669
* For enabling fetching and application of server config values.
668670
* @discussion If set, Server Config values from Countly Server will be fetched at the beginning of a session.
671+
* @deprecated and will do nothing
669672
*/
670673
@property (nonatomic) BOOL enableServerConfiguration;
671674

675+
/**
676+
* Set the server configuration to be set while initializing the SDK
677+
*/
678+
@property (nonatomic, copy) NSString* serverConfiguration;
679+
672680
#if (TARGET_OS_IOS)
673681
/**
674682
* Variable to access content configurations.

ios/Classes/CountlyiOS/CountlyConfig.m

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ - (instancetype)init
7676
self.internalLogLevel = CLYInternalLogLevelDebug;
7777

7878
self.enableOrientationTracking = YES;
79-
self.enableServerConfiguration = NO;
8079
self.remoteConfigGlobalCallbacks = NSMutableArray.new;
8180
}
8281

ios/Classes/CountlyiOS/CountlyConnectionManager.m

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,9 @@ - (void)beginSession
356356
if (!CountlyConsentManager.sharedInstance.consentForSessions)
357357
return;
358358

359+
if(!CountlyServerConfig.sharedInstance.sessionTrackingEnabled)
360+
return;
361+
359362
if (isSessionStarted) {
360363
CLY_LOG_W(@"%s A session is already running, this 'beginSession' will be ignored", __FUNCTION__);
361364
return;
@@ -387,9 +390,11 @@ - (void)beginSession
387390
kCountlyQSKeySessionBegin, @"1",
388391
kCountlyQSKeyMetrics, [CountlyDeviceInfo metrics]];
389392

390-
NSString* locationRelatedInfoQueryString = [self locationRelatedInfoQueryString];
391-
if (locationRelatedInfoQueryString)
392-
queryString = [queryString stringByAppendingString:locationRelatedInfoQueryString];
393+
if(CountlyServerConfig.sharedInstance.locationTrackingEnabled) {
394+
NSString* locationRelatedInfoQueryString = [self locationRelatedInfoQueryString];
395+
if (locationRelatedInfoQueryString)
396+
queryString = [queryString stringByAppendingString:locationRelatedInfoQueryString];
397+
}
393398

394399
NSString* attributionQueryString = [self attributionQueryString];
395400
if (attributionQueryString)
@@ -407,6 +412,9 @@ - (void)updateSession
407412
if (!CountlyConsentManager.sharedInstance.consentForSessions)
408413
return;
409414

415+
if(!CountlyServerConfig.sharedInstance.sessionTrackingEnabled)
416+
return;
417+
410418
if (!isSessionStarted) {
411419
CLY_LOG_W(@"%s No session is running, this 'updateSession' will be ignored", __FUNCTION__);
412420
return;
@@ -425,6 +433,9 @@ - (void)endSession
425433
if (!CountlyConsentManager.sharedInstance.consentForSessions)
426434
return;
427435

436+
if(!CountlyServerConfig.sharedInstance.sessionTrackingEnabled)
437+
return;
438+
428439
if (!isSessionStarted) {
429440
CLY_LOG_W(@"%s No session is running, this 'endSession' will be ignored", __FUNCTION__);
430441
return;

ios/Classes/CountlyiOS/CountlyContentBuilderInternal.m

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ - (void)enterContentZone:(NSArray<NSString *> *)tags {
4848
return;
4949

5050
if(_requestTimer != nil) {
51-
CLY_LOG_I(@"Already entered for content zone, please exit from content zone first to start again");
51+
CLY_LOG_I(@"%s, Already entered for content zone, please exit from content zone first to start again", __FUNCTION__);
5252
return;
5353
}
5454

@@ -97,7 +97,7 @@ - (void)fetchContents {
9797

9898
NSURLSessionTask *dataTask = [[NSURLSession sharedSession] dataTaskWithRequest:[self fetchContentsRequest] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
9999
if (error) {
100-
CLY_LOG_I(@"Fetch content details failed: %@", error);
100+
CLY_LOG_I(@"%s, Fetch content details failed: %@", __FUNCTION__, error);
101101
self->_isRequestQueueLocked = NO;
102102
return;
103103
}
@@ -106,13 +106,13 @@ - (void)fetchContents {
106106
NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
107107

108108
if (jsonError) {
109-
CLY_LOG_I(@"Failed to parse JSON: %@", jsonError);
109+
CLY_LOG_I(@"%s, Failed to parse JSON: %@", __FUNCTION__, jsonError);
110110
self->_isRequestQueueLocked = NO;
111111
return;
112112
}
113113

114114
if (!jsonResponse) {
115-
CLY_LOG_I(@"Received empty or null response.");
115+
CLY_LOG_I(@"%s, Received empty or null response.", __FUNCTION__);
116116
self->_isRequestQueueLocked = NO;
117117
return;
118118
}
@@ -152,30 +152,38 @@ - (NSURLRequest *)fetchContentsRequest
152152
}
153153

154154
- (CGSize)getWindowSize {
155-
CGSize size = CGSizeZero;
155+
UIWindow *window = nil;
156156

157-
// Attempt to retrieve the size from the connected scenes (for modern apps)
158157
if (@available(iOS 13.0, *)) {
159-
NSSet<UIScene *> *scenes = [[UIApplication sharedApplication] connectedScenes];
160-
for (UIScene *scene in scenes) {
158+
for (UIScene *scene in [UIApplication sharedApplication].connectedScenes) {
161159
if ([scene isKindOfClass:[UIWindowScene class]]) {
162-
UIWindowScene *windowScene = (UIWindowScene *)scene;
163-
UIWindow *window = windowScene.windows.firstObject;
164-
if (window) {
165-
size = window.bounds.size;
166-
return size; // Return immediately if we find a valid size
167-
}
160+
window = ((UIWindowScene *)scene).windows.firstObject;
161+
break;
168162
}
169163
}
164+
} else {
165+
window = [[UIApplication sharedApplication].delegate window];
170166
}
171167

172-
// Fallback for legacy apps using AppDelegate
173-
id<UIApplicationDelegate> appDelegate = [[UIApplication sharedApplication] delegate];
174-
if ([appDelegate respondsToSelector:@selector(window)]) {
175-
UIWindow *legacyWindow = [appDelegate performSelector:@selector(window)];
176-
if (legacyWindow) {
177-
size = legacyWindow.bounds.size;
178-
}
168+
if (!window) return CGSizeZero;
169+
170+
UIEdgeInsets safeArea = UIEdgeInsetsZero;
171+
CGFloat screenScale = [UIScreen mainScreen].scale;
172+
if (@available(iOS 11.0, *)) {
173+
safeArea = window.safeAreaInsets;
174+
safeArea.left /= screenScale;
175+
safeArea.bottom /= screenScale;
176+
safeArea.right /= screenScale;
177+
}
178+
179+
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
180+
BOOL isLandscape = UIInterfaceOrientationIsLandscape(orientation);
181+
182+
CGSize size = CGSizeMake(window.bounds.size.width, window.bounds.size.height);
183+
184+
if(!isLandscape){
185+
size.width -= safeArea.left + safeArea.right;
186+
size.height -= safeArea.top + safeArea.bottom;
179187
}
180188

181189
return size;
@@ -196,6 +204,8 @@ - (NSString *)resolutionJson {
196204
@"landscape": @{@"height": @(lHpW), @"width": @(lWpH)}
197205
};
198206

207+
CLY_LOG_D(@"%s, %@", __FUNCTION__, resolutionDict);
208+
199209
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:resolutionDict options:0 error:nil];
200210
return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
201211
}
@@ -205,7 +215,7 @@ - (void)showContentWithHtmlPath:(NSString *)urlString placementCoordinates:(NSDi
205215
NSURL *url = [NSURL URLWithString:urlString];
206216

207217
if (!url || !url.scheme || !url.host) {
208-
NSLog(@"The URL is not valid: %@", urlString);
218+
CLY_LOG_E(@"%s, The URL is not valid: %@", __FUNCTION__, urlString);
209219
return;
210220
}
211221

@@ -227,17 +237,17 @@ - (void)showContentWithHtmlPath:(NSString *)urlString placementCoordinates:(NSDi
227237
CGRect frame = CGRectMake(x, y, width, height);
228238

229239
// Log the URL and the frame
230-
CLY_LOG_I(@"Showing content from URL: %@", url);
231-
CLY_LOG_I(@"Placement frame: %@", NSStringFromCGRect(frame));
240+
CLY_LOG_I(@"%s, Showing content from URL: %@", __FUNCTION__, url);
241+
CLY_LOG_I(@"%s, Placement frame: %@", __FUNCTION__, NSStringFromCGRect(frame));
232242

233243
CountlyWebViewManager* webViewManager = CountlyWebViewManager.new;
234244
[webViewManager createWebViewWithURL:url frame:frame appearBlock:^
235245
{
236-
CLY_LOG_I(@"Webview appeared");
246+
CLY_LOG_I(@"%s, Webview appeared", __FUNCTION__);
237247
[self clearContentState];
238248
} dismissBlock:^
239249
{
240-
CLY_LOG_I(@"Webview dismissed");
250+
CLY_LOG_I(@"%s, Webview dismissed", __FUNCTION__);
241251
self->_minuteTimer = [NSTimer scheduledTimerWithTimeInterval:60.0
242252
target:self
243253
selector:@selector(enterContentZone)

0 commit comments

Comments
 (0)