Skip to content

Commit d108cf5

Browse files
authored
Merge pull request #135 from erkanyildiz/master
For 19.02
2 parents ec4ae46 + 2fc78d4 commit d108cf5

18 files changed

+592
-107
lines changed

CHANGELOG.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,25 @@
1+
## 19.02
2+
- Added push notification support for macOS
3+
- Added provisional push notification permission support for iOS12
4+
- Added remote config feature
5+
- Added `recordPushNotificationToken` method to be used after device ID changes
6+
- Added `clearPushNotificationToken` method to be used after device ID changes
7+
- Discarded `Push Open` event and replaced it with `Push Action` event
8+
- Fixed push notification token not being sent on some iOS12 devices
9+
- Fixed device ID change request delaying issue by discarding delay altogether
10+
- Fixed internal view controller presenting failure when root view controller is not ready yet
11+
- Fixed `openURL` freeze caused by iOS
12+
- Fixed wrong `kCountlyQSKeyLocationIP` key in location info requests
13+
- Fixed missing app key in feedback widget requests
14+
- Fixed feedback widget dismiss button position
15+
16+
- Other various improvements
17+
- Discarded separate UIWindow usage for presenting feedback widgets
18+
- Added checksum to feedback widget requests
19+
- Improved internal logging for request queue
20+
21+
22+
123
## 18.08
224
- Added feedback widgets support
325
- Added limit for number of custom crash logs (100 logs)

Countly.h

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#import <CoreLocation/CoreLocation.h>
99
#import "CountlyUserDetails.h"
1010
#import "CountlyConfig.h"
11-
#if TARGET_OS_IOS
11+
#if (TARGET_OS_IOS || TARGET_OS_OSX)
1212
#import <UserNotifications/UserNotifications.h>
1313
#endif
1414

@@ -246,7 +246,7 @@ NS_ASSUME_NONNULL_BEGIN
246246

247247

248248
#pragma mark - Push Notification
249-
#if TARGET_OS_IOS
249+
#if (TARGET_OS_IOS || TARGET_OS_OSX)
250250
/**
251251
* Shows default system dialog that asks for user's permission to display notifications.
252252
* @discussion A unified convenience method that handles asking for notification permission on both iOS10 and older iOS versions with badge, sound and alert notification types.
@@ -261,7 +261,7 @@ NS_ASSUME_NONNULL_BEGIN
261261
* @param options Bitwise combination of notification types (badge, sound or alert) the app wants to display
262262
* @param completionHandler A completion handler block to be executed when user answers notification permission dialog
263263
*/
264-
- (void)askForNotificationPermissionWithOptions:(UNAuthorizationOptions)options completionHandler:(void (^)(BOOL granted, NSError * error))completionHandler API_AVAILABLE(ios(10.0));
264+
- (void)askForNotificationPermissionWithOptions:(UNAuthorizationOptions)options completionHandler:(void (^)(BOOL granted, NSError * error))completionHandler API_AVAILABLE(ios(10.0), macos(10.14));
265265

266266
/**
267267
* Records action event for a manually presented push notification with custom action buttons.
@@ -273,6 +273,18 @@ NS_ASSUME_NONNULL_BEGIN
273273
*/
274274
- (void)recordActionForNotification:(NSDictionary *)userInfo clickedButtonIndex:(NSInteger)buttonIndex;
275275

276+
/**
277+
* Records push notification token to Countly Server for current device ID.
278+
* @discussion Can be used to re-send push notification token for current device ID, after a new user logs in and device ID changes, without waiting for the app to be restarted.
279+
* @discussion In general, push notification token is handled automatically and this method does not need to be called manually.
280+
*/
281+
- (void)recordPushNotificationToken;
282+
283+
/**
284+
* Clears push notification token on Countly Server for current device ID.
285+
* @discussion Can be used to clear push notification token for current device ID, before the current user logs out and device ID changes, without waiting for the app to be restarted.
286+
*/
287+
- (void)clearPushNotificationToken;
276288
#endif
277289

278290

@@ -477,6 +489,41 @@ NS_ASSUME_NONNULL_BEGIN
477489

478490
#endif
479491

