---
title: Initialize the Android SDK
slug: feature-experimentation/docs/initialize-sdk-android
docTags: 
createdAt: 2026-08-05T20:39:56.000Z
---

Use the `instantiate` method to initialize the Android SDK and instantiate an instance of the Optimizely client class that exposes API methods like the [decide methods](docId:0RRA0tqKb53_Evlvk1hNS). Each client corresponds to the datafile representing the state of a project for a certain environment.

You do not need to manage the datafile directly in the Android SDK. The SDK has an additional abstraction called a manager that handles getting the datafile and instantiating the client for you during the SDK's initialization process. The manager includes support for [datafile polling](docId\:h4DJEcwodA26HnOB6F68S) to update the datafile on a regular interval automatically.

## Version

4.0.0 and higher

## Description

The constructor accepts a configuration object to configure Optimizely.

Some parameters are optional because the SDK provides a default implementation, but you may want to override these for your production environments. For example, you may want to override these to configure an [error handler](docId\:EP71WowWj7HPQNseXONZx) and [logger](docId\:JIhfxkhnm4ACNaEfVWsmO) to catch issues, an [event dispatcher](docId\:w7doPrWnB8BSibrBAYkWK) to manage network calls, and a [User Profile Service](docId\:xGJP0eY_0Gu08c5Ppj0MK) to ensure sticky bucketing.

## Parameters

The following are the required and optional parameters (client constructed using the Builder class and passing the following to `Build()`).

