Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
a749f11
add cmab support
jaeopt Oct 21, 2025
4ca1e42
fix cmab
jaeopt Oct 22, 2025
b840dc9
clean up
jaeopt Oct 23, 2025
4f077f3
clean up
jaeopt Oct 23, 2025
1ee5ba6
add cmab config
jaeopt Oct 23, 2025
35a3876
more tests
jaeopt Oct 23, 2025
162e766
add more tests
jaeopt Oct 23, 2025
c5e178c
fix with cmab builder
jaeopt Oct 28, 2025
13bc880
upgrade android to 35
jaeopt Oct 29, 2025
ca86f4e
upgrade targetSDK and gradle versions
jaeopt Oct 29, 2025
8d660b3
clean up github workflow
jaeopt Oct 29, 2025
6f6407a
fix gradle settings
jaeopt Oct 29, 2025
f612e79
clean up
jaeopt Oct 29, 2025
23536be
fix for API 21 tests
jaeopt Oct 29, 2025
fccb5cd
clean up
jaeopt Oct 29, 2025
dd47d8d
Merge branch 'jae/upgrade-android-api' into jae/FSSDK-11136
jaeopt Oct 29, 2025
f12e872
add cmab support
jaeopt Oct 21, 2025
9949c71
fix cmab
jaeopt Oct 22, 2025
f62d141
clean up
jaeopt Oct 23, 2025
4e4eb46
clean up
jaeopt Oct 23, 2025
07ed767
add cmab config
jaeopt Oct 23, 2025
11f89c8
more tests
jaeopt Oct 23, 2025
8cda9b2
add more tests
jaeopt Oct 23, 2025
50b0be9
fix with cmab builder
jaeopt Oct 28, 2025
f57eefa
local maven
jaeopt Oct 29, 2025
762c44b
fix cmabservice instantiation
jaeopt Oct 29, 2025
cb1d9ea
fix cmab interfaces
jaeopt Oct 30, 2025
969180c
fix for java-sdk changes
jaeopt Oct 30, 2025
4faabd2
testing
jaeopt Oct 30, 2025
70a3039
fix cmab tests
jaeopt Oct 31, 2025
2b2497f
fix cmab tests
jaeopt Oct 31, 2025
57541f7
maven local support
jaeopt Oct 31, 2025
7834c92
fix conflicts
jaeopt Oct 31, 2025
c7a237b
clean up
jaeopt Oct 31, 2025
2da0445
fix conflicts
jaeopt Oct 31, 2025
6a87840
add blocking async api
jaeopt Oct 31, 2025
826f8c5
clean up android user context
jaeopt Nov 3, 2025
a8d1ffa
clean up androd user contexts for testability
jaeopt Nov 3, 2025
929e676
cmab endpoint configurable
jaeopt Nov 12, 2025
1c2ae64
fix cmab in test-app
jaeopt Nov 24, 2025
2a23966
fix cmab in test-app
jaeopt Nov 24, 2025
c68eae3
add sample cmab tests
jaeopt Nov 24, 2025
ba2d3b7
clean up
jaeopt Nov 24, 2025
0491b57
clean up
jaeopt Nov 24, 2025
b127a64
clean up
jaeopt Nov 25, 2025
c649dea
fix cmab endpoint config
jaeopt Nov 25, 2025
3564b8f
fix tests
jaeopt Nov 25, 2025
eb1cbe6
fix tests
jaeopt Nov 25, 2025
e56dca7
add sample for blocking async
jaeopt Nov 25, 2025
fb665ea
clean up
jaeopt Nov 25, 2025
274b23a
fix per reviews
jaeopt Nov 25, 2025
f27b135
clean up
jaeopt Nov 25, 2025
bfa1db9
clean up
jaeopt Nov 25, 2025
8d72196
clean up
jaeopt Nov 26, 2025
b85e1a6
clean up local maven
jaeopt Dec 11, 2025
79a293b
clean up
jaeopt Dec 11, 2025
641574c
decideBlocking
jaeopt Dec 11, 2025
8df7d30
clean up
jaeopt Dec 11, 2025
d7b9237
clean up
jaeopt Dec 12, 2025
b43648e
fix per reviews
jaeopt Dec 12, 2025
23d33c2
fix tests
jaeopt Dec 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ public void setup() throws Exception {
notificationCenter,
null,
odpManager,
null,
"test-vuid",
null,
null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import com.optimizely.ab.OptimizelyUserContext;
import com.optimizely.ab.android.event_handler.DefaultEventHandler;
import com.optimizely.ab.bucketing.Bucketer;
import com.optimizely.ab.bucketing.DecisionPath;
import com.optimizely.ab.bucketing.DecisionService;
import com.optimizely.ab.config.Experiment;
import com.optimizely.ab.config.ProjectConfig;
Expand Down Expand Up @@ -132,20 +133,23 @@ public OptimizelyClientTest(int datafileVersion,String datafile){

// set to return DecisionResponse with null variation by default (instead of null DecisionResponse)
when(bucketer.bucket(any(), any(), any())).thenReturn(DecisionResponse.nullNoReasons());
when(bucketer.bucket(any(), any(), any(), any())).thenReturn(DecisionResponse.nullNoReasons());

if(datafileVersion==3) {
Variation variation = optimizely.getProjectConfig().getExperiments().get(0).getVariations().get(0);
when(bucketer.bucket(
optimizely.getProjectConfig().getExperiments().get(0),
GENERIC_USER_ID,
optimizely.getProjectConfig())
eq(optimizely.getProjectConfig().getExperiments().get(0)),
eq(GENERIC_USER_ID),
any(ProjectConfig.class),
any())
).thenReturn(DecisionResponse.responseNoReasons(variation));
} else {
Variation variation = optimizely.getProjectConfig().getExperimentKeyMapping().get(FEATURE_MULTI_VARIATE_EXPERIMENT_KEY).getVariations().get(1);
when(bucketer.bucket(
optimizely.getProjectConfig().getExperimentKeyMapping().get(FEATURE_MULTI_VARIATE_EXPERIMENT_KEY),
GENERIC_USER_ID,
optimizely.getProjectConfig())
eq(optimizely.getProjectConfig().getExperimentKeyMapping().get(FEATURE_MULTI_VARIATE_EXPERIMENT_KEY)),
eq(GENERIC_USER_ID),
any(ProjectConfig.class),
any())
).thenReturn(DecisionResponse.responseNoReasons(variation));
}
spyOnConfig();
Expand Down Expand Up @@ -385,7 +389,7 @@ public void testGoodActivationBucketingId() {
Experiment experiment = optimizelyClient.getProjectConfig().getExperimentKeyMapping().get(FEATURE_ANDROID_EXPERIMENT_KEY);
attributes.put(BUCKETING_ATTRIBUTE, bucketingId);
Variation v = optimizelyClient.activate(FEATURE_ANDROID_EXPERIMENT_KEY, GENERIC_USER_ID, attributes);
verify(bucketer).bucket(experiment, bucketingId, optimizely.getProjectConfig());
verify(bucketer).bucket(eq(experiment), eq(bucketingId), eq(optimizely.getProjectConfig()), any());
}

