Skip to content

Commit 9fa527a

Browse files
authored
Merge pull request #13 from optimizely/josh/android-proxy
Adds AndroidOptimizely class
2 parents 1e0ea05 + 377a9d4 commit 9fa527a

File tree

9 files changed

+228
-19
lines changed

9 files changed

+228
-19
lines changed

.idea/misc.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

android-sdk/src/androidTest/java/com/optimizely/ab/android/sdk/OptimizelyManagerTest.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import android.support.test.espresso.core.deps.guava.util.concurrent.MoreExecutors;
88
import android.support.test.runner.AndroidJUnit4;
99

10-
import com.optimizely.ab.Optimizely;
1110
import com.optimizely.ab.android.shared.ServiceScheduler;
1211
import com.optimizely.user_experiment_record.AndroidUserExperimentRecord;
1312

@@ -118,7 +117,7 @@ public void injectOptimizely() {
118117
verify(userExperimentRecord).start();
119118
verify(serviceScheduler).schedule(captor.capture(), TimeUnit.HOURS.toMillis(1L));
120119
verify(logger).info("Sending Optimizely instance to listener");
121-
verify(startListener).onStart(any(Optimizely.class));
120+
verify(startListener).onStart(any(AndroidOptimizely.class));
122121
}
123122

124123
@Test
@@ -140,7 +139,7 @@ public void injectOptimizelyNullListener() {
140139
verify(userExperimentRecord).start();
141140
verify(serviceScheduler).schedule(captor.capture(), eq(TimeUnit.HOURS.toMillis(1L)));
142141
verify(logger).info("No listener to send Optimizely to");
143-
verify(startListener, never()).onStart(any(Optimizely.class));
142+
verify(startListener, never()).onStart(any(AndroidOptimizely.class));
144143

145144
Intent intent = captor.getValue();
146145
assertTrue(intent.getComponent().getShortClassName().contains("DataFileService"));
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
package com.optimizely.ab.android.sdk;
2+
3+
import android.app.Activity;
4+
import android.support.annotation.NonNull;
5+
import android.support.annotation.Nullable;
6+
7+
import com.optimizely.ab.Optimizely;
8+
import com.optimizely.ab.UnknownEventTypeException;
9+
import com.optimizely.ab.UnknownExperimentException;
10+
import com.optimizely.ab.config.Experiment;
11+
import com.optimizely.ab.config.ProjectConfig;
12+
import com.optimizely.ab.config.Variation;
13+
14+
import org.slf4j.Logger;
15+
import org.slf4j.LoggerFactory;
16+
17+
import java.util.Map;
18+
19+
/**
20+
* Wraps {@link Optimizely} instances
21+
*
22+
* This proxy ensures that the Android SDK will not crash if the inner Optimizely SDK
23+
* failed to start. When Optimizely fails to start via {@link OptimizelyManager#start(Activity, OptimizelyStartListener)}
24+
* there will be no cached instance returned from {@link OptimizelyManager#getOptimizely()}. By accessing
25+
* Optimizely through this interface checking for null is not required. If Optimizely is null warnings
26+
* will be logged.
27+
*/
28+
public class AndroidOptimizely {
29+
30+
Logger logger = LoggerFactory.getLogger(AndroidOptimizely.class);
31+
32+
@Nullable private Optimizely optimizely;
33+
34+
public AndroidOptimizely(@Nullable Optimizely optimizely) {
35+
this.optimizely = optimizely;
36+
}
37+
38+
/**
39+
* @see Optimizely#activate(String, String)
40+
*/
41+
public @Nullable Variation activate(@NonNull String experimentKey,
42+
@NonNull String userId) throws UnknownExperimentException {
43+
if (optimizely != null) {
44+
return optimizely.activate(experimentKey, userId);
45+
} else {
46+
logger.warn("Optimizely is not initialized, can't activate experiment {} for {}",
47+
experimentKey, userId);
48+
return null;
49+
}
50+
}
51+
52+
/**
53+
* @see Optimizely#activate(String, String, Map)
54+
*/
55+
public @Nullable Variation activate(@NonNull String experimentKey,
56+
@NonNull String userId,
57+
@NonNull Map<String, String> attributes) throws UnknownExperimentException {
58+
if (optimizely != null) {
59+
return optimizely.activate(experimentKey, userId, attributes);
60+
} else {
61+
logger.warn("Optimizely is not initialized, can't activate experiment {} for user {} " +
62+
"with attributes", experimentKey, userId);
63+
return null;
64+
}
65+
}
66+
67+
/**
68+
* @see Optimizely#activate(Experiment, String)
69+
*/
70+
public @Nullable Variation activate(@NonNull Experiment experiment,
71+
@NonNull String userId) {
72+
if (optimizely != null) {
73+
return optimizely.activate(experiment, userId);
74+
} else {
75+
logger.warn("Optimizely is not initialized, can't activate experiment {} for user {}",
76+
experiment.getKey(), userId);
77+
return null;
78+
}
79+
}
80+
81+
public @Nullable Variation activate(@NonNull Experiment experiment,
82+
@NonNull String userId,
83+
@NonNull Map<String, String> attributes) {
84+
if (optimizely != null) {
85+
return optimizely.activate(experiment, userId, attributes);
86+
} else {
87+
logger.warn("Optimizely is not initialized, can't activate experiment {} for user {}, " +
88+
"with attributes", experiment.getKey(), userId);
89+
return null;
90+
}
91+
}
92+
93+
94+
/**
95+
* @see Optimizely#track(String, String)
96+
*/
97+
public void track(@NonNull String eventName,
98+
@NonNull String userId) throws UnknownEventTypeException {
99+
if (optimizely != null) {
100+
optimizely.track(eventName, userId);
101+
} else {
102+
logger.warn("Optimizely is not initialized, could not track event {} for user {}", eventName, userId);
103+
}
104+
}
105+
106+
/**
107+
* @see Optimizely#track(String, String, Map)
108+
*/
109+
public void track(@NonNull String eventName,
110+
@NonNull String userId,
111+
@NonNull Map<String, String> attributes) throws UnknownEventTypeException {
112+
if (optimizely != null) {
113+
optimizely.track(eventName, userId, attributes);
114+
} else {
115+
logger.warn("Optimizely is not initialized, could not track event {} for user {}" +
116+
" with attributes", eventName, userId);
117+
}
118+
}
119+
120+
/**
121+
* @see Optimizely#track(String, String, long)
122+
*/
123+
public void track(@NonNull String eventName,
124+
@NonNull String userId,
125+
long eventValue) throws UnknownEventTypeException {
126+
if (optimizely != null) {
127+
optimizely.track(eventName, userId, eventValue);
128+
} else {
129+
logger.warn("Optimizely is not initialized, could not track event {} for user {}" +
130+
" with value {}", eventName, userId, eventValue);
131+
}
132+
}
133+
134+
/**
135+
* @see Optimizely#track(String, String, Map, long)
136+
*/
137+
public void track(@NonNull String eventName,
138+
@NonNull String userId,
139+
@NonNull Map<String, String> attributes,
140+
long eventValue) throws UnknownEventTypeException {
141+
if (optimizely != null) {
142+
optimizely.track(eventName, userId, attributes, eventValue);
143+
} else {
144+
logger.warn("Optimizely is not initialized, could not track event {} for user {}" +
145+
" with value {} and attributes", eventName, userId, eventValue);
146+
}
147+
}
148+
149+
150+
/**
151+
* @see Optimizely#getVariation(Experiment, String)
152+
*/
153+
public @Nullable Variation getVariation(@NonNull Experiment experiment,
154+
@NonNull String userId) throws UnknownExperimentException {
155+
if (optimizely != null) {
156+
return optimizely.getVariation(experiment, userId);
157+
} else {
158+
logger.warn("Optimizely is not initialized, could not get variation for experiment {} " +
159+
"for user {}", experiment.getKey(), userId);
160+
return null;
161+
}
162+
}
163+
164+
/**
165+
* @see Optimizely#getVariation(String, String)
166+
*/
167+
public @Nullable Variation getVariation(@NonNull String experimentKey,
168+
@NonNull String userId) throws UnknownExperimentException{
169+
if (optimizely != null) {
170+
return getVariation(experimentKey, userId);
171+
} else {
172+
logger.warn("Optimizely is not initialized, could not get variation for experiment {} " +
173+
"for user {}", experimentKey, userId);
174+
return null;
175+
}
176+
}
177+
178+
/**
179+
* @see Optimizely#getVariation(String, String, Map)
180+
*/
181+
public @Nullable Variation getVariation(@NonNull String experimentKey,
182+
@NonNull String userId,
183+
@NonNull Map<String, String> attributes) {
184+
if (optimizely != null) {
185+
return optimizely.getVariation(experimentKey, userId, attributes);
186+
} else {
187+
logger.warn("Optimizely is not initialized, could not get variation for experiment {} " +
188+
"for user {} with attributes", experimentKey, userId);
189+
return null;
190+
}
191+
}
192+
193+
/**
194+
* @see Optimizely#getVariation(ProjectConfig, Experiment, Map, String)
195+
*/
196+
public @Nullable Variation getVariation(@NonNull ProjectConfig projectConfig,
197+
@NonNull Experiment experiment,
198+
@NonNull Map<String, String> attributes,
199+
@NonNull String userId) {
200+
if (optimizely != null) {
201+
return optimizely.getVariation(projectConfig, experiment, attributes, userId);
202+
} else {
203+
logger.warn("Optimizely is not initialized, could not get variation for experiment {} " +
204+
"for user {} with attributes and project config", experiment.getKey(), userId);
205+
return null;
206+
}
207+
}
208+
}

android-sdk/src/main/java/com/optimizely/ab/android/sdk/OptimizelyManager.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
* Handles loading the Optimizely data file
3333
*/
3434
public class OptimizelyManager {
35-
@Nullable private static Optimizely optimizely;
35+
@NonNull private static AndroidOptimizely androidOptimizely = new AndroidOptimizely(null);
3636
@NonNull private final String projectId;
3737
@NonNull private final Long eventHandlerDispatchInterval;
3838
@NonNull private final TimeUnit eventHandlerDispatchIntervalTimeUnit;
@@ -107,8 +107,9 @@ public void stop(@NonNull Context context) {
107107
this.optimizelyStartListener = null;
108108
}
109109

110-
public Optimizely getOptimizely() {
111-
return optimizely;
110+
@NonNull
111+
public AndroidOptimizely getOptimizely() {
112+
return androidOptimizely;
112113
}
113114

114115
@NonNull
@@ -137,8 +138,9 @@ protected void onPostExecute(UserExperimentRecord userExperimentRecord) {
137138
.withUserExperimentRecord(userExperimentRecord)
138139
.build();
139140
logger.info("Sending Optimizely instance to listener");
140-
optimizelyStartListener.onStart(optimizely);
141-
OptimizelyManager.optimizely = optimizely;
141+
AndroidOptimizely androidOptimizely = new AndroidOptimizely(optimizely);
142+
optimizelyStartListener.onStart(androidOptimizely);
143+
OptimizelyManager.androidOptimizely = androidOptimizely;
142144
} else {
143145
logger.info("No listener to send Optimizely to");
144146
}
Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
package com.optimizely.ab.android.sdk;
22

3-
import com.optimizely.ab.Optimizely;
4-
53
/**
64
* Created by jdeffibaugh on 7/28/16 for Optimizely.
75
*/
86
public interface OptimizelyStartListener {
9-
void onStart(Optimizely optimizely);
7+
void onStart(AndroidOptimizely optimizely);
108
}

test-app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ repositories {
2828

2929
dependencies {
3030
// Includes SST Java core, event handler, and user experiment record
31-
// compile project(':android-sdk')
32-
compile 'com.optimizely.ab:android-sdk:0.0.1'
31+
compile project(':android-sdk')
32+
// compile 'com.optimizely.ab:android-sdk:0.0.1'
3333
compile 'com.google.code.gson:gson:2.6.2'
3434
compile 'com.android.support:appcompat-v7:23.0.1'
3535
compile 'com.android.support:design:23.0.1'

test-app/src/main/java/com/optimizely/ab/android/test_app/MainActivity.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import android.widget.Toast;
88

99
import com.optimizely.ab.Optimizely;
10+
import com.optimizely.ab.android.sdk.AndroidOptimizely;
1011
import com.optimizely.ab.android.sdk.OptimizelyManager;
1112
import com.optimizely.ab.android.sdk.OptimizelyStartListener;
1213
import com.optimizely.ab.config.Variation;
@@ -41,7 +42,7 @@ protected void onStart() {
4142

4243
optimizelyManager.start(this, new OptimizelyStartListener() {
4344
@Override
44-
public void onStart(Optimizely optimizely) {
45+
public void onStart(AndroidOptimizely optimizely) {
4546
Variation variation = optimizely.activate("experiment_1", "user_1");
4647

4748
if (variation != null) {

test-app/src/main/java/com/optimizely/ab/android/test_app/MyIntentService.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import android.content.Intent;
55

66
import com.optimizely.ab.Optimizely;
7+
import com.optimizely.ab.android.sdk.AndroidOptimizely;
78
import com.optimizely.ab.android.sdk.OptimizelyManager;
89

910
public class MyIntentService extends IntentService {
@@ -17,7 +18,7 @@ protected void onHandleIntent(Intent intent) {
1718
if (intent != null) {
1819
// Get Optimizely from the Intent that started this Service
1920
final OptimizelyManager optimizelyManager = ((MyApplication) getApplication()).getOptimizelyManager();
20-
Optimizely optimizely = optimizelyManager.getOptimizely();
21+
AndroidOptimizely optimizely = optimizelyManager.getOptimizely();
2122
if (optimizely != null) {
2223
optimizely.track("goal_3", "user_1");
2324
}

test-app/src/main/java/com/optimizely/ab/android/test_app/SecondaryActivity.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import android.os.Bundle;
77
import android.support.v7.app.AppCompatActivity;
88

9-
import com.optimizely.ab.Optimizely;
9+
import com.optimizely.ab.android.sdk.AndroidOptimizely;
1010
import com.optimizely.ab.android.sdk.OptimizelyManager;
1111

1212
public class SecondaryActivity extends AppCompatActivity {
@@ -18,7 +18,7 @@ protected void onCreate(Bundle savedInstanceState) {
1818

1919
// Get Optimizely from the Intent that started this Activity
2020
final OptimizelyManager optimizelyManager = ((MyApplication) getApplication()).getOptimizelyManager();
21-
Optimizely optimizely = optimizelyManager.getOptimizely();
21+
AndroidOptimizely optimizely = optimizelyManager.getOptimizely();
2222

2323
// track conversion event
2424
optimizely.track("goal_1", "user_1");
@@ -41,7 +41,7 @@ public static class SecondaryFragment extends Fragment {
4141
public void onStart() {
4242
super.onStart();
4343
final OptimizelyManager optimizelyManager = ((MyApplication) getActivity().getApplication()).getOptimizelyManager();
44-
Optimizely optimizely = optimizelyManager.getOptimizely();
44+
AndroidOptimizely optimizely = optimizelyManager.getOptimizely();
4545

4646
if (optimizely != null) {
4747
optimizely.track("goal_2", "user_1");

0 commit comments

Comments
 (0)