| Parameter                                         | Type                    | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| ------------------------------------------------- | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| \`sdkKey\` \_required\_                           | String                  | The SDK key is used to define the config file for the environment.                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| \`eventProcessor\` \_optional\_                   | \`EventProcessor\`      | An event handler object provides an intermediary processing stage for events. The \`EventProcessor\` dispatches events through a provided \`EventHandler\`.                                                                                                                                                                                                                                                                                                                                                     |
| \`eventHandler\` \_optional\_                     | \`EventHandler\`        | An event handler dispatching events to the Optimizely event end-point.                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| \`errorHandler\` \_optional\_                     | \`ErrorHandler\`        | An error handler object to handle errors.                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| \`logger\` \_optional\_                           | \`Logger\`              | A logger implementation to log messages.                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| \`userProfileService\` \_optional\_               | \`UserProfileService\`  | A user profile service. An object with lookup and save methods.                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| \`datafileDownloadInterval\` \_optional\_         | Long                    | Sets the interval (in the specified \`TimeUnit\`) at which \`DatafileHandler\` attempts to update the cached datafile periodically. If this value is not set, background updates are disabled. The minimum interval is 15 minutes (enforced by the \[Android JobScheduler API]\(https\://developer.android.com/reference/android/app/job/JobScheduler)).                                                                                                                                                        |
| \`eventFlushInterval\` \_optional\_               | \`Long\`                | Sets the interval (in the specified \`TimeUnit\`) in which queued events are flushed periodically. If this value is not set, the default interval (30 seconds) is used.                                                                                                                                                                                                                                                                                                                                         |
| \`defaultDecideOptions\` \_optional\_             | Array                   | An array of \`OptimizelyDecideOption\` enums. When the Optimizely client is constructed with this parameter, it sets default decide options applied to all the Decide calls made during the lifetime of the Optimizely client. Additionally, you can pass options to individual Decide methods (does not override defaults). For details on decide options, see \[OptimizelyDecideOption]\(https\://docs.developers.optimizely.com/feature-experimentation/docs/decide-methods-android#optimizelydecideoption). |
| \`odpEnabled\` \_optional\_                       | Boolean                 | Enable or disable \[Real-Time Audiences for Feature Experimentation integration]\(https\://docs.developers.optimizely.com/feature-experimentation/docs/real-time-audiences-for-feature-experimentation).                                                                                                                                                                                                                                                                                                        |
| \`vuidEnabled\` \_optional\_                      | Boolean                 | Enable or disable automatic VUID creation and management. See VUIDs and client-side IDs.                                                                                                                                                                                                                                                                                                                                                                                                                        |
| \`odpSegmentCacheSize\` \_optional\_              | Int                     | Override the default ODP segment cache size (100).                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| \`odpSegmentCacheTimeoutInSecs\` \_optional\_     | Int                     | Override the default ODP segment cache timeout (10 minutes).                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| \`timeoutForODPSegmentFetchInSecs\` \_optional\_  | Int                     | Override the default timeout of ODP segment fetch (10 seconds).                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| \`timeoutForODPEventDispatchInSecs\` \_optional\_ | Int                     | Override the default timeout of ODP event dispatch (10 seconds).                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| \`odpEventManager\` \_optional\_                  | \`ODPEventManager\`     | Provide an optional custom \`ODPEventManager\` instance.                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| \`odpSegmentManager\` \_optional\_                | \`ODPSegmentManager\`   | Provide an optional custom \`ODPSegmentManager\` instance.                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| \`cmabCacheSize\` \_optional\_                    | Int                     | Maximum number of cached decisions.                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| \`cmabCacheTimeout\` \_optional\_                 | Int (with \`TimeUnit\`) | Time-to-live for cache entries.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| \`cmabClient\` \_optional\_                       | \`CmabClient\`          | This network client implements the CmabClient interface to fetch real-time decisions from Optimizely's CMAB service.                                                                                                                                                                                                                                                                                                                                                                                            |
| \`cmabPredictionEndpoint\` \_optional\_           | String                  | This setting overrides the default prediction endpoint URL. It must include a \`%s\` placeholder for the CMAB experiment ID.                                                                                                                                                                                                                                                                                                                                                                                    |

:::hint{type="success"}
**Beta**
CMAB for Feature Experimentation is in beta. Apply on the [Optimizely beta signup page](https://www.optimizely.com/beta) or contact your Customer Success Manager.
:::

### Customize `ODPManager`

The `ODPManager` contains the logic supporting [Real-Time Audiences for Feature Experimentation integration](docId:6UBBxxRv331nBIVZ2lun8)-related features, including audiences. ODP is enabled by default, and the SDK creates the `ODPManager` automatically. To use Real-Time Audiences for Feature Experimentation, enable the integration in your project. To turn ODP off, call `withODPDisabled()`.

The following settings are optionally configurable when the Android SDK is initialized:

- **ODP SegmentsCache size** – `.withODPSegmentCacheSize`
  - **Default** – 100
  - Set to 0 to disable caching.
- **ODP SegmentsCache timeout** (in seconds) – `.withODPSegmentCacheTimeout`
  - **Default** – 600 secs (10 minutes)
  - Set to 0 to disable timeout (never expires).
- **ODP disable** – `.withODPDisabled`
  - **Default** – false (enabled)
  - When disabled, the Android SDK will disable ODP-related features. The Android SDK still creates and manages VUID regardless of this flag and supports VUID-based decisions. See [anonymous users](docId\:iKfXFMXe_eqGd2PbD3j6T).
  - The Android SDK returns or logs an `odpNotEnabled` error when ODP is disabled and its features are requested.
- **VUID enable** – `.withVuidEnabled`

:::hint{type="warning"}
**Important**
`.withVuidEnabled` is only available on the Android SDK version 5.0.0+. See [SDK compatibility matrix](docId:2shbZfPCkPAZ0mlZpL1TU).
:::

:::Paragraph{listStyleType="disc" indent="2"}
**Default** – false (disabled)
:::

:::Paragraph{listStyleType="disc" indent="2"}
When enabled, the Android SDK creates and manages VUID and supports VUID-based decisions. See [anonymous users](docId\:iKfXFMXe_eqGd2PbD3j6T).
:::

```kotlin
val disableODP = false // Setting this to true disables Real-Time Audiences for Feature Experimentation 
var enableVuid = false // Set this true to enable VUID
val optimizelyManagerBuilder = OptimizelyManager.builder() 
  .withSDKKey("YOUR_SDK_KEY") // Replace with your SDK key.
  .withDatafileDownloadInterval(15, TimeUnit.MINUTES) 
  .withEventDispatchInterval(60, TimeUnit.SECONDS) 
  .withTimeoutForODPEventDispatch(10) // In seconds 
  .withTimeoutForODPSegmentFetch(10) // In seconds 
  .withODPSegmentCacheSize(10) 
  .withODPSegmentCacheTimeout(10, TimeUnit.SECONDS) 