492+
493+
494+
#pragma mark - Remote Config
495+
/**
496+
* Returns last retrieved remote config value for given key, if exists.
497+
* @discussion If remote config is never retrieved from Countly Server before, this method will return @c nil.
498+
* @discussion If @c key is not defined in remote config on Countly Server, this method will return @c nil.
499+
* @discussion If Countly Server is not reachable, this method will return the last retrieved value which is stored on device.
500+
* @param key Remote config key specified on Countly Server
501+
*/
502+
- (id)remoteConfigValueForKey:(NSString *)key;
503+
504+
/**
505+
* Manually updates all locally stored remote config values by fetching latest values from Countly Server, and executes completion handler.
506+
* @discussion @c completionHandler has an @c NSError parameter that will be either @ nil or an @c NSError object, depending on result.
507+
* @param completionHandler A completion handler block to be executed when updating of remote config is completed, either with success or failure.
508+
*/
509+
- (void)updateRemoteConfigWithCompletionHandler:(void (^)(NSError * error))completionHandler;
510+
511+
/**
512+
* Manually updates locally stored remote config values only for specified keys, by fetching latest values from Countly Server, and executes completion handler.
513+
* @discussion @c completionHandler has an @c NSError parameter that will be either @ nil or an @c NSError object, depending on result.
514+
* @param keys An array of remote config keys to update
515+
* @param completionHandler A completion handler block to be executed when updating of remote config is completed, either with success or failure
516+
*/
517+
- (void)updateRemoteConfigOnlyForKeys:(NSArray *)keys completionHandler:(void (^)(NSError * error))completionHandler;
518+
519+
/**
520+
* Manually updates locally stored remote config values except for specified keys, by fetching latest values from Countly Server, and executes completion handler.
521+
* @discussion @c completionHandler has an @c NSError parameter that will be either @ nil or an @c NSError object, depending on result.
522+
* @param omitKeys An array of remote config keys to omit from updating
523+
* @param completionHandler A completion handler block to be executed when updating of remote config is completed, either with success or failure
524+
*/
525+
- (void)updateRemoteConfigExceptForKeys:(NSArray *)omitKeys completionHandler:(void (^)(NSError * error))completionHandler;
526+
480527
NS_ASSUME_NONNULL_END
481528

482529
@end

Countly.m

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -108,22 +108,25 @@ - (void)startWithConfig:(CountlyConfig *)config
108108
CountlyLocationManager.sharedInstance.IP = config.IP;
109109
[CountlyLocationManager.sharedInstance sendLocationInfo];
110110

111+
CountlyCrashReporter.sharedInstance.crashSegmentation = config.crashSegmentation;
112+
CountlyCrashReporter.sharedInstance.crashLogLimit = MAX(1, config.crashLogLimit);
113+
if ([config.features containsObject:CLYCrashReporting])
114+
{
115+
CountlyCrashReporter.sharedInstance.isEnabledOnInitialConfig = YES;
116+
[CountlyCrashReporter.sharedInstance startCrashReporting];
117+
}
118+
#endif
119+
120+
#if (TARGET_OS_IOS || TARGET_OS_OSX)
111121
if ([config.features containsObject:CLYPushNotifications])
112122
{
113123
CountlyPushNotifications.sharedInstance.isEnabledOnInitialConfig = YES;
114124
CountlyPushNotifications.sharedInstance.isTestDevice = config.isTestDevice;
115125
CountlyPushNotifications.sharedInstance.sendPushTokenAlways = config.sendPushTokenAlways;
116126
CountlyPushNotifications.sharedInstance.doNotShowAlertForNotifications = config.doNotShowAlertForNotifications;
127+
CountlyPushNotifications.sharedInstance.launchNotification = config.launchNotification;
117128
[CountlyPushNotifications.sharedInstance startPushNotifications];
118129
}
119-
120-
CountlyCrashReporter.sharedInstance.crashSegmentation = config.crashSegmentation;
121-
CountlyCrashReporter.sharedInstance.crashLogLimit = MAX(1, config.crashLogLimit);
122-
if ([config.features containsObject:CLYCrashReporting])
123-
{
124-
CountlyCrashReporter.sharedInstance.isEnabledOnInitialConfig = YES;
125-
[CountlyCrashReporter.sharedInstance startCrashReporting];
126-
}
127130
#endif
128131

129132
#if (TARGET_OS_IOS || TARGET_OS_TV)
@@ -145,6 +148,10 @@ - (void)startWithConfig:(CountlyConfig *)config
145148

146149
[CountlyCommon.sharedInstance startAttribution];
147150

151+
CountlyRemoteConfig.sharedInstance.isEnabledOnInitialConfig = config.enableRemoteConfig;
152+
CountlyRemoteConfig.sharedInstance.remoteConfigCompletionHandler = config.remoteConfigCompletionHandler;
153+
[CountlyRemoteConfig.sharedInstance startRemoteConfig];
154+
148155
[CountlyConnectionManager.sharedInstance proceedOnQueue];
149156
}
150157

