Skip to content

Commit f7d4f65

Browse files
Added activity null checks. Reworked attribution for ios. Increased SDK version. Merge pull request #29 from Countly/dev-junaid
2 parents 5d267a3 + 9f51a7c commit f7d4f65

File tree

8 files changed

+154
-16
lines changed

8 files changed

+154
-16
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
## 20.4.8
2+
* Added "recordAttributionID" call to support changes in iOS 14 related to App Tracking Permission.
13
## 20.4.7
24
* Adding call to set consent during init
35

Countly.js

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,8 @@ Countly.recordView = function(recordView, segments){
119119

120120
/**
121121
*
122-
* Set Push notification messaging mode and callbacks for push notifications
123-
* Should be call after Countly init
122+
* Set messaging mode for push notifications
123+
* Should be call before Countly init
124124
*/
125125
Countly.pushTokenType = function(tokenType, channelName, channelDescription){
126126
var args = [];
@@ -674,10 +674,36 @@ Countly.enableApm = function(){
674674
/**
675675
*
676676
* Enable campaign attribution reporting to Countly.
677+
* For iOS use "recordAttributionID" instead of "enableAttribution"
677678
* Should be call before Countly init
678679
*/
679-
Countly.enableAttribution = function() {
680-
CountlyReactNative.enableAttribution();
680+
Countly.enableAttribution = async function(attributionID = "") {
681+
if (Platform.OS.match("ios")) {
682+
if(attributionID == "") {
683+
if(await CountlyReactNative.isLoggingEnabled()) {
684+
console.error("[CountlyReactNative] enableAttribution, attribution Id for iOS can't be empty string");
685+
}
686+
return "attribution Id for iOS can't be empty string";
687+
}
688+
Countly.recordAttributionID(attributionID);
689+
}
690+
else {
691+
CountlyReactNative.enableAttribution();
692+
}
693+
}
694+
695+
/**
696+
*
697+
* set attribution Id for campaign attribution reporting.
698+
* Currently implemented for iOS only
699+
* For Android just call the enableAttribution to enable campaign attribution.
700+
*/
701+
702+
Countly.recordAttributionID = function(attributionID){
703+
if (!Platform.OS.match("ios")) return "recordAttributionID : To be implemented";
704+
var args = [];
705+
args.push(attributionID);
706+
CountlyReactNative.recordAttributionID(args);
681707
}
682708

683709
/*

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

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public String toString(){
6666

6767
public class CountlyReactNative extends ReactContextBaseJavaModule {
6868

69-
public static final String TAG = "CountlyReactNative";
69+
public static final String TAG = "CountlyReactNativePlugin";
7070
private String COUNTLY_RN_SDK_VERSION_STRING = "20.04.7";
7171
private String COUNTLY_RN_SDK_NAME = "js-rnb-android";
7272

@@ -119,8 +119,13 @@ public void init(ReadableArray args, Promise promise){
119119
Countly.sharedInstance().COUNTLY_SDK_VERSION_STRING = COUNTLY_RN_SDK_VERSION_STRING;
120120

121121
this.config.setContext(_reactContext);
122-
Activity activity = getCurrentActivity();
123-
this.config.setApplication(activity.getApplication());
122+
Activity activity = getActivity();
123+
if (activity != null) {
124+
this.config.setApplication(activity.getApplication());
125+
}
126+
else {
127+
log("init, Activity is null, some features will not work", LogLevel.WARNING);
128+
}
124129
if(deviceId == null || "".equals(deviceId)){
125130
}else{
126131
if(deviceId.equals("TemporaryDeviceID")){
@@ -504,7 +509,11 @@ public void callback(String result) {
504509

505510
@ReactMethod
506511
public void askForNotificationPermission(ReadableArray args){
507-
Activity activity = this._reactContext.getCurrentActivity();
512+
Activity activity = this.getActivity();
513+
if (activity == null) {
514+
log("askForNotificationPermission failed, Activity is null", LogLevel.ERROR);
515+
return;
516+
}
508517
Context context = this._reactContext;
509518
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
510519
NotificationManager notificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
@@ -532,7 +541,12 @@ public void onComplete(Task<InstanceIdResult> task) {
532541

533542
@ReactMethod
534543
public void start(){
535-
Countly.sharedInstance().onStart(getCurrentActivity());
544+
Activity activity = this.getActivity();
545+
if (activity == null) {
546+
log("start failed, Activity is null", LogLevel.ERROR);
547+
return;
548+
}
549+
Countly.sharedInstance().onStart(activity);
536550
}
537551

538552
@ReactMethod
@@ -778,7 +792,11 @@ public void remoteConfigClearValues(Promise promise){
778792

779793
@ReactMethod
780794
public void showStarRating(ReadableArray args, final Callback callback){
781-
Activity activity = getCurrentActivity();
795+
Activity activity = getActivity();
796+
if (activity == null) {
797+
log("showStarRating failed, Activity is null", LogLevel.ERROR);
798+
return;
799+
}
782800
Countly.sharedInstance().ratings().showStarRating(activity, new StarRatingCallback(){
783801

784802
@Override
@@ -796,9 +814,13 @@ public void onDismiss() {
796814

797815
@ReactMethod
798816
public void showFeedbackPopup(ReadableArray args){
817+
Activity activity = getActivity();
818+
if (activity == null) {
819+
log("showFeedbackPopup failed, Activity is null", LogLevel.ERROR);
820+
return;
821+
}
799822
String widgetId = args.getString(0);
800823
String closeFeedBackButton = args.getString(1);
801-
Activity activity = getCurrentActivity();
802824
Countly.sharedInstance().ratings().showFeedbackPopup( widgetId, closeFeedBackButton, activity, null);
803825
}
804826

@@ -864,6 +886,12 @@ public void enableApm(ReadableArray args){
864886
public void enableAttribution(){
865887
this.config.setEnableAttribution(true);
866888
}
889+
890+
@ReactMethod
891+
public void recordAttributionID(ReadableArray args){
892+
String attributionID = args.getString(0);
893+
log("recordAttributionID: Not implemented for Android");
894+
}
867895

868896
enum LogLevel {INFO, DEBUG, VERBOSE, WARNING, ERROR}
869897
static void log(String message, LogLevel logLevel) {
@@ -893,4 +921,13 @@ static void log(String message, Throwable tr, LogLevel logLevel) {
893921
}
894922
}
895923

924+
Activity getActivity() {
925+
Activity activity = getCurrentActivity();
926+
if(activity == null && _reactContext != null)
927+
{
928+
activity = _reactContext.getCurrentActivity();
929+
}
930+
return activity;
931+
}
932+
896933
}

example/Example.js

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
11
import React, { Component } from 'react';
22
import { Text, Button, ScrollView, Image, View, Alert } from 'react-native';
33
import Countly from 'countly-sdk-react-native-bridge';
4+
/*
5+
First add "react-native-permissions" and "react-native-idfa" plugins to implement the attribution feature for iOS.
6+
Here is the link of both plugins:
7+
https://www.npmjs.com/package/react-native-permissions
8+
https://www.npmjs.com/package/react-native-idfa
9+
10+
Here is the required import from above mentioned plugins
11+
12+
import {request, PERMISSIONS, RESULTS} from 'react-native-permissions';
13+
import { IDFA } from 'react-native-idfa';
14+
*/
415

516
var successCodes = [100, 101, 200, 201, 202, 205, 300, 301, 303, 305];
617
var failureCodes = [400, 402, 405, 408, 500, 501, 502, 505];
@@ -53,15 +64,61 @@ class Example extends Component {
5364
// Countly.pinnedCertificates("count.ly.cer"); // It will ensure that connection is made with one of the public keys specified
5465
// Countly.setHttpPostForced(false); // Set to "true" if you want HTTP POST to be used for all requests
5566
Countly.enableApm(); // Enable APM features, which includes the recording of app start time.
56-
Countly.enableAttribution(); // Enable to measure your marketing campaign performance by attributing installs from specific campaigns.
67+
Countly.pushTokenType(Countly.messagingMode.DEVELOPMENT, "Channel Name", "Channel Description"); // Set messaging mode for push notifications
68+
if (!Platform.OS.match("ios")){
69+
Countly.enableAttribution(); // Enable to measure your marketing campaign performance by attributing installs from specific campaigns.
70+
}
71+
/*
72+
For iOS 14+ apple changes regarding app tracking you need to ask the user for permission to track app.
73+
For permission you can use this plugin
74+
https://www.npmjs.com/package/react-native-permissions
75+
76+
For IDFA you can use this plugin
77+
https://www.npmjs.com/package/react-native-idfa
78+
79+
Below is the example app that how you can use both these plugins Countly SDK iOS attibution feature.
80+
81+
if (Platform.OS.match("ios")) {
82+
request(PERMISSIONS.IOS.APP_TRACKING_TRANSPARENCY)
83+
.then((result) => {
84+
switch (result) {
85+
case RESULTS.UNAVAILABLE:
86+
console.log(
87+
'This feature is not available (on this device / in this context)',
88+
);
89+
break;
90+
case RESULTS.DENIED:
91+
console.log(
92+
'The permission has not been requested / is denied but requestable',
93+
);
94+
break;
95+
case RESULTS.GRANTED:
96+
console.log('The permission is granted');
97+
IDFA.getIDFA().then((idfa) => {
98+
console.log('idfa : ' + idfa);
99+
Countly.recordAttributionID(idfa);
100+
})
101+
.catch((e) => {
102+
console.error(e);
103+
});
104+
break;
105+
case RESULTS.BLOCKED:
106+
console.log('The permission is denied and not requestable anymore');
107+
break;
108+
}
109+
})
110+
.catch((error) => {
111+
// …
112+
});
113+
}
114+
*/
57115

58116
await Countly.init("https://master.count.ly", "5b77e4c785410351f32d8aa286d2383195d13b93", "123456"); // Initialize the countly SDK.
59117

60118
/**
61119
* Push notifications settings
62120
* Should be call after init
63121
*/
64-
Countly.pushTokenType(Countly.messagingMode.DEVELOPMENT, "Channel Name", "Channel Description"); // Set messaging mode for push notifications
65122
Countly.registerForNotification(function(theNotification){
66123
console.log("Just received this notification data: " + JSON.stringify(theNotification));
67124
alert('theNotification: ' + JSON.stringify(theNotification));

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
@@ -63,4 +63,5 @@ typedef void (^Result)(id _Nullable result);
6363
- (void)enableApm:(NSArray*_Nullable)arguments;
6464

6565
- (void)enableAttribution;
66+
- (void)recordAttributionID:(NSArray*_Nullable)arguments;
6667
@end

ios/src/CountlyReactNative.m

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -941,6 +941,21 @@ + (void) log: (NSString *) theMessage{
941941
});
942942
}
943943

944+
RCT_EXPORT_METHOD(recordAttributionID:(NSArray*)arguments) {
945+
dispatch_async(dispatch_get_main_queue(), ^ {
946+
NSString* attributionID = [arguments objectAtIndex:0];
947+
if(CountlyCommon.sharedInstance.hasStarted) {
948+
[Countly.sharedInstance recordAttributionID: attributionID];
949+
}
950+
else {
951+
if (config == nil){
952+
config = CountlyConfig.new;
953+
}
954+
config.attributionID = attributionID;
955+
}
956+
});
957+
}
958+
944959
- (void)addCountlyFeature:(CLYFeature)feature
945960
{
946961
if(countlyFeatures == nil) {
@@ -972,7 +987,7 @@ void CountlyRNInternalLog(NSString *format, ...)
972987
va_start(args, format);
973988

974989
NSString* logString = [NSString.alloc initWithFormat:format arguments:args];
975-
NSLog(@"[CountlyReactNative] %@", logString);
990+
NSLog(@"[CountlyReactNativePlugin] %@", logString);
976991

977992
va_end(args);
978993
}

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.4.7",
3+
"version": "20.4.8",
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)