if (disableODP) { 
  optimizelyManagerBuilder.withODPDisabled() // Disables Real-Time Audiences for Feature Experimentation
} 
if (enableVuid) { 
  optimizelyManagerBuilder.withVuidEnabled() // Enable VUID
} 
val optimizelyManager = optimizelyManagerBuilder.build(applicationContext) 


// Instantiate a client synchronously with a bundled datafile 
val datafile = "REPLACE_WITH_YOUR_DATAFILE" 
val optimizelyClient = optimizelyManager.initialize(this, datafile) 


// Or, instantiate it asynchronously with a callback 
optimizelyManager.initialize(this, null) { client: OptimizelyClient? -> 
  // flag decision with userID (optional) 
  val user1 = client!!.createUserContext("USER_ID") 
  val decision = user1!!.decide("FLAG_KEY") 


  // flag decision with auto-generated VUID
  val user2 = client!!.createUserContext() 
  val decision2 = user2!!.decide("FLAG_KEY") 
} 
```

```java
boolean disableODP = false; // Setting this true will disable the odp
OptimizelyManager.Builder optimizelyManagerBuilder = OptimizelyManager.builder()
       .withSDKKey("YOUR_SDK_KEY") //Replace with your SDK key
       .withDatafileDownloadInterval(15, TimeUnit.MINUTES)
       .withEventDispatchInterval(60, TimeUnit.SECONDS)
       .withTimeoutForODPEventDispatch(10) // in seconds
       .withTimeoutForODPSegmentFetch(10) // in seconds
       .withODPSegmentCacheSize(10)
       .withODPSegmentCacheTimeout(10, TimeUnit.SECONDS);
if (disableODP) {
   optimizelyManagerBuilder.withODPDisabled(); // This function will disable the odp
}
OptimizelyManager optimizelyManager =
optimizelyManagerBuilder.build(getApplicationContext());

// Instantiate a client synchronously with a bundled datafile
String datafile = "REPLACE_WITH_YOUR_DATAFILE";
OptimizelyClient optimizelyClient = optimizelyManager.initialize(this, datafile);

// Or, instantiate it asynchronously with a callback
optimizelyManager.initialize(context, null, (OptimizelyClient client) -> {
    // flag decision with userID (optional)
    OptimizelyUserContext user1 = client.createUserContext("USER_ID");
    OptimizelyDecision decision1 = user1.decide("FLAG_KEY");

    // flag decision with auto generated vuid
    OptimizelyUserContext user2 = client.createUserContext();
    OptimizelyDecision decision2 = user2.decide("FLAG_KEY");

});
```

## Example

The manager is implemented as a factory for Optimizely client instances. To use it, create a manager object by supplying your **SDK key** and optional configuration settings for [datafile polling](docId\:h4DJEcwodA26HnOB6F68S) and [datafile bundling](docId\:h4DJEcwodA26HnOB6F68S). The SDK key is in **Settings > Environments**.

Next, choose whether to instantiate the client [synchronously or asynchronously](docId\:h4DJEcwodA26HnOB6F68S) and use the appropriate `initialize` method to instantiate a client.

If you use a bundled datafile, copy the datafile JSON string from [the Optimizely application](docId:8_kRh18IHN_0bW1xf7jYv). Typically, you want to copy the datafile string at the latest point possible before release.

```kotlin
// Build a manager
val optimizelyManager = OptimizelyManager.builder()
          .withSDKKey("YOUR_SDK_KEY") //Replace with your SDK key
          .withDatafileDownloadInterval(15, TimeUnit.MINUTES)
          .withEventDispatchInterval(30, TimeUnit.SECONDS)
          .build(context)

// Instantiate a client synchronously with a bundled datafile
val datafile = "REPLACE_WITH_YOUR_DATAFILE"
val optimizelyClient = optimizelyManager.initialize(context, datafile)

