Comments (9)
Hi @Sinapse87,
I'm not sure what you are asking. If you look at 1.5.1 in test_app there is an example of using synchronous as opposed to asynchronous.
The call to datafileHandler.downloadDatafile(context, projectId, null);
actually updates the cache with the latest datafile from CDN. So, if you wanted to use the latest, you could do is something like the following:
if (optimizelyManager.isDatafileCached(myApplication)) {
optimizelyManager.initialize(myApplication);
} else {
optimizelyManager.initialize(myApplication, R.raw.datafile);
}
You could have the data file in your bundle, like above or in code as a string datafile. The app would initialize with the datafile passed in. You also have access to the cached datafile directly to pass in or augment before passing it in. Does that answer your question?
from android-sdk.
Hi Thomas, thanks for your answer but it does not answer the question. We to initialize everything in out Dependency Injection framework, Dagger.
This is the code in the OptimizelyManager.java:
`
/**
* Initialize Optimizely Synchronously
*
* Instantiates and returns an {@link OptimizelyClient} instance. Will also cache the instance
* for future lookups via getClient
*
* @param context any {@link Context} instance
* @param datafile the datafile
* @return an {@link OptimizelyClient} instance
*/
public OptimizelyClient initialize(@nonnull Context context, @nonnull String datafile) {
if (!isAndroidVersionSupported()) {
return optimizelyClient;
}
try {
optimizelyClient = buildOptimizely(context, datafile);
} catch (ConfigParseException e) {
logger.error("Unable to parse compiled data file", e);
} catch (Exception e) {
logger.error("Unable to build OptimizelyClient instance", e);
} catch (Error e) {
logger.error("Unable to build OptimizelyClient instance", e);
}
datafileHandler.downloadDatafile(context, projectId, null);
return optimizelyClient;
}
`
Unfortunately:
datafileHandler.downloadDatafile(context, projectId, null);
We do not see the above updating the file from the cdn. It is downloading the file from the cdn, but not storing it, because you are passing null in the listener. in fact this is your code:
`
/**
* Asynchronous download data file.
*
* We create a DatafileService intent, create a DataService connection, and bind it to the application context.
* After we receive the datafile, we unbind the service and cleanup the service connection.
* This gets the project file from the Optimizely CDN.
*
* @param context application context
* @param projectId project id of the datafile to get
* @param listener listener to call when datafile download complete
*/
public void downloadDatafile(final Context context, String projectId, final DatafileLoadedListener listener) {
final Intent intent = new Intent(context.getApplicationContext(), DatafileService.class);
if (datafileServiceConnection == null) {
this.datafileServiceConnection = new DatafileServiceConnection(projectId, context.getApplicationContext(),
new DatafileLoadedListener() {
@RequiresApi(api = Build.VERSION_CODES.HONEYCOMB)
@OverRide
public void onDatafileLoaded(@nullable String dataFile) {
if (listener != null) {
listener.onDatafileLoaded(dataFile);
}
if (datafileServiceConnection != null && datafileServiceConnection.isBound()) {
context.getApplicationContext().unbindService(datafileServiceConnection);
datafileServiceConnection = null;
}
}
@Override
public void onStop(Context context) {
if (listener != null) {
listener.onStop(context);
}
}
});
context.getApplicationContext().bindService(intent, datafileServiceConnection, Context.BIND_AUTO_CREATE);
}
}
`
but the listener is null.
Am I misunderstanding something?
Thanks
from android-sdk.
Yes, you are missing what is happening in the DataServiceConnection. First, it uses its own internal DatafileDownloadListener that calls into the passed in listener if it exists. The DataServiceConnection creates a DatafileLoader that in turn creates a request. When this request is fulfilled, it saves it to the DatafileCache. So, the file is in data file cache. However, the cached file will never be used unless you explicitly check for it and use it as in the coding example I provided. Does that make sense?
from android-sdk.
Thomas, thanks for your answer.
So, are you suggesting to reinitialize the manager everytime we need to use it to see if there is a new version of the datafile being cached?
if (optimizelyManager.isDatafileCached(myApplication)) { optimizelyManager.initialize(myApplication); } else { optimizelyManager.initialize(myApplication, R.raw.datafile); }
from android-sdk.
No, that would not work. If you want to always use the CDN datafile, then I would use the async passing in the onStartListener. That always goes to cache if there and downloads the latest if not. Generally, we suggest not initializing mid experience because the customer could get re-bucketed and get a inconsistent experience.
Can you tell me exactly what you are want to achieve? Do you always want to use the latest?
from android-sdk.
We are trying to achieve a simple happy path:
- App starts up and downloads the new datafile overriding the file in the raw folder.
- If optimizely server not responding the file in raw folder would have been used.
Generally, we suggest not initializing mid experience because the customer could get re-bucketed and get a inconsistent experience.
in that case, why do we have to provide a "datafileDownloadInterval"?
Sorry, I feel this is not being documented very well.
from android-sdk.
No need to apologize, we are revamping our initialize because others are also finding it confusing. I would suggest using the synchronous version I mentioned above. You don't have to provide a datafileDownloadInterval. If you provide one, the datafile will be periodically polled at that interval and if a new file is found it is downloaded. If you don't provide a datafile download interval, then there will not be periodic downloads. But, you would still get a download from the initialize. The idea being that the next time you start up, you can use that downloaded datafile from cache. It is always downloaded to cache. We are thinking about adding a listener that is called when the cached file has changed.
from android-sdk.
Hi Thomas, thanks for your answer!
So, first of all, we still have three issue:
- Even specifying an interval, the datafile is not being pulled down. We specify 30 seconds for example, but we do not see any network call at all, excluding the first one. Not sure why the interval is multiplied per 1000 here:
` /**
* Start background checks if the the project datafile jas been updated. This starts an alarm service that checks to see if there is a
* new datafile to download at interval provided. If there is a update, the new datafile is cached.
*
* @param context application context
* @param updateInterval frequency of updates in seconds
*/
public void startBackgroundUpdates(Context context, String projectId, Long updateInterval) {
enableBackgroundCache(context, projectId);
AlarmManager alarmManager = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
ServiceScheduler.PendingIntentFactory pendingIntentFactory = new ServiceScheduler
.PendingIntentFactory(context.getApplicationContext());
ServiceScheduler serviceScheduler = new ServiceScheduler(alarmManager, pendingIntentFactory,
LoggerFactory.getLogger(ServiceScheduler.class));
Intent intent = new Intent(context.getApplicationContext(), DatafileService.class);
intent.putExtra(DatafileService.EXTRA_PROJECT_ID, projectId);
serviceScheduler.schedule(intent, updateInterval * 1000);
}
`
-
Using the approach you are suggesting, the user will not get the new datafile when the the app starts up. He will only get the previous datafile (from the cache) and the new datafile will override the new one but it will not be used.
-
Changing experiments on the server, does change the datafile on the server, but it does not push it down to the CDN, in fact we keep getting the old datafile and an http 304.
I opened a support ticket too, but no answer.
We are thinking about adding a listener that is called when the cached file has changed.
Yes, this is exactly what I suggest in the first message. Currently, null is being passed rather than a listener. Even if you just pass the listener present in the manager, that could be enough for us to have a callback and upload the datafile manually. A much better solution would have that listener to update the datafile.
Let me know if I got something wrong, please
Thanks
from android-sdk.
developer docs are updated along with simpler initialize options
from android-sdk.
Related Issues (20)
- slack test
- Optimizely does not initialize without proguard rule for Gson HOT 6
- Update SDK's dependencies HOT 2
- ConcurrentModificationException in NotificationManager.addHandler() HOT 3
- Issues targeting android 12 (API 31) HOT 5
- StrictMode violation due to Deflater.end() not being called HOT 1
- `updateConfigOnNewDatafile` does nothing HOT 2
- Unable to exclude users from experiment HOT 4
- isFeatureEnabled is failing some times HOT 2
- List all Flags available HOT 2
- AD Blocker is blocking the data sync HOT 2
- `Parcel.createExceptionOrNull` due to too many scheduled jobs HOT 5
- DatafileClient should specify read/write timeout on urlConnection HOT 3
- Crash in WorkerScheduler.startService HOT 12
- 2 files found with path 'android-logger.properties' from inputs HOT 6
- Wrong conversion rates while tracking feature flags HOT 2
- Crash with java.lang.ExceptionInInitializerError caused by java.lang.IllegalStateException: FileLogger is not initialized. Forgot to call Log4O.init()? HOT 6
- Reporting a vulnerability HOT 1
- ResourcesNotFoundException thrown during initialisaiton HOT 3
- [BUG] Setting initialize()'s updateConfigOnNewDatafile=false is ignored by DefaultDatafileHandler HOT 5
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from android-sdk.