Skip to content

Commit

Permalink
Implemented experiment info calls for flutter (#131)
Browse files Browse the repository at this point in the history
* Implemented experiment info calls for flutter

-- Added android native calls for experiment info
-- Added iOS native calls for experiment info
-- Updated underlying SDK's

* Updated changelog

* iOS: renamed 'CountlyExperimentInformation' class

* renamed 'ExperimentInformation' class

* updated native file after renaming
  • Loading branch information
ijunaid authored Sep 14, 2023
1 parent 4011308 commit 6724439
Show file tree
Hide file tree
Showing 30 changed files with 504 additions and 28 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
## 23.8.1
* Added `enrollABOnRCDownload` config method to enroll users to AB tests when downloading Remote Config values
* Fixed a bug where enabling consent requirements would enable consents for all features for Android
* Fixed a bug where enabling consent requirements would enable consents for all features for Android
* Added `testingDownloadExperimentInformation:` in remote config interface
* Added `testingGetAllExperimentInfo:` in remote config interface
* Updated underlying Android SDK version to 23.8.1
* Updated underlying iOS SDK version to 23.8.2

## 23.8.0
* ! Minor breaking change ! Manual view recording calls are now ignored if automatic view recording mode is enabled.
Expand Down
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@ android {
}

dependencies {
implementation 'ly.count.android:sdk:23.8.0'
implementation 'ly.count.android:sdk:23.8.1'
implementation 'com.google.firebase:firebase-messaging:20.2.1'
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

import ly.count.android.sdk.Countly;
import ly.count.android.sdk.CountlyConfig;
import ly.count.android.sdk.ExperimentInformation;
import ly.count.android.sdk.FeedbackRatingCallback;
import ly.count.android.sdk.ModuleFeedback.*;
import ly.count.android.sdk.DeviceIdType;
Expand Down Expand Up @@ -981,7 +982,41 @@ public void callback(RequestResult downloadResult, String error, boolean fullVal
});

result.success(null);
} else if ("remoteConfigTestingEnrollIntoVariant".equals(call.method)) {
}
else if ("testingDownloadExperimentInformation".equals(call.method)) {
int requestID = args.getInt(0);

log("testingDownloadExperimentInformation", LogLevel.WARNING);

Countly.sharedInstance().remoteConfig().testingDownloadExperimentInformation((rResult, error) -> {
if (requestID == requestIDNoCallback) {
return;
}
Map<String, Object> data = new HashMap<>();
data.put("error", error);
data.put("requestResult", resultResponder(rResult));
data.put("id", requestID);
methodChannel.invokeMethod("remoteConfigVariantCallback", data);
});

result.success(null);
}
else if ("testingGetAllExperimentInfo".equals(call.method)) {
Map<String, ExperimentInformation> experimentInfoMap = Countly.sharedInstance().remoteConfig().testingGetAllExperimentInfo();
List<Map<String, Object>> experimentInfoArray = new ArrayList<>();
for (Map.Entry<String, ExperimentInformation> entry : experimentInfoMap.entrySet()) {
ExperimentInformation experimentInfo = entry.getValue();
Map<String, Object> experimentInfoValue = new HashMap<>();
experimentInfoValue.put("experimentID", experimentInfo.experimentName);
experimentInfoValue.put("experimentName", experimentInfo.experimentName);
experimentInfoValue.put("experimentDescription", experimentInfo.experimentDescription);
experimentInfoValue.put("currentVariant", experimentInfo.currentVariant);
experimentInfoValue.put("variants", experimentInfo.variants);
experimentInfoArray.add(experimentInfoValue);
}
result.success(experimentInfoArray);
}
else if ("remoteConfigTestingEnrollIntoVariant".equals(call.method)) {
int requestID = args.getInt(0);
String key = args.getString(1);
String variant = args.getString(2);
Expand Down
2 changes: 1 addition & 1 deletion example-no-push/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,6 @@ dependencies {
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'ly.count.android:sdk:22.09.4'
implementation 'ly.count.android:sdk:23.8.1'
}

2 changes: 1 addition & 1 deletion example/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ dependencies {
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'ly.count.android:sdk:22.09.4'
implementation 'ly.count.android:sdk:23.8.1'
implementation 'com.google.firebase:firebase-messaging:20.2.1'
implementation(platform("org.jetbrains.kotlin:kotlin-bom:1.8.0"))
}
Expand Down
2 changes: 1 addition & 1 deletion example/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ subprojects {
project.evaluationDependsOn(':app')
}

task clean(type: Delete) {
tasks.register("clean", Delete) {
delete rootProject.buildDir
}
4 changes: 2 additions & 2 deletions example/ios/Flutter/Flutter.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#
# NOTE: This podspec is NOT to be published. It is only used as a local source!
# This is a generated file; do not edit or check into version control.
# This podspec is NOT to be published. It is only used as a local source!
# This is a generated file; do not edit or check into version control.
#

Pod::Spec.new do |s|
Expand Down
2 changes: 1 addition & 1 deletion example/ios/Podfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '11.0'
platform :ios, '11.0'

# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
Expand Down
6 changes: 3 additions & 3 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
PODS:
- countly_flutter (23.6.0):
- countly_flutter (23.8.0):
- Flutter
- Flutter (1.0.0)

Expand All @@ -14,9 +14,9 @@ EXTERNAL SOURCES:
:path: Flutter

SPEC CHECKSUMS:
countly_flutter: 4eeee607183664b871589250a0bd049cfd2697eb
countly_flutter: f153e5547d4f3cdf24be11f6ed4df32c9a421fa3
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854

PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3
PODFILE CHECKSUM: 7368163408c647b7eb699d0d788ba6718e18fb8d

COCOAPODS: 1.12.1
36 changes: 30 additions & 6 deletions example/ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,11 @@
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
Expand Down Expand Up @@ -490,7 +494,11 @@
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = CountlyNSE/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.2;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.countly.demo.CountlyNSE;
Expand All @@ -514,7 +522,11 @@
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = CountlyNSE/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.2;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.countly.demo.CountlyNSE;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand All @@ -537,7 +549,11 @@
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = CountlyNSE/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.2;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.countly.demo.CountlyNSE;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand Down Expand Up @@ -666,7 +682,11 @@
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
Expand Down Expand Up @@ -696,7 +716,11 @@
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
Expand Down
11 changes: 11 additions & 0 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'dart:io';
import 'dart:math';

import 'package:countly_flutter/countly_flutter.dart';
import 'package:countly_flutter/experiment_information.dart';
import 'package:flutter/material.dart';

final navigatorKey = GlobalKey<NavigatorState>();
Expand Down Expand Up @@ -150,6 +151,15 @@ class _MyAppState extends State<MyApp> {
Countly.changeDeviceId(Countly.deviceIDType['TemporaryDeviceID']!, false);
}

void remoteConfigDownloadExperimentInfo() {
Countly.instance.remoteConfig.testingDownloadExperimentInformation((rResult, error) async {
if(rResult == RequestResult.success) {
Map<String, ExperimentInformation> experimentInfoMap = await Countly.instance.remoteConfig.testingGetAllExperimentInfo();
print(experimentInfoMap);
}
});
}

void remoteConfigRegisterDownloadCallback() {
Countly.instance.remoteConfig.registerDownloadCallback(_rcDownloadCallback);
}
Expand Down Expand Up @@ -1080,6 +1090,7 @@ class _MyAppState extends State<MyApp> {
MyButton(text: 'Get AB testing values (Legacy)', color: 'green', onPressed: getABTestingValues),
MyButton(text: 'Record event for goal #1', color: 'green', onPressed: eventForGoal_1),
MyButton(text: 'Record event for goal #2', color: 'green', onPressed: eventForGoal_2),
MyButton(text: 'Remote Config Download Experiment Info', color: 'purple', onPressed: remoteConfigDownloadExperimentInfo),
MyButton(text: 'Remote Config Register Download Callback', color: 'purple', onPressed: remoteConfigRegisterDownloadCallback),
MyButton(text: 'Remote Config Remove Download Callback', color: 'purple', onPressed: remoteConfigRemoveDownloadCallback),
MyButton(text: 'Remote Config Download Values', color: 'purple', onPressed: remoteConfigDownloadKeys),
Expand Down
33 changes: 32 additions & 1 deletion ios/Classes/CountlyFlutterPlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -930,7 +930,38 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result
result(@"Success!");
});

} else if ([@"presentRatingWidgetWithID" isEqualToString:call.method]) {
} else if ([@"testingDownloadExperimentInformation" isEqualToString:call.method]) {
NSNumber *callbackID = [command objectAtIndex:0];
dispatch_async(dispatch_get_main_queue(), ^{
[Countly.sharedInstance.remoteConfig testingDownloadExperimentInformation:^(CLYRequestResult _Nonnull response, NSError * _Nonnull error) {
[self remoteConfigVariantCallback:callbackID response:response error:error];
}];
result(@"Success!");
});

} else if ([@"testingGetAllExperimentInfo" isEqualToString:call.method]) {
dispatch_async(dispatch_get_main_queue(), ^{
NSDictionary<NSString*, CountlyExperimentInformation*> * experiments = [Countly.sharedInstance.remoteConfig testingGetAllExperimentInfo];
NSMutableArray *experimentInfoArray = [NSMutableArray arrayWithCapacity:experiments.count];
[experiments enumerateKeysAndObjectsUsingBlock:^(NSString * key, CountlyExperimentInformation* experimentID, BOOL * stop)
{
NSMutableDictionary *experimentInfoValue = [NSMutableDictionary dictionaryWithCapacity:5];
experimentInfoValue[@"experimentID"] = experimentID.experimentID;
experimentInfoValue[@"experimentName"] = experimentID.experimentName;
experimentInfoValue[@"experimentDescription"] = experimentID.experimentDescription;
if(experimentID.currentVariant) {
experimentInfoValue[@"currentVariant"] = experimentID.currentVariant;
}
else
{
experimentInfoValue[@"currentVariant"] = @"null";
}
experimentInfoValue[@"variants"] = experimentID.variants;
[experimentInfoArray addObject:experimentInfoValue];
}];
result(experimentInfoArray);
});
} else if ([@"presentRatingWidgetWithID" isEqualToString:call.method]) {
dispatch_async(dispatch_get_main_queue(), ^{
NSString *widgetId = [command objectAtIndex:0];
[Countly.sharedInstance presentRatingWidgetWithID:widgetId
Expand Down
10 changes: 10 additions & 0 deletions ios/Classes/CountlyiOS/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
## 23.8.2
- Fixed rating feedback widget event key for widget closed event
- Added `testingDownloadExperimentInformation:` in remote config interface
- Added `testingGetAllExperimentInfo:` in remote config interface

## 23.8.1
- Expanded feedback widget functionality. Added ability to use rating widgets.
- Added functionality to access tags for feedback widgets.
- Fixed SPM public header issues of `CountlyViewTracking.h`

## 23.8.0
- Added `CountlyViewTracking:` interface with new view methods:
- `setGlobalViewSegmentation:`
Expand Down
4 changes: 2 additions & 2 deletions ios/Classes/CountlyiOS/Countly-PL.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'Countly-PL'
s.version = '23.8.0'
s.version = '23.8.2'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.summary = 'Countly is an innovative, real-time, open source mobile analytics platform.'
s.homepage = 'https://github.com/Countly/countly-sdk-ios'
Expand All @@ -17,7 +17,7 @@ Pod::Spec.new do |s|

s.subspec 'Core' do |core|
core.source_files = '*.{h,m}'
core.public_header_files = 'Countly.h', 'CountlyUserDetails.h', 'CountlyConfig.h', 'CountlyFeedbackWidget.h', 'CountlyRCData.h', 'CountlyRemoteConfig.h', 'CountlyViewTracking.h'
core.public_header_files = 'Countly.h', 'CountlyUserDetails.h', 'CountlyConfig.h', 'CountlyFeedbackWidget.h', 'CountlyRCData.h', 'CountlyRemoteConfig.h', 'CountlyViewTracking.h', 'CountlyExperimentInformation.h'
core.preserve_path = 'countly_dsym_uploader.sh'
core.ios.frameworks = ['Foundation', 'UIKit', 'UserNotifications', 'CoreLocation', 'WebKit', 'CoreTelephony', 'WatchConnectivity']
end
Expand Down
4 changes: 2 additions & 2 deletions ios/Classes/CountlyiOS/Countly.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'Countly'
s.version = '23.8.0'
s.version = '23.8.2'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.summary = 'Countly is an innovative, real-time, open source mobile analytics platform.'
s.homepage = 'https://github.com/Countly/countly-sdk-ios'
Expand All @@ -17,7 +17,7 @@ Pod::Spec.new do |s|

s.subspec 'Core' do |core|
core.source_files = '*.{h,m}'
core.public_header_files = 'Countly.h', 'CountlyUserDetails.h', 'CountlyConfig.h', 'CountlyFeedbackWidget.h', 'CountlyRCData.h', 'CountlyRemoteConfig.h', 'CountlyViewTracking.h'
core.public_header_files = 'Countly.h', 'CountlyUserDetails.h', 'CountlyConfig.h', 'CountlyFeedbackWidget.h', 'CountlyRCData.h', 'CountlyRemoteConfig.h', 'CountlyViewTracking.h', 'CountlyExperimentInformation.h'
core.preserve_path = 'countly_dsym_uploader.sh'
core.ios.frameworks = ['Foundation', 'UIKit', 'UserNotifications', 'CoreLocation', 'WebKit', 'CoreTelephony', 'WatchConnectivity']
end
Expand Down
2 changes: 1 addition & 1 deletion ios/Classes/CountlyiOS/CountlyCommon.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ @interface CountlyCommon ()
#endif
@end

NSString* const kCountlySDKVersion = @"23.8.0";
NSString* const kCountlySDKVersion = @"23.8.2";
NSString* const kCountlySDKName = @"objc-native-ios";

NSString* const kCountlyErrorDomain = @"ly.count.ErrorDomain";
Expand Down
23 changes: 23 additions & 0 deletions ios/Classes/CountlyiOS/CountlyExperimentInfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// CountlyExperimentInfo.h
//
// This code is provided under the MIT License.
//
// Please visit www.count.ly for more information.

#import <Foundation/Foundation.h>

@interface CountlyExperimentInfo : NSObject

@property (nonatomic, readonly) NSString* experimentID;
@property (nonatomic, readonly) NSString* experimentName;
@property (nonatomic, readonly) NSString* experimentDescription;
@property (nonatomic, readonly) NSString* currentVariant;
@property (nonatomic, readonly) NSDictionary* variants;


- (instancetype)initWithID:(NSString*)experimentID experimentName:(NSString*)experimentName experimentDescription:(NSString*)experimentDescription currentVariant:(NSString*)currentVariant variants:(NSDictionary*)variants;

@end



Loading

0 comments on commit 6724439

Please sign in to comment.