// Or, instantiate it asynchronously with a callback
optimizelyManager.initialize(context, null) { client: OptimizelyClient ->
    // flag decision
    val user = client.createUserContext("USER_ID")!!
    val decision = user.decide("FLAG_KEY")
}
```

```java
// Build a manager
OptimizelyManager optimizelyManager = OptimizelyManager.builder()
       .withSDKKey("YOUR_SDK_KEY")
       .withDatafileDownloadInterval(15, TimeUnit.MINUTES)
       .withEventDispatchInterval(30, TimeUnit.SECONDS)
       .build(context);

// Instantiate a client synchronously with a bundled datafile
String datafile = "REPLACE_WITH_YOUR_DATAFILE";
OptimizelyClient optimizelyClient = optimizelyManager.initialize(context, datafile);

// Or, instantiate it asynchronously with a callback
optimizelyManager.initialize(context, null, (OptimizelyClient client) -> {
    // flag decision
    OptimizelyUserContext user = client.createUserContext("USER_ID");
    OptimizelyDecision decision = user.decide("FLAG_KEY");
});
```

See the [Android example: \_MainActivity.java](https://gist.github.com/mauerbac/64d2c638b72e38de603f511601dd2b91).

## Get a client

Each manager retains a reference to its most recently initialized client. You can use the `getOptimizely` function to return that instance.

A dummy client instance is created and returned if this method is called before any client objects are initialized. This dummy instance logs errors when any of its methods are used.

```kotlin
val optimizelyClient = optimizelyManager.optimizely
```

```java
OptimizelyClient optimizelyClient = optimizelyManager.getOptimizely();
```

## Use synchronous or asynchronous initialization

You can instantiate the Optimizely client synchronously or asynchronously.

- The *behavioral* difference between the two methods is whether your application pings the Optimizely Experimentation servers for a new datafile during initialization.
- The *functional* difference between the two methods is whether your app prioritizes accuracy or speed.

:::hint{type="warning"}
**Important**
You must decide to initialize the Android SDK *either* synchronously or asynchronously. You cannot use both initialization methods.
:::

### Synchronous initialization

The synchronous method prioritizes speed over accuracy.

Instead of attempting to download a new datafile every time you initialize an Optimizely client, your app uses a local version of the datafile. This local datafile can be cached from a previous network request (see [configure datafile polling](docId\:h4DJEcwodA26HnOB6F68S)) or embedded within your app (see [enable bundled datafiles](docId\:h4DJEcwodA26HnOB6F68S)).

When you initialize an Optimizely client synchronously, the Optimizely manager first searches for a [cached datafile](docId\:h4DJEcwodA26HnOB6F68S). If one is available, the manager uses it to complete the client initialization. If the manager cannot find a cached datafile, the manager searches for a [bundled datafile](docId\:h4DJEcwodA26HnOB6F68S). If the manager finds a bundled datafile, it uses the datafile to complete the client initialization. If the manager cannot find a bundled datafile, the manager cannot initialize the client.

![](https://api.archbee.com/api/optimize/BrbvVORKJ5iIeSMZye5kI/wQyocWQfzw8HKv17IaLxC_1085e10-initialize-synchronous.png)

To initialize an `OptimizelyClient` object **synchronously**, call `OptimizelyManager#initialize()` and provide two arguments:

- The Application instance (from `android.app.Application`).
- An `Integer` pointer to the application resource datafile.