@@ -194,6 +201,9 @@ - (void)setNewDeviceID:(NSString *)deviceID onServer:(BOOL)onServer
194201

195202
[CountlyPersistency.sharedInstance clearAllTimedEvents];
196203
}
204+
205+
[CountlyRemoteConfig.sharedInstance clearCachedRemoteConfig];
206+
[CountlyRemoteConfig.sharedInstance startRemoteConfig];
197207
}
198208

199209
- (void)setCustomHeaderFieldValue:(NSString *)customHeaderFieldValue
@@ -502,7 +512,7 @@ - (void)cancelEvent:(NSString *)key
502512

503513

504514
#pragma mark - Push Notifications
505-
#if TARGET_OS_IOS
515+
#if (TARGET_OS_IOS || TARGET_OS_OSX)
506516

507517
- (void)askForNotificationPermission
508518
{
@@ -518,6 +528,16 @@ - (void)recordActionForNotification:(NSDictionary *)userInfo clickedButtonIndex:
518528
{
519529
[CountlyPushNotifications.sharedInstance recordActionForNotification:userInfo clickedButtonIndex:buttonIndex];
520530
}
531+
532+
- (void)recordPushNotificationToken
533+
{
534+
[CountlyPushNotifications.sharedInstance sendToken];
535+
}
536+
537+
- (void)clearPushNotificationToken
538+
{
539+
[CountlyPushNotifications.sharedInstance clearToken];
540+
}
521541
#endif
522542

523543

@@ -662,4 +682,29 @@ - (void)presentFeedbackWidgetWithID:(NSString *)widgetID completionHandler:(void
662682

663683
#endif
664684

685+
686+
687+
#pragma mark - Remote Config
688+
689+
- (id)remoteConfigValueForKey:(NSString *)key
690+
{
691+
return [CountlyRemoteConfig.sharedInstance remoteConfigValueForKey:key];
692+
}
693+
694+
- (void)updateRemoteConfigWithCompletionHandler:(void (^)(NSError * error))completionHandler
695+
{
696+
[CountlyRemoteConfig.sharedInstance updateRemoteConfigForForKeys:nil omitKeys:nil completionHandler:completionHandler];
697+
}
698+
699+
- (void)updateRemoteConfigOnlyForKeys:(NSArray *)keys completionHandler:(void (^)(NSError * error))completionHandler
700+
{
701+
[CountlyRemoteConfig.sharedInstance updateRemoteConfigForForKeys:keys omitKeys:nil completionHandler:completionHandler];
702+
}
703+
704+
- (void)updateRemoteConfigExceptForKeys:(NSArray *)omitKeys completionHandler:(void (^)(NSError * error))completionHandler
705+
{
706+
[CountlyRemoteConfig.sharedInstance updateRemoteConfigForForKeys:nil omitKeys:omitKeys completionHandler:completionHandler];
707+
}
708+
709+
665710
@end

Countly.podspec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
Pod::Spec.new do |s|
22
s.name = 'Countly'
3-
s.version = '18.08'
3+
s.version = '19.02'
44
s.license = {
55
:type => 'COMMUNITY',
66
:text => <<-LICENSE
77
COUNTLY MOBILE ANALYTICS COMMUNITY EDITION LICENSE
88
--------------------------------------------------
99
10-
Copyright (c) 2012, 2018 Countly
10+
Copyright (c) 2012, 2019 Countly
1111
1212
Permission is hereby granted, free of charge, to any person obtaining a copy
1313
of this software and associated documentation files (the "Software"), to deal

CountlyCommon.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#import "CountlyNotificationService.h"
2323
#import "CountlyConsentManager.h"
2424
#import "CountlyLocationManager.h"
25+
#import "CountlyRemoteConfig.h"
2526

2627
#if DEBUG
2728
#define COUNTLY_LOG(fmt, ...) CountlyInternalLog(fmt, ##__VA_ARGS__)
@@ -64,6 +65,7 @@ NS_ERROR_ENUM(kCountlyErrorDomain)
6465
{
6566
CLYErrorFeedbackWidgetNotAvailable = 10001,
6667
CLYErrorFeedbackWidgetNotTargetedForDevice = 10002,
68+
CLYErrorRemoteConfigGeneralAPIError = 10011,
6769
};
6870

6971
@interface CountlyCommon : NSObject
@@ -88,6 +90,7 @@ void CountlyInternalLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2);
8890

8991
#if (TARGET_OS_IOS || TARGET_OS_TV)
9092
- (UIViewController *)topViewController;
93+
- (void)tryPresentingViewController:(UIViewController *)viewController;
9194
#endif
9295

9396
- (void)startAppleWatchMatching;

CountlyCommon.m

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ @interface CountlyCommon ()
1818
#endif
1919
@end
2020

21-
NSString* const kCountlySDKVersion = @"18.08";
21+
NSString* const kCountlySDKVersion = @"19.02";
2222
NSString* const kCountlySDKName = @"objc-native-ios";
2323

2424
NSString* const kCountlyParentDeviceIDTransferKey = @"kCountlyParentDeviceIDTransferKey";
@@ -222,6 +222,19 @@ - (UIViewController *)topViewController
222222

223223
return topVC;
224224
}
225+
226+
- (void)tryPresentingViewController:(UIViewController *)viewController
227+
{
228+
UIViewController* topVC = self.topViewController;
229+
230+
if (topVC)
231+
{
232+
[topVC presentViewController:viewController animated:YES completion:nil];
233+
return;
234+
}
235+
236+
[self performSelector:@selector(tryPresentingViewController:) withObject:viewController afterDelay:1.0];
237+
}
225238
#endif
226239

227240
@end

CountlyConfig.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ extern NSString* const CLYCrashReporting;
1515
extern NSString* const CLYAutoViewTracking;
1616
#elif TARGET_OS_TV
1717
extern NSString* const CLYAutoViewTracking;
18+
#elif TARGET_OS_OSX
19+
extern NSString* const CLYPushNotifications;
1820
#endif
1921
//NOTE: Disable APM feature until Countly Server completely supports it
2022
// extern NSString* const CLYAPM;
@@ -105,6 +107,12 @@ extern NSString* const CLYConsentAppleWatch;
105107
*/
106108
@property (nonatomic) BOOL doNotShowAlertForNotifications;
107109

110+
/**
111+
* For handling push notifications for macOS apps on launch.
112+
* @discussion Needs to be set in @c applicationDidFinishLaunching: method of macOS apps that uses @c CLYPushNotifications feature, in order to handle app launches by push notification click.
113+
*/
114+
@property (nonatomic) NSNotification* launchNotification;
115+
108116
#pragma mark -
109117

110118
/**
@@ -276,6 +284,24 @@ extern NSString* const CLYConsentAppleWatch;
276284
*/
277285
@property (nonatomic, copy) void (^starRatingCompletion)(NSInteger rating);
278286

287+
#pragma mark -
288+
289+
/**
290+
* For enabling automatic fetching of remote config values.
291+
* @discussion If set, Remote Config values specified on Countly Server will be fetched on beginning of sessions.
292+
*/
293+
@property (nonatomic) BOOL enableRemoteConfig;
294+
295+
/**
296+
* Completion block to be executed after remote config is fetched from Countly Server, on start or device ID change.
297+
* @discussion This completion block can be used to detect updating of remote config values is completed, either with success or failure.
298+
* @discussion It has an @c NSError parameter that will be either @ nil or an @c NSError object, depending of request result.
299+
* @discussion If there is no error, it will be executed with an @c nil, which means latest remote config values are ready to be used.
300+
* @discussion If Countly Server is not reachable or if there is another error, it will be executed with an @c NSError indicating the problem.
301+
* @discussion If @c enableRemoteConfig flag is not set on initial config, it will never be executed.
302+
*/
303+
@property (nonatomic, copy) void (^remoteConfigCompletionHandler)(NSError * _Nullable error);
304+
279305
NS_ASSUME_NONNULL_END
280306

281307
@end

CountlyConfig.m

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ @implementation CountlyConfig
1515
NSString* const CLYAutoViewTracking = @"CLYAutoViewTracking";
1616
#elif TARGET_OS_TV
1717
NSString* const CLYAutoViewTracking = @"CLYAutoViewTracking";
18+
#elif TARGET_OS_OSX
19+
NSString* const CLYPushNotifications = @"CLYPushNotifications";
1820
#endif
1921
//NOTE: Disable APM feature until Countly Server completely supports it
2022
// NSString* const CLYAPM = @"CLYAPM";

CountlyConnectionManager.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,8 @@
3838
- (void)sendConsentChanges:(NSString *)consentChanges;
3939

4040
- (void)proceedOnQueue;
41+
42+
- (NSString *)queryEssentials;
43+
- (NSString *)appendChecksum:(NSString *)queryString;
44+
4145
@end

0 commit comments

Comments
 (0)