2222import android .content .Context ;
2323import android .content .Intent ;
2424import android .content .ServiceConnection ;
25+ import android .content .res .Resources ;
2526import android .os .AsyncTask ;
2627import android .os .Bundle ;
2728import android .os .IBinder ;
2829import android .support .annotation .NonNull ;
2930import android .support .annotation .Nullable ;
31+ import android .support .annotation .RawRes ;
3032
3133import com .optimizely .ab .Optimizely ;
3234import com .optimizely .ab .android .event_handler .OptlyEventHandler ;
3335import com .optimizely .ab .android .shared .ServiceScheduler ;
3436import com .optimizely .ab .bucketing .UserExperimentRecord ;
37+ import com .optimizely .ab .config .parser .ConfigParseException ;
3538import com .optimizely .ab .event .internal .payload .Event ;
3639import com .optimizely .user_experiment_record .AndroidUserExperimentRecord ;
3740
3841import org .slf4j .Logger ;
3942import org .slf4j .LoggerFactory ;
4043
44+ import java .io .IOException ;
45+ import java .io .InputStream ;
4146import java .util .concurrent .Executor ;
4247import java .util .concurrent .Executors ;
4348import java .util .concurrent .TimeUnit ;
@@ -128,6 +133,38 @@ public AndroidOptimizely getOptimizely() {
128133 return androidOptimizely ;
129134 }
130135
136+ @ NonNull
137+ public AndroidOptimizely getOptimizely (@ NonNull Context context , @ RawRes int dataFileRes ) {
138+ AndroidUserExperimentRecord userExperimentRecord =
139+ (AndroidUserExperimentRecord ) AndroidUserExperimentRecord .newInstance (getProjectId (), context );
140+ // Blocking File I/O is necessary here in order to provide a synchronous API
141+ // The User Experiment Record is started off the of the main thread when starting
142+ // asynchronously. Starting simply creates the file if it doesn't exist so it's not
143+ // terribly expensive. Blocking the UI the thread prevents touch input...
144+ userExperimentRecord .start ();
145+ try {
146+ androidOptimizely = buildOptimizely (context , loadRawResource (context , dataFileRes ), userExperimentRecord );
147+ } catch (ConfigParseException e ) {
148+ logger .error ("Unable to parse compiled data file" , e );
149+ } catch (IOException e ) {
150+ logger .error ("Unable to load compiled data file" , e );
151+ }
152+
153+ return androidOptimizely ;
154+ }
155+
156+ private String loadRawResource (Context context , @ RawRes int rawRes ) throws IOException {
157+ Resources res = context .getResources ();
158+ InputStream in = res .openRawResource (rawRes );
159+ byte [] b = new byte [in .available ()];
160+ int read = in .read (b );
161+ if (read > -1 ) {
162+ return new String (b );
163+ } else {
164+ throw new IOException ("Couldn't parse raw res fixture, no bytes" );
165+ }
166+ }
167+
131168 @ NonNull
132169 public String getProjectId () {
133170 return projectId ;
@@ -148,16 +185,8 @@ protected void onPostExecute(UserExperimentRecord userExperimentRecord) {
148185 serviceScheduler .schedule (intent , dataFileDownloadIntervalTimeUnit .toMillis (dataFileDownloadInterval ));
149186
150187 try {
151- OptlyEventHandler eventHandler = OptlyEventHandler .getInstance (context );
152- eventHandler .setDispatchInterval (eventHandlerDispatchInterval , eventHandlerDispatchIntervalTimeUnit );
153- Optimizely optimizely = Optimizely .builder (dataFile , eventHandler )
154- .withUserExperimentRecord (userExperimentRecord )
155- .withClientEngine (Event .ClientEngine .ANDROID_SDK )
156- .withClientVersion (BuildConfig .CLIENT_VERSION )
157- .build ();
188+ OptimizelyManager .androidOptimizely = buildOptimizely (context , dataFile , userExperimentRecord );
158189 logger .info ("Sending Optimizely instance to listener" );
159- AndroidOptimizely androidOptimizely = new AndroidOptimizely (optimizely );
160- OptimizelyManager .androidOptimizely = androidOptimizely ;
161190
162191 if (optimizelyStartListener != null ) {
163192 optimizelyStartListener .onStart (androidOptimizely );
@@ -176,6 +205,17 @@ protected void onPostExecute(UserExperimentRecord userExperimentRecord) {
176205 initUserExperimentRecordTask .executeOnExecutor (executor );
177206 }
178207
208+ private AndroidOptimizely buildOptimizely (@ NonNull Context context , @ NonNull String dataFile , @ NonNull UserExperimentRecord userExperimentRecord ) throws ConfigParseException {
209+ OptlyEventHandler eventHandler = OptlyEventHandler .getInstance (context );
210+ eventHandler .setDispatchInterval (eventHandlerDispatchInterval , eventHandlerDispatchIntervalTimeUnit );
211+ Optimizely optimizely = Optimizely .builder (dataFile , eventHandler )
212+ .withUserExperimentRecord (userExperimentRecord )
213+ .withClientEngine (Event .ClientEngine .ANDROID_SDK )
214+ .withClientVersion (BuildConfig .CLIENT_VERSION )
215+ .build ();
216+ return new AndroidOptimizely (optimizely );
217+ }
218+
179219 public static class OptlyActivityLifecycleCallbacks implements Application .ActivityLifecycleCallbacks {
180220
181221 @ NonNull private OptimizelyManager optimizelyManager ;
0 commit comments