For more details on the specific requirements, view [`OptimizelyManager.java from the publicly available Android SDK`](https://github.com/optimizely/android-sdk/blob/master/android-sdk/src/main/java/com/optimizely/ab/android/sdk/OptimizelyManager.java).

### Asynchronous initialization

The asynchronous method prioritizes accuracy over speed.

During initialization, your app requests the newest datafile from the CDN servers. Requesting the newest datafile ensures that your app always uses the most current project settings, but it also means your app cannot instantiate a client until it downloads a new datafile, discovers the datafile has not changed, or until the request times out. This process takes time.

Initializing a client asynchronously executes like the [synchronous initialization](docId\:h4DJEcwodA26HnOB6F68S), except the manager will first attempt to download the newest datafile. This network activity is what causes an asynchronous initialization to take longer to complete.

If the network request returns an error (such as when network connectivity is unreliable) or if the manager discovers that the cached datafile is identical to the newest datafile, the manager then uses the synchronous approach. If the manager discovers that the datafile was updated and now differs from the cached datafile, the manager downloads the new datafile and uses it to initialize the client.

![](https://api.archbee.com/api/optimize/BrbvVORKJ5iIeSMZye5kI/nyFakldFQIaqYqq-pi-Wo_ee8b24d-initialize-asynchronous.png)

To initialize an `OptimizelyClient` object **asynchronously**, call `OptimizelyManager#initialize()` and three arguments:

- The Application instance (from `android.app.Application`).
- An `Integer` pointer to the application resource datafile.
- A listener object.

For more details on the specific requirements and to see how to build each object, see [`OptimizelyManager.java from the publicly available Android SDK`](https://github.com/optimizely/android-sdk/blob/master/android-sdk/src/main/java/com/optimizely/ab/android/sdk/OptimizelyManager.java).

## Configure datafile polling

The Optimizely manager attempts to pull the newest datafile from the CDN servers during its initialization. After this, the Optimizely manager can periodically check for and pull a new datafile at the time interval you set during its initialization. The process of checking for and downloading a new datafile is called *datafile polling*.

Datafile polling is disabled by default, so the manager only checks for a new datafile during initialization. To enable polling, set an interval with `withDatafileDownloadInterval(interval, timeUnit)`. The minimum interval is 15 minutes.

```kotlin
// Poll every 15 minutes
val optimizelyManager = OptimizelyManager.builder()
            .withSDKKey("<Your_SDK_Key>")
            .withDatafileDownloadInterval(15, TimeUnit.MINUTES)
            .build(context)
```

```java
// Poll every 15 minutes
OptimizelyManager optimizelyManager = OptimizelyManager.builder()
        .withSDKKey("<Your_SDK_Key>")
        .withDatafileDownloadInterval(15, TimeUnit.MINUTES)
        .build(context);
```

### Usage notes

Updated datafiles are automatically picked up because the default datafile handler now supports the [ProjectConfigManager](https://github.com/optimizely/java-sdk/blob/master/core-api/src/main/java/com/optimizely/ab/config/ProjectConfigManager.java) API.

You can register for datafile change notifications as well with the [UpdateConfigNotification on Github](https://github.com/optimizely/java-sdk/blob/master/core-api/src/main/java/com/optimizely/ab/notification/UpdateConfigNotification.java):

```kotlin
optimizelyClient.addUpdateConfigNotificationHandler { notification ->
    println("got datafile change")
}
```

```java
optimizelyClient.addUpdateConfigNotificationHandler(notification -> {
    System.out.println("got datafile change");
});
```

To override the default datafile handler and use your own, see [DatafileHandler on GitHub](https://github.com/optimizely/android-sdk/blob/master/datafile-handler/src/main/java/com/optimizely/ab/android/datafile_handler/DatafileHandler.java).

## Enable bundled datafiles

When your customer opens your app for the first time after installing or updating it, the manager attempts to pull the newest datafile from Optimizely's CDN. If your app cannot contact the servers, the manager can substitute a datafile that you included (*bundled*) when you created your app.

By bundling a datafile within your app, you ensure that the Optimizely manager can initialize without waiting for a response from the CDN. This prevents poor network connectivity from causing your app to hang or crash while it loads.

Datafile bundling works with synchronous and asynchronous initialization because reverting to a bundled datafile happens during the Optimizely manager's initialization before a client is instantiated.

```kotlin
// Initialize Optimizely asynchronously with a datafile.
//  If it is not able to download a new datafile, it
//  initializes an OptimizelyClient with the one provided.

optimizelyManager.initialize(context, R.raw.datafile) { optimizelyClient: OptimizelyClient ->
    val user = optimizelyClient.createUserContext("<User_ID>")!!
    val decision = user.decide("<Flag_Key>")
}

// Initialize Optimizely synchronously
//  This immediately instantiates and returns an
//  OptimizelyClient with the datafile that was passed in.
//  It also downloads a new datafile from the Optimizely CDN and
//  persist it to local storage.
//  The newly downloaded datafile is used the next
//  time the SDK is initialized.

optimizelyManager.initialize(context, R.raw.datafile)
```

```java
// Initialize Optimizely asynchronously with a datafile.
//  If it is not able to download a new datafile, it will
//  initialize an OptimizelyClient with the one provided.

optimizelyManager.initialize(context, R.raw.datafile, (OptimizelyClient optimizelyClient) -> {
    OptimizelyUserContext user = optimizelyClient.createUserContext("<User_ID>");
    OptimizelyDecision decision = user.decide("<Flag_Key>");
});

// Initialize Optimizely synchronously
//  This will immediately instantiate and return an
//  OptimizelyClient with the datafile that was passed in.
//  It'll also download a new datafile from the CDN and
//  persist it to local storage.
//  The newly downloaded datafile will be used the next
//  time the SDK is initialized.

optimizelyManager.initialize(context, R.raw.datafile);
```

## Dispose of the client

For effective resource management with the Optimizely Android SDK, you must properly close the Optimizely client instance when it is no longer needed. This is done by calling `optimizelyClient.close()`.

The `.close()` method ensures that the processes and queues associated with the instance are properly released. This is essential for preventing memory leaks and ensuring that the application runs efficiently, especially in environments where resources are limited or in applications that create and dispose of many instances over their lifecycle.

See [Close Optimizely Feature Experimentation Android SDK on application exit](docId\:TwklBP7vXaVg64I8wHide).

## More sample code

```kotlin
// Here are more sample codes for synchronous and asynchronous SDK initializations with multiple options

// [Synchronous]

// [S1] Synchronous initialization
//      1. SDK is initialized instantly with a cached (or bundled) datafile
//      2. A new datafile can be downloaded in background and cached after the SDK is initialized.
//         The cached datafile will be used only when the SDK re-starts in the next session.
optimizelyManager = OptimizelyManager.builder()
                .withSDKKey("<Your_SDK_Key>")
                .build(context)
optimizelyClient = optimizelyManager.initialize(context, R.raw.datafile)
user = optimizelyClient.createUserContext("<User_ID>")!!
decision = user.decide("<Flag_Key>")

// [S2] Synchronous initialization
//      1. SDK is initialized instantly with a cached (or bundled) datafile
//      2. A new datafile can be downloaded in background and cached after the SDK is initialized.
//         The cached datafile is used immediately to update the SDK project config.
optimizelyManager = OptimizelyManager.builder()
                .withSDKKey("<Your_SDK_Key>")
                .build(context)
optimizelyClient = optimizelyManager.initialize(context, R.raw.datafile, true, true)
user = optimizelyClient.createUserContext("<User_ID>")!!
decision = user.decide("<Flag_Key>")

// [S3] Synchronous initialization
//      1. SDK is initialized instantly with a cached (or bundled) datafile
//      2. A new datafile can be downloaded in background and cached after the SDK is initialized.
//         The cached datafile is used immediately to update the SDK project config.
//      3. Polling datafile periodically.
//         The cached datafile is used immediately to update the SDK project config.
optimizelyManager = OptimizelyManager.builder()
                .withSDKKey("<Your_SDK_Key>")
                .withDatafileDownloadInterval(15, TimeUnit.MINUTES)
                .build(context)
optimizelyClient = optimizelyManager.initialize(context, R.raw.datafile)
user = optimizelyClient.createUserContext("<User_ID>")!!
decision = user.decide("<Flag_Key>")

// [Asynchronous]

// [A1] Asynchronous initialization
//      1. A datafile is downloaded from the server and the SDK is initialized with the datafile
optimizelyManager = OptimizelyManager.builder()
                .withSDKKey("<Your_SDK_Key>")
                .build(context)
optimizelyManager.initialize(context, null) { client: OptimizelyClient ->
   val user = client.createUserContext("<User_ID>")!!
   val decision = user.decide("<Flag_Key>")
}

// [A2] Asynchronous initialization
//      1. A datafile is downloaded from the server and the SDK is initialized with the datafile
//      2. Polling datafile periodically.
//         The cached datafile is used immediately to update the SDK project config.
optimizelyManager = OptimizelyManager.builder()
                .withSDKKey("<Your_SDK_Key>")
                .withDatafileDownloadInterval(15, TimeUnit.MINUTES)
                .build(context)
optimizelyManager.initialize(context, null) { client: OptimizelyClient ->
   val user = client.createUserContext("<User_ID>")!!
   val decision = user.decide("<Flag_Key>")
}
```

```java
// Here are more sample codes for synchronous and asynchronous SDK initializations with multiple options

// [Synchronous]

// [S1] Synchronous initialization
//      1. SDK is initialized instantly with a cached (or bundled) datafile
//      2. A new datafile can be downloaded in background and cached after the SDK is initialized.
//         The cached datafile will be used only when the SDK re-starts in the next session.
        
optimizelyManager =  OptimizelyManager.builder()
                .withSDKKey("<Your_SDK_Key>")
                .build(context);
optimizelyClient = optimizelyManager.initialize(context, R.raw.datafile);
user = optimizelyClient.createUserContext("<User_ID>");
decision = user.decide("<Flag_Key>");

// [S2] Synchronous initialization
//      1. SDK is initialized instantly with a cached (or bundled) datafile
//      2. A new datafile can be downloaded in background and cached after the SDK is initialized.
//         The cached datafile is used immediately to update the SDK project config.
        
optimizelyManager =  OptimizelyManager.builder()
                .withSDKKey("<Your_SDK_Key>")
                .build(context);
optimizelyClient = optimizelyManager.initialize(context, R.raw.datafile, true, true);
user = optimizelyClient.createUserContext("<User_ID>");
decision = user.decide("<Flag_Key>");

// [S3] Synchronous initialization
//      1. SDK is initialized instantly with a cached (or bundled) datafile
//      2. A new datafile can be downloaded in background and cached after the SDK is initialized.
//         The cached datafile is used immediately to update the SDK project config.
//      3. Polling datafile periodically.
//         The cached datafile is used immediately to update the SDK project config.
        
optimizelyManager =  OptimizelyManager.builder()
                .withSDKKey("<Your_SDK_Key>")
                .withDatafileDownloadInterval(15, TimeUnit.MINUTES)
                .build(context);
optimizelyClient = optimizelyManager.initialize(context, R.raw.datafile, true, true);
user = optimizelyClient.createUserContext("<User_ID>");
decision = user.decide("<Flag_Key>");

// [Asynchronous]

// [A1] Asynchronous initialization
//      1. A datafile is downloaded from the server and the SDK is initialized with the datafile
        
optimizelyManager =  OptimizelyManager.builder()
                .withSDKKey("<Your_SDK_Key>")
                .build(context);
optimizelyManager.initialize(context, null, (OptimizelyClient client) -> {
            OptimizelyUserContext userContext = client.createUserContext("<User_ID>");
            OptimizelyDecision optDecision = userContext.decide("<Flag_Key>");
});

// [A2] Asynchronous initialization
//      1. A datafile is downloaded from the server and the SDK is initialized with the datafile
//      2. Polling datafile periodically.
//         The cached datafile is used immediately to update the SDK project config.
       
optimizelyManager =  OptimizelyManager.builder()
                .withSDKKey("<Your_SDK_Key>")
                .withDatafileDownloadInterval(15, TimeUnit.MINUTES)
                .build(context);
optimizelyManager.initialize(context, null, (OptimizelyClient client) -> {
            OptimizelyUserContext userContext = client.createUserContext("<User_ID>");
            OptimizelyDecision optDecision = userContext.decide("<Flag_Key>");
});
```

## Source files

The language and platform source files containing the implementation for Android are available on [GitHub](https://github.com/optimizely/android-sdk/tree/master/android-sdk/src/main/java/com/optimizely/ab/android/sdk).