@Test
Expand Down Expand Up @@ -910,7 +914,7 @@ public void testGoodGetVariationBucketingId() {
Map<String, String> attributes = new HashMap<>();
attributes.put(BUCKETING_ATTRIBUTE, bucketingId);
Variation v = optimizelyClient.getVariation("android_experiment_key", "userId", attributes);
verify(bucketer).bucket(experiment, bucketingId, optimizely.getProjectConfig());
verify(bucketer).bucket(eq(experiment), eq(bucketingId), eq(optimizely.getProjectConfig()), any());
}

@Test
Expand Down Expand Up @@ -2249,7 +2253,9 @@ public void testDecide() {
assertEquals(decision.getVariables().toMap(), variablesExpected.toMap());
assertEquals(decision.getRuleKey(), FEATURE_MULTI_VARIATE_EXPERIMENT_KEY);
assertEquals(decision.getFlagKey(), flagKey);
assertEquals(decision.getUserContext(), userContext);
OptimizelyUserContext decisionUserContext = decision.getUserContext();
assertEquals(decisionUserContext.getUserId(), userContext.getUserId());
assertEquals(decisionUserContext.getAttributes(), userContext.getAttributes());
assertTrue(decision.getReasons().isEmpty());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ public void initializeSyncWithEnvironment() {
EventHandler eventHandler = mock(DefaultEventHandler.class);
EventProcessor eventProcessor = mock(EventProcessor.class);
OptimizelyManager optimizelyManager = new OptimizelyManager(testProjectId, testSdkKey, null, logger, 3600L, datafileHandler, null, 3600L,
eventHandler, eventProcessor, null, null, null, null, null, null, null);
eventHandler, eventProcessor, null, null, null, null, null, null, null, null);
/*
* Scenario#1: when datafile is not Empty
* Scenario#2: when datafile is Empty
Expand Down Expand Up @@ -222,7 +222,7 @@ public void initializeAsyncWithEnvironment() {
EventHandler eventHandler = mock(DefaultEventHandler.class);
EventProcessor eventProcessor = mock(EventProcessor.class);
final OptimizelyManager optimizelyManager = new OptimizelyManager(testProjectId, testSdkKey, null, logger, 3600L, datafileHandler, null, 3600L,
eventHandler, eventProcessor, null, null, null, null, null, null, null);
eventHandler, eventProcessor, null, null, null, null, null, null, null, null);

/*
* Scenario#1: when datafile is not Empty
Expand Down Expand Up @@ -494,7 +494,7 @@ public void initializeSyncWithUpdateOnNewDatafileDisabled() {
Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();

OptimizelyManager manager = new OptimizelyManager(testProjectId, testSdkKey, null, logger, pollingInterval, datafileHandler, null, 0,
null, null, null, null, null, null, null, null, null);
null, null, null, null, null, null, null, null, null, null);

ArgumentCaptor<Context> contextCaptor = ArgumentCaptor.forClass(Context.class);
ArgumentCaptor<DatafileConfig> configCaptor = ArgumentCaptor.forClass(DatafileConfig.class);
Expand Down Expand Up @@ -533,7 +533,7 @@ public void initializeSyncWithUpdateOnNewDatafileEnabled() {
Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();

OptimizelyManager manager = new OptimizelyManager(testProjectId, testSdkKey, null, logger, pollingInterval, datafileHandler, null, 0,
null, null, null, null, null, null, null, null, null);
null, null, null, null, null, null, null, null, null, null);

ArgumentCaptor<Context> contextCaptor = ArgumentCaptor.forClass(Context.class);
ArgumentCaptor<DatafileConfig> configCaptor = ArgumentCaptor.forClass(DatafileConfig.class);
Expand Down Expand Up @@ -572,7 +572,7 @@ public void initializeSyncWithDownloadToCacheDisabled() {
Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();

OptimizelyManager manager = new OptimizelyManager(testProjectId, testSdkKey, null, logger, pollingInterval, datafileHandler, null, 0,
null, null, null, null, null, null, null, null, null);
null, null, null, null, null, null, null, null, null, null);

ArgumentCaptor<Context> contextCaptor = ArgumentCaptor.forClass(Context.class);
ArgumentCaptor<DatafileConfig> configCaptor = ArgumentCaptor.forClass(DatafileConfig.class);
Expand Down Expand Up @@ -611,7 +611,7 @@ public void initializeSyncWithUpdateOnNewDatafileDisabledWithPeriodicPollingEnab
Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();

OptimizelyManager manager = new OptimizelyManager(testProjectId, testSdkKey, null, logger, pollingInterval, datafileHandler, null, 0,
null, null, null, null, null, null, null, null, null);
null, null, null, null, null, null, null, null, null, null);

ArgumentCaptor<Context> contextCaptor = ArgumentCaptor.forClass(Context.class);
ArgumentCaptor<DatafileConfig> configCaptor = ArgumentCaptor.forClass(DatafileConfig.class);
Expand Down Expand Up @@ -651,7 +651,7 @@ public void initializeSyncWithUpdateOnNewDatafileEnabledWithPeriodicPollingEnabl
Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();

OptimizelyManager manager = new OptimizelyManager(testProjectId, testSdkKey, null, logger, pollingInterval, datafileHandler, null, 0,
null, null, null, null, null, null, null, null, null);
null, null, null, null, null, null, null, null, null, null);

ArgumentCaptor<Context> contextCaptor = ArgumentCaptor.forClass(Context.class);
ArgumentCaptor<DatafileConfig> configCaptor = ArgumentCaptor.forClass(DatafileConfig.class);
Expand Down Expand Up @@ -690,7 +690,7 @@ public void initializeSyncWithUpdateOnNewDatafileDisabledWithPeriodicPollingDisa
Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();

OptimizelyManager manager = new OptimizelyManager(testProjectId, testSdkKey, null, logger, pollingInterval, datafileHandler, null, 0,
null, null, null, null, null, null, null, null, null);
null, null, null, null, null, null, null, null, null, null);

ArgumentCaptor<Context> contextCaptor = ArgumentCaptor.forClass(Context.class);
ArgumentCaptor<DatafileConfig> configCaptor = ArgumentCaptor.forClass(DatafileConfig.class);
Expand All @@ -706,7 +706,7 @@ public void initializeSyncWithUpdateOnNewDatafileDisabledWithPeriodicPollingDisa

return datafileHandler;
}).when(manager.getDatafileHandler()).downloadDatafile(contextCaptor.capture(), configCaptor.capture(), listenerCaptor.capture());

OptimizelyClient client = manager.initialize(context, defaultDatafile, downloadToCache, updateConfigOnNewDatafile);

try {
Expand All @@ -730,7 +730,7 @@ public void initializeSyncWithUpdateOnNewDatafileEnabledWithPeriodicPollingDisab
Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();

OptimizelyManager manager = new OptimizelyManager(testProjectId, testSdkKey, null, logger, pollingInterval, datafileHandler, null, 0,
null, null, null, null, null, null, null, null, null);
null, null, null, null, null, null, null, null, null, null);

ArgumentCaptor<Context> contextCaptor = ArgumentCaptor.forClass(Context.class);
ArgumentCaptor<DatafileConfig> configCaptor = ArgumentCaptor.forClass(DatafileConfig.class);
Expand Down Expand Up @@ -769,7 +769,7 @@ public void initializeSyncWithResourceDatafileNoCache() {
Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();

OptimizelyManager manager = spy(new OptimizelyManager(testProjectId, testSdkKey, null, logger, pollingInterval, datafileHandler, null, 0,
null, null, null, null, null, null, null, null, null));
null, null, null, null, null, null, null, null, null, null));

datafileHandler.removeSavedDatafile(context, manager.getDatafileConfig());
OptimizelyClient client = manager.initialize(context, R.raw.datafile, downloadToCache, updateConfigOnNewDatafile);
Expand All @@ -786,7 +786,7 @@ public void initializeSyncWithResourceDatafileNoCacheWithDefaultParams() {
Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();

OptimizelyManager manager = spy(new OptimizelyManager(testProjectId, testSdkKey, null, logger, pollingInterval, datafileHandler, null, 0,
null, null, null, null, null, null, null, null, null));
null, null, null, null, null, null, null, null, null, null));

datafileHandler.removeSavedDatafile(context, manager.getDatafileConfig());
OptimizelyClient client = manager.initialize(context, R.raw.datafile);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -816,28 +816,33 @@ public OptimizelyConfig getOptimizelyConfig() {
* @return An OptimizelyUserContext associated with this OptimizelyClient.
*/
@Nullable
public OptimizelyUserContext createUserContext(@NonNull String userId,
@NonNull Map<String, Object> attributes) {
if (optimizely != null) {
return optimizely.createUserContext(userId, attributes);
} else {
public OptimizelyUserContextAndroid createUserContext(@NonNull String userId,
@NonNull Map<String, Object> attributes) {
if (optimizely == null) {
logger.warn("Optimizely is not initialized, could not create a user context");
return null;
}

if (userId == null) {
logger.warn("The userId parameter must be nonnull.");
return null;
}

return new OptimizelyUserContextAndroid(optimizely, userId, attributes);
}

@Nullable
public OptimizelyUserContext createUserContext(@NonNull String userId) {
public OptimizelyUserContextAndroid createUserContext(@NonNull String userId) {
return createUserContext(userId, Collections.emptyMap());
}

@Nullable
public OptimizelyUserContext createUserContext() {
public OptimizelyUserContextAndroid createUserContext() {
return createUserContext(Collections.emptyMap());
}

@Nullable
public OptimizelyUserContext createUserContext(@NonNull Map<String, Object> attributes) {
public OptimizelyUserContextAndroid createUserContext(@NonNull Map<String, Object> attributes) {
if (vuid == null) {
logger.warn("Optimizely vuid is not available. A userId is required to create a user context.");
return null;
Expand Down
Loading
Loading