Skip to content

Commit 7097409

Browse files
authored
Push action caching implemented for iOS. (#56)
* Push action caching implemented for iOS. * Changelog and release version updated. * Changlelog updated and android sdk version to .9 * Public header file issue fixed for “CountlyReactNative.h” file * onNotificationResponse function added in .h file for public * Revert to android SDK .8 version
1 parent 5ae5589 commit 7097409

File tree

9 files changed

+165
-43
lines changed

9 files changed

+165
-43
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
## 20.11.6
2+
* !! To handle the push notification you need to add the notifcation callback "didReceiveNotificationResponse" in your "AppDelegate.m" file and send the reponse to Countly SDK using this function "onNotificationResponse", for more detials please check the below mentioned link of "Handling push callbacks" section in Countly SDK documentation.
3+
https://support.count.ly/hc/en-us/articles/360037813231-React-Native-Bridge-#handling-push-callbacks
4+
* Push notification action issue fixed when app is closed and user tap on notification.
5+
* Updated underlying android SDK to 20.11.8
6+
* Underlying iOS SDK version is 20.11.1
7+
18
## 20.11.5
29
* iOS thread safety added to make all function calls on main thread.
310

CountlyReactNative.podspec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = 'CountlyReactNative'
3-
s.version = '20.11.5'
3+
s.version = '20.11.6'
44
s.license = {
55
:type => 'COMMUNITY',
66
:text => <<-LICENSE
@@ -34,7 +34,7 @@ Pod::Spec.new do |s|
3434
s.author = {'Countly' => '[email protected]'}
3535
s.source = { :git => 'https://github.com/Countly/countly-sdk-ios.git', :tag => s.version.to_s }
3636
s.source_files = 'ios/src/*.{h,m}'
37-
s.public_header_files = 'ios/src/Countly.h', 'ios/src/CountlyUserDetails.h', 'ios/src/CountlyConfig.h'
37+
s.public_header_files = 'ios/src/CountlyReactNative.h'
3838
s.requires_arc = true
3939
s.ios.deployment_target = '8.0'
4040
s.osx.deployment_target = '8.0'

android/build.gradle

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
buildscript {
22
repositories {
3+
mavenCentral()
34
google()
45
jcenter()
56
}
@@ -31,6 +32,7 @@ android {
3132
}
3233

3334
repositories {
35+
mavenCentral()
3436
google()
3537
maven {
3638
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
@@ -44,7 +46,7 @@ repositories {
4446

4547
dependencies {
4648
implementation "com.facebook.react:react-native:${safeExtGet('reactNativeVersion', '+')}"
47-
implementation 'ly.count.android:sdk:20.11.5'
49+
implementation 'ly.count.android:sdk:20.11.8'
4850

4951
//if any version higher than 18.0.0 is used then it forces AndroidX
5052
implementation 'com.google.firebase:firebase-messaging:18.0.0'

android/src/main/java/ly/count/android/sdk/react/CountlyReactNative.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public String toString(){
7474
public class CountlyReactNative extends ReactContextBaseJavaModule implements LifecycleEventListener {
7575

7676
public static final String TAG = "CountlyRNPlugin";
77-
private String COUNTLY_RN_SDK_VERSION_STRING = "20.11.5";
77+
private String COUNTLY_RN_SDK_VERSION_STRING = "20.11.6";
7878
private String COUNTLY_RN_SDK_NAME = "js-rnb-android";
7979

8080
private static CountlyConfig config = new CountlyConfig();

example/README.md

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,23 @@ Add header file
2222

2323
Before `@end` add these method
2424

25-
-(void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler{
26-
NSLog(@"didReceiveNotificationResponse");
27-
NSDictionary *notification = response.notification.request.content.userInfo;
28-
[CountlyReactNative onNotification: notification];
25+
// Required for the notification event. You must call the completion handler after handling the remote notification.
26+
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
27+
{
28+
[CountlyReactNative onNotification: userInfo];
29+
completionHandler(0);
30+
}
31+
32+
// When app is killed.
33+
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler{
34+
[CountlyReactNative onNotificationResponse: response];
2935
completionHandler();
3036
}
3137

32-
//Called when a notification is delivered to a foreground app.
33-
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
34-
{
35-
NSLog(@"didReceiveNotificationResponse");
36-
NSDictionary *userInfo = notification.request.content.userInfo;
37-
[CountlyReactNative onNotification: userInfo];
38-
completionHandler(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge);
38+
// When app is running.
39+
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{
40+
[CountlyReactNative onNotification: notification.request.content.userInfo];
41+
completionHandler(0);
3942
}
4043

4144

example/install.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ rm App.js
1111
curl https://raw.githubusercontent.com/Countly/countly-sdk-react-native-bridge/master/example/App.js --output App.js
1212
curl https://raw.githubusercontent.com/Countly/countly-sdk-react-native-bridge/master/example/Example.js --output Example.js
1313

14-
14+
1515

1616
cd ./ios
1717
pod install

ios/src/CountlyReactNative.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ typedef void (^Result)(id _Nullable result);
5252
- (void)askForNotificationPermission:(NSArray*_Nullable)arguments;
5353
- (void)registerForNotification:(NSArray*_Nullable)arguments;
5454
+ (void)onNotification:(NSDictionary *_Nullable)notification;
55+
+ (void)onNotificationResponse:(UNNotificationResponse* _Nullable)response;
5556
- (void)handleRemoteNotificationReceived:(NSDictionary *_Nullable)notification;
5657
- (void)remoteConfigClearValues:(RCTPromiseResolveBlock _Nullable )resolve rejecter:(RCTPromiseRejectBlock _Nullable )reject;
5758
+ (NSString *_Nullable) toJSON: (NSDictionary * _Nullable) json;

ios/src/CountlyReactNative.m

Lines changed: 135 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ @interface CountlyFeedbackWidget ()
2121
+ (CountlyFeedbackWidget *)createWithDictionary:(NSDictionary *)dictionary;
2222
@end
2323

24-
NSString* const kCountlyReactNativeSDKVersion = @"20.11.5";
24+
NSString* const kCountlyReactNativeSDKVersion = @"20.11.6";
2525
NSString* const kCountlyReactNativeSDKName = @"js-rnb-ios";
2626

2727
CountlyConfig* config = nil;
@@ -31,7 +31,11 @@ + (CountlyFeedbackWidget *)createWithDictionary:(NSDictionary *)dictionary;
3131
NSMutableArray<CLYFeature>* countlyFeatures = nil;
3232
BOOL enablePushNotifications = true;
3333

34+
NSDictionary* notificationCacheDictionary = nil;
35+
NSInteger notificationCacheButtonIndex = 0;
36+
3437
@implementation CountlyReactNative
38+
NSString* const kCountlyNotificationPersistencyKey = @"kCountlyNotificationPersistencyKey";
3539

3640
- (NSArray<NSString *> *)supportedEvents {
3741
return @[@"onCountlyPushNotification"];
@@ -66,8 +70,27 @@ @implementation CountlyReactNative
6670
}
6771

6872
if (serverurl != nil && [serverurl length] > 0) {
69-
[[Countly sharedInstance] startWithConfig:config];
70-
resolve(@"Success");
73+
dispatch_async(dispatch_get_main_queue(), ^
74+
{
75+
[[Countly sharedInstance] startWithConfig:config];
76+
77+
resolve(@"Success");
78+
// NSData* readData = [NSData dataWithContentsOfURL:[CountlyReactNative storageFileURL]];
79+
80+
if (notificationCacheDictionary != nil)
81+
{
82+
// NSDictionary* readDict = [NSKeyedUnarchiver unarchiveObjectWithData:readData];
83+
NSDictionary* notificationDictionary = notificationCacheDictionary;// [readDict[kCountlyNotificationPersistencyKey] mutableCopy];
84+
NSInteger buttonIndex = notificationCacheButtonIndex;
85+
if([notificationDictionary count] > 0) {
86+
[Countly.sharedInstance recordActionForNotification:notificationDictionary clickedButtonIndex:buttonIndex];
87+
notificationCacheDictionary = nil;
88+
notificationCacheButtonIndex = 0;
89+
// [CountlyReactNative saveToFile:NSMutableDictionary.new buttonIndex:0];
90+
}
91+
92+
}
93+
});
7194
}
7295
});
7396
}
@@ -236,29 +259,6 @@ - (void) saveListener:(Result) result{
236259

237260
};
238261

239-
+ (void)onNotification:(NSDictionary *)notificationMessage
240-
{
241-
COUNTLY_RN_LOG(@"Notification received");
242-
COUNTLY_RN_LOG(@"The notification %@", [CountlyReactNative toJSON:notificationMessage]);
243-
if(notificationMessage && notificationListener != nil){
244-
lastStoredNotification = notificationMessage;
245-
notificationListener(@[[CountlyReactNative toJSON:notificationMessage]]);
246-
}else{
247-
lastStoredNotification = notificationMessage;
248-
}
249-
if(notificationMessage){
250-
if(notificationIDs == nil){
251-
notificationIDs = [[NSMutableArray alloc] init];
252-
}
253-
if ([[notificationMessage allKeys] containsObject:@"c"]) {
254-
NSDictionary* countlyPayload = notificationMessage[@"c"];
255-
if ([[countlyPayload allKeys] containsObject:@"c"]) {
256-
NSString *notificationID = countlyPayload[@"i"];
257-
[notificationIDs insertObject:notificationID atIndex:[notificationIDs count]];
258-
}
259-
}
260-
}
261-
}
262262
+ (NSString *) toJSON: (NSDictionary *) json{
263263
NSError *error;
264264
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:json options:NSJSONWritingPrettyPrinted error:&error];
@@ -1091,4 +1091,113 @@ void CountlyRNInternalLog(NSString *format, ...)
10911091

10921092
va_end(args);
10931093
}
1094+
1095+
+ (void)onNotification:(NSDictionary *)notificationMessage
1096+
{
1097+
[CountlyReactNative onNotification:notificationMessage buttonIndex:0];
1098+
}
1099+
1100+
+ (void)onNotification:(NSDictionary *)notificationMessage buttonIndex:(NSInteger)btnIndex
1101+
{
1102+
COUNTLY_RN_LOG(@"Notification received");
1103+
COUNTLY_RN_LOG(@"The notification %@", [CountlyReactNative toJSON:notificationMessage]);
1104+
if(notificationMessage && notificationListener != nil){
1105+
lastStoredNotification = notificationMessage;
1106+
notificationListener(@[[CountlyReactNative toJSON:notificationMessage]]);
1107+
}else{
1108+
lastStoredNotification = notificationMessage;
1109+
}
1110+
if(notificationMessage){
1111+
if(notificationIDs == nil){
1112+
notificationIDs = [[NSMutableArray alloc] init];
1113+
}
1114+
if ([[notificationMessage allKeys] containsObject:@"c"]) {
1115+
NSDictionary* countlyPayload = notificationMessage[@"c"];
1116+
if ([[countlyPayload allKeys] containsObject:@"c"]) {
1117+
NSString *notificationID = countlyPayload[@"i"];
1118+
[notificationIDs insertObject:notificationID atIndex:[notificationIDs count]];
1119+
}
1120+
}
1121+
}
1122+
}
1123+
1124+
+(void)onNotificationResponse:(UNNotificationResponse *)response
1125+
API_AVAILABLE(ios(10.0)){
1126+
NSDictionary* notificationDictionary = response.notification.request.content.userInfo;
1127+
NSInteger buttonIndex = 0;
1128+
if ([response.actionIdentifier hasPrefix:kCountlyActionIdentifier])
1129+
{
1130+
buttonIndex = [[response.actionIdentifier stringByReplacingOccurrencesOfString:kCountlyActionIdentifier withString:@""] integerValue];
1131+
}
1132+
if(!CountlyCommon.sharedInstance.hasStarted) {
1133+
notificationCacheDictionary = notificationDictionary;
1134+
notificationCacheButtonIndex = buttonIndex;
1135+
// [CountlyReactNative saveToFile:notificationDictionary buttonIndex:buttonIndex];
1136+
}
1137+
[CountlyReactNative onNotification:notificationDictionary buttonIndex:buttonIndex];
1138+
1139+
}
1140+
+ (NSURL *)storageDirectoryURL
1141+
{
1142+
static NSURL* URL = nil;
1143+
1144+
static dispatch_once_t onceToken;
1145+
dispatch_once(&onceToken, ^
1146+
{
1147+
#if (TARGET_OS_TV)
1148+
NSSearchPathDirectory directory = NSCachesDirectory;
1149+
#else
1150+
NSSearchPathDirectory directory = NSApplicationSupportDirectory;
1151+
#endif
1152+
URL = [[NSFileManager.defaultManager URLsForDirectory:directory inDomains:NSUserDomainMask] lastObject];
1153+
1154+
#if (TARGET_OS_OSX)
1155+
URL = [URL URLByAppendingPathComponent:NSBundle.mainBundle.bundleIdentifier];
1156+
#endif
1157+
NSError *error = nil;
1158+
1159+
if (![NSFileManager.defaultManager fileExistsAtPath:URL.path])
1160+
{
1161+
[NSFileManager.defaultManager createDirectoryAtURL:URL withIntermediateDirectories:YES attributes:nil error:&error];
1162+
if (error)
1163+
{
1164+
COUNTLY_LOG(@"Application Support directory can not be created: \n%@", error);
1165+
}
1166+
}
1167+
});
1168+
1169+
return URL;
1170+
}
1171+
1172+
+ (NSURL *)storageFileURL
1173+
{
1174+
NSString* const kCountlyPersistencyFileName = @"CountlyBridge.dat";
1175+
1176+
static NSURL* URL = nil;
1177+
1178+
static dispatch_once_t onceToken;
1179+
dispatch_once(&onceToken, ^
1180+
{
1181+
URL = [[CountlyReactNative storageDirectoryURL] URLByAppendingPathComponent:kCountlyPersistencyFileName];
1182+
});
1183+
1184+
return URL;
1185+
}
1186+
1187+
+ (void)saveToFile:(NSDictionary *)notificationMessage buttonIndex:(NSInteger)btnIndex
1188+
{
1189+
NSData* saveData;
1190+
1191+
@synchronized (self)
1192+
{
1193+
saveData = [NSKeyedArchiver archivedDataWithRootObject:@{kCountlyNotificationPersistencyKey: notificationMessage}];
1194+
1195+
}
1196+
1197+
#pragma clang diagnostic push
1198+
#pragma clang diagnostic ignored "-Wunused-variable"
1199+
1200+
BOOL writeResult = [saveData writeToFile:[CountlyReactNative storageFileURL].path atomically:YES];
1201+
COUNTLY_LOG(@"Result of writing data to file: %d", writeResult);
1202+
}
10941203
@end

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "countly-sdk-react-native-bridge",
3-
"version": "20.11.5",
3+
"version": "20.11.6",
44
"author": "Countly <[email protected]> (https://count.ly/)",
55
"bugs": {
66
"url": "https://github.com/Countly/countly-sdk-react-native-bridge/issues"

0 commit comments

Comments
 (0)