Movatterモバイル変換


[0]ホーム

URL:


Dev guideRecipesAPI ReferenceChangelog
Dev guideAPI ReferenceRecipesChangelogUser GuideGitHubDev CommunityOptimizely AcademySubmit a ticketLog InFeature Experimentation
Dev guide
All
Pages
Start typing to search…

Android SDK quickstart

Welcome to the quickstart guide for Optimizely Feature Experimentation's Android SDK. Follow the steps in this guide to create a flag, roll out a flag delivery, and run an A/B test using a simple command-line application.

Part 1: Create a sample app

1. Get a free account

You need an Optimizely account to follow this guide. If you do not have an account, you canregister for a free account. If you already have an account navigate to your Feature Experimentation project.

2. Get your SDK key

To find your SDK Key in your Optimizely project:

  1. Go toSettings >Environments.
  2. Copy and save theSDK Key for your primary environment.
🚧

Important

Each environment has its own SDK key. Ensure you copy the correct key.

SDK key for primary environment

Click image to enlarge

3. Copy the sample code

To try out the Android SDK:

  1. In Android Studio, create a new Project, Empty activity android project calledoptimizely-android-quickstart withcom.example.optimizely_android_quickstart asPackage Name.
  2. Install the Optimizely Feature Experimentation Android SDK.
  3. In build.gradle (Project), add MavenCentral to repositories.
repositories {mavenCentral()        google()        jcenter()}

In build.gradle (Module), add Optimizely Android SDK dependency and sync gradle by clickingSync Now.

dependencies {implementation 'com.optimizely.ab:android-sdk:+'}

The Android SDK is distributed throughMavenCentral. The full source code is available onGitHub.

  1. Copy the following code sample into theMainActivity.java file for your app.
  2. Replace<Your_SDK_Key> with the SDK key you found in a previous step.
package com.example.optimizely_android_quickstart;import android.os.Bundle;import android.os.PersistableBundle;import android.util.Log;import androidx.annotation.Nullable;import androidx.appcompat.app.AppCompatActivity;import com.optimizely.ab.OptimizelyUserContext;import com.optimizely.ab.android.sdk.OptimizelyManager;import com.optimizely.ab.android.sdk.OptimizelyClient;import com.optimizely.ab.config.parser.JsonParseException;import com.optimizely.ab.optimizelydecision.OptimizelyDecision;import java.io.BufferedInputStream;import java.io.IOException;import java.net.URL;import java.util.Random;import java.util.Timer;import java.util.TimerTask;public class MainActivity extends AppCompatActivity {    OptimizelyManager optimizelyManager;    String SDK_KEY = "Your_SDK_Key";    String LOG_TAG = "OPTIMIZELY_QUICK_START";    private TimerTask task = new DatafilePoller();    @Override    protected void onDestroy() {        super.onDestroy();        task.cancel();    }    @Override    public void onCreate(@Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        // this Optimizely initialization is synchronous. for other methods see the Android SDK reference        //Initializing Optimizely Manager        optimizelyManager = OptimizelyManager.builder()            .withSDKKey(SDK_KEY)            .build(this);        Timer timer = new Timer();        long intevalPeriod = 1000;        // schedules the task to be run in an interval        timer.scheduleAtFixedRate(task, 0,            intevalPeriod);    }    private void runQuickStart(String datafile) {        // Initialize optimizelyClient        OptimizelyClient optimizelyClient = optimizelyManager.initialize(this, datafile);        if (optimizelyClient.isValid()) {            /* --------------------------------             * to get rapid demo results, generate random users. Each user always sees the same variation unless you reconfigure the flag rule.             * --------------------------------             */            Random rnd = new Random();            boolean hasOnFlags = false;            for (int i = 0; i < 10; i++) {                String userId = (rnd.nextInt(9999 - 1000) + 1000) + "";          /* --------------------------------             Create hardcoded user & bucket user into a flag variation             --------------------------------          */                OptimizelyUserContext user = optimizelyClient.createUserContext(userId);                // "product_sort" corresponds to a flag key in your Optimizely project                OptimizelyDecision decision = user.decide("product_sort");                // did decision fail with a critical error?                if (decision.getVariationKey() == null) {                    Log.e(LOG_TAG, "\n\ndecision error: " + decision.getReasons());                }                // get a dynamic configuration variable                // "sort_method" corresponds to a variable key in your Optimizely project                String sortMethod = null;                try {                    sortMethod = decision.getVariables().getValue("sort_method", String.class);                }  catch (JsonParseException e) {                    e.printStackTrace();                }                if (decision.getEnabled()) {                    // Keep count how many visitors had the flag enabled                    hasOnFlags = true;                }              /* --------------------------------                   Mock what the users sees with print statements (in production, use flag variables to implement feature configuration)                   --------------------------------                */                // always returns false until you enable a flag rule in your Optimizely project                Log.d(LOG_TAG, "\n\nFlag " + (decision.getEnabled()? "on": "off") + ". User number " + user.getUserId() + " saw flag variation: " + decision.getVariationKey() + " and got products sorted by: " + sortMethod + " config variable as part of flag rule: " + decision.getRuleKey());            }            if (!hasOnFlags) {                Log.d(LOG_TAG, "\n\nFlag was off for everyone. Some reasons could include:" +                    "\n1. Your sample size of visitors was too small. Rerun, or increase the iterations in the FOR loop" +                    "\n2. By default you have 2 keys for 2 project environments (dev/prod). Verify in Settings>Environments that you used the right key for the environment where your flag is toggled to ON." +                    "\nCheck your key at  https://app.optimizely.com/v2/projects/" + optimizelyClient.getProjectConfig().getProjectId() + "settings/implementation");            }        } else {            Log.d(LOG_TAG, "Optimizely client invalid. Verify in Settings>Environments that you used the primary environment's SDK key");        }    }    /**     * Downloads latest datafile from DATAFILE_URL. Then verify and call {@link MainActivity#runQuickStart(String)} (String)} if datafile got updated.     * Fetch any datafile changes, which result from configuration updates you make to traffic percentage sliders, flag variable values, etc.     */    public class DatafilePoller extends TimerTask {        static final String DATAFILE_URL = "https://cdn.optimizely.com/datafiles/%s.json";        private String currentDatafile = "";        @Override        public void run() {            try {                BufferedInputStream in = new BufferedInputStream(new URL(String.format(DATAFILE_URL, SDK_KEY)).openStream());                byte[] contents = new byte[1024];                int bytesRead;                String latestDatafile = "";                while ((bytesRead = in.read(contents)) != -1) {                    latestDatafile += new String(contents, 0, bytesRead);                }                if (!currentDatafile.equals(latestDatafile)) {                    currentDatafile = latestDatafile;                    runQuickStart(currentDatafile);                }            } catch (IOException e) {                e.printStackTrace();            }        }    }}
📘

Note

Do not run your app yet, because you still need to set up the flag in the Optimizely application.

Part 2: Run your app

After completingPart 1, your app does nothing. You need to create a flag and a flag rule in the Optimizely app to enable the app.

1. Create the feature flag

Aflag lets you control the users that are exposed to new code in your application. For this quickstart, imagine that you are rolling out a redesigned sorting feature for displaying products.

Create a flag in your Feature Experimentation project namedproduct_sort and give it a variable namedsort_method:

  1. SelectCreate New Flag... from theFlags tab.
  2. Enterproduct_sort in theName field.
  3. Keep the auto-createdKey,product_sort, and clickCreate Flag. TheKey corresponds to the flag key in your sample app.

Next, create a variable in your flag:

  1. In your new flag,product_sort, underFlag Setupgo toVariables and clickAdd Variable (+).
  2. SelectString in theAdd Variable drop-down.
  1. Entersort_method for theVariable Key, which corresponds to the variable key in your sample app.
  2. Enteralphabetical for theDefault Value, which represents your old sorting method. The new sorting method is what you are rolling out.
  3. ClickSave.

Next, create a variation in your flag:

  1. UnderFlag Setup go toVariations select theOn variation. A variation is a wrapper for a collection of variable values.
  2. For thesort_method variable value, enterpopular_first, which represents your new sorting method.
  3. ClickSave.

2. Create the flag delivery rule

Your sample appstill does nothing because you need to create and enable aflag rule.

Make atargeted delivery rule for theOn variation for theproduct_sort flag. A targeted delivery lets you gradually release a feature flag to users but with the flexibility to roll it back if you encounter bugs.

  1. Ensure you are in your primary environment (because you are using the primary environment SDK key fromPart 1.

  2. ClickAdd Rule and selectTargeted Delivery.

  3. EnterTargeted Delivery for theName field.

  4. Keep the defaultKey andAudiences.

  5. Set theTraffic Allocation slider to 50%. This delivers theproduct_sort flag to 50% of everyone who triggers the flag in this environment. You can roll out or roll back theproduct_sort flag to a percentage of traffic whenever you want.

  6. From theDeliver drop-down list, select theOn variation.

  7. ClickSave.

3. Run your sample app

To run your sample application:

  1. ClickRun on your targeted delivery rule:

  2. ClickOk on theReady to Run Status page. This lets you know that your ruleset has not been set to run, yet.

  3. ClickRun on your ruleset (flag):

  4. In Android studio, clickRun for the sample app you created earlier. Output appears similar to the following in the logcat:

    Flag on. User number 6998 saw flag variation: on and got products sorted by: popular_first config variable as part of flag rule: targeted_deliveryFlag on. User number 1177 saw flag variation: on and got products sorted by: popular_first config variable as part of flag rule: targeted_deliveryFlag on. User number 9714 saw flag variation: on and got products sorted by: popular_first config variable as part of flag rule: targeted_deliveryFlag on. User number 4140 saw flag variation: on and got products sorted by: popular_first config variable as part of flag rule: targeted_deliveryFlag on. User number 4994 saw flag variation: on and got products sorted by: popular_first config variable as part of flag rule: targeted_deliveryFlag off. User number 8700 saw flag variation: off and got products sorted by: alphabetical config variable as part of flag rule: default-rollout-208-19963693913Flag off. User number 9912 saw flag variation: off and got products sorted by: alphabetical config variable as part of flag rule: default-rollout-208-19963693913Flag on. User number 6560 saw flag variation: on and got products sorted by: popular_first config variable as part of flag rule: targeted_deliveryFlag on. User number 9252 saw flag variation: on and got products sorted by: popular_first config variable as part of flag rule: targeted_deliveryFlag on. User number 6582 saw flag variation: on and got products sorted by: popular_first config variable as part of flag rule: targeted_delivery
📘

Note

You will not get exactly 50% of your user traffic in theOn variation, since you are working with a small numbers of visitors. Also, the users who got an "off" flag did not make it into the 50% traffic you set, so they fell through to the default "Off" rule (default-rollout in the logcat print statements).

4. How it works

So far, you have:

  • Created a flag, flag variable, and a flag variation (wrapper for your variables) in the Optimizely application.
  • Implemented a flag in your application with the Decide method from the Android SDK.

What is going on in your sample app?

How it works: decide to show a user a flag

The Android SDK’sDecide method determines whether to show or hide the feature flag for a specific user.

📘

Note

You can reuse this method for different flag rules—whether for delivering more traffic, or running an experiment to show different sorting methods to just a portion of users.

After you learn which sorting method works best to increase sales, roll out the product sort flag to all traffic with the method set to the optimum value.

In your sample app:

OptimizelyUserContext user = optimizelyClient.createUserContext(userId);// "product_sort" corresponds to the flag key you create in the Optimizely appOptimizelyDecision decision = user.decide("product_sort");
📘

Note

Optionally include attributes when you create your user (not shown in your sample app ), so that you can target specific audiences. For example:

Map attributes = new HashMap<String, Object>();attributes.put("logged_in", true);OptimizelyUserContext user = optimizelyClient.createUserContext("user123", attributes);

How it works: configure flag variations

You can dynamically configure a flag variation using flag variables. In your sample app:

// always returns false until you enable a flag rule in the Optimizely appif (decision.getEnabled()) {  // "sort_method" corresponds to variable key you define in Optimizely app  String sortMethod = decision.getVariables().getValue("sort_method", String.class);Log.d(LOG_TAG, "sort_method: "+ sortMethod.toString());}

For yourproduct_sort flag, you can configure variations with differentsort_method values, sorting by popular products, relevant products, promoted products, and so on. You can set different values for the sort method at any time in the Optimizely app.

Part 3: Run an A/B test

Part 2 of this tutorial guided you through a targeted delivery because it is the most straightforward flag rule. However, you often want toA/B test how users react to feature flag variationsbefore you roll out a flag delivery.

  • Targeted delivery rule – You can roll out your flag to a percentage of your general user base (or to specific audiences), or roll back if you encounter bugs.
  • A/B test rule – Experiment by A/B testing a flag before you invest in delivering so you know what to build. Track how users behave in flag variations, then interpret your experiment results using the Optimizely Stats Engine.

For Part 3, you will run an A/B test on theOn variation of yourproduct_sort flag.

1. Add event tracking

You need to add aTrack Event method to your sample app, so you can mock up user events and then seemetrics.

  1. Delete your old sample code, and paste the following code.
  2. Replace your SDK key. SeeGet your SDK Key.
  3. Do not run your app yet because you still need to set up the A/B test in the Optimizely application.
📘

Note

You also need to addimplementation group: 'com.google.code.gson', name: 'gson', version: '2.8.6' dependency in gradle project as it is getting used in the given code.

package com.example.optimizely_android_quickstart;import android.os.Bundle;import android.util.Log;import androidx.annotation.Nullable;import androidx.appcompat.app.AppCompatActivity;import com.optimizely.ab.OptimizelyUserContext;import com.optimizely.ab.android.sdk.OptimizelyClient;import com.optimizely.ab.android.sdk.OptimizelyManager;import com.optimizely.ab.optimizelydecision.OptimizelyDecision;import java.io.BufferedInputStream;import java.io.IOException;import java.net.URL;import java.util.Random;import java.util.Timer;import java.util.TimerTask;public class MainActivity extends AppCompatActivity {    OptimizelyManager optimizelyManager;    String SDK_KEY = "YOUR_SDK_KEY";    String LOG_TAG = "OPTIMIZELY_QUICK_START";    private TimerTask task = new DatafilePoller();    @Override    protected void onDestroy() {        super.onDestroy();        task.cancel();    }    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        // this Optimizely initialization is synchronous. for other methods see the Java SDK reference        //Initializing Optimizely Manager        optimizelyManager = OptimizelyManager.builder()                .withSDKKey(SDK_KEY)                .build(this);        Timer timer = new Timer();        long intevalPeriod = 1000;        // schedules the task to be run in an interval        timer.scheduleAtFixedRate(task, 0,                intevalPeriod);    }    private void runQuickStart(String datafile) {        OptimizelyClient optimizelyClient = optimizelyManager.initialize(this, datafile);      if (!optimizelyClient.isValid()) {            Log.d(LOG_TAG,"Optimizely client invalid. Verify in Settings>Environments that you used the primary environment's SDK key");            return;        }          /* --------------------------------         OPTIONAL: Add a notification listener so you can integrate with third-party analytics platforms         --------------------------------        */      /*        int notificationId = optimizelyClient.getNotificationCenter().addNotificationHandler(DecisionNotification.class, decisionNotification -> {            if ("flag".equals(decisionNotification.getType())) {                Gson gsonObj = new Gson();                String serializedJsonInfo = gsonObj.toJson(decisionNotification.getDecisionInfo());                Log.d(LOG_TAG,"Feature flag access related information: " + serializedJsonInfo);                // Send data to analytics provider here            }        });*/        /* --------------------------------         * to get rapid demo experiment results, generate random users. Each user is deterministically hashed into a variation.         * --------------------------------         */        Random rnd = new Random();      boolean hasOnFlags = false;        for (int i = 0; i < 5; i++) {            String userId = (rnd.nextInt(9999 - 1000) + 1000) + "";        /* --------------------------------           Bucket user into a flag variation and mock experiment results           --------------------------------        */            OptimizelyUserContext user = optimizelyClient.createUserContext(userId);            OptimizelyDecision decision = user.decide("product_sort");            // did decision fail with a critical error?            if (decision.getVariationKey() != null && !decision.getVariationKey().isEmpty()) {                Log.d(LOG_TAG,"decision error: " + decision.getReasons());            }            Object sortMethod = decision.getVariables().toMap().get("sort_method");            if (decision.getEnabled()) {                hasOnFlags = true;            }          Log.d(LOG_TAG, "\n\nFlag " + (decision.getEnabled()? "on": "off") + ". User number " + user.getUserId() + " saw flag variation: " + decision.getVariationKey() + " and got products sorted by: " + sortMethod + " config variable as part of flag rule: " + decision.getRuleKey());            MockPurchase(user);        }      if (!hasOnFlags) {          Log.d(LOG_TAG,"\n\nFlag was off for everyone. Some reasons could include:" +                    "\n1. Your sample size of visitors was too small. Rerun, or increase the iterations in the FOR loop" +                    "\n2. By default you have 2 keys for 2 project environments (dev/prod). Verify in Settings>Environments that you used the right key for the environment where your flag is toggled to ON." +                    "\n\nCheck your key at  https://app.optimizely.com/v2/projects/" + optimizelyClient.getProjectConfig().getProjectId() + "settings/implementation");        } else {     Log.d(LOG_TAG,"\n\nDone with your mocked A/B test.");        Log.d(LOG_TAG,"Check out your report at  https://app.optimizely.com/v2/projects/" + optimizelyClient.getProjectConfig().getProjectId() + "/reports");        Log.d(LOG_TAG,"Be sure to select the environment that corresponds to your SDK key");        }    }   // mock tracking a user event so you can see some experiment reports    void MockPurchase(OptimizelyUserContext user) {        Log.d(LOG_TAG,"Pretend that user made a purchase? y/n ");        Random rnd = new Random();        int yesOrNo = rnd.nextInt(2);        // Assigning random yes and no        String answer = yesOrNo == 1? "y" : "n";        Log.d(LOG_TAG, answer);        if (answer.toLowerCase().equals("y")) {            // track a user event you defined in the Optimizely app            user.trackEvent("purchase");            Log.d(LOG_TAG,"Optimizely recorded a purchase in experiment results for user " + user.getUserId());        } else {            Log.d(LOG_TAG,"Optimizely didn't record a purchase in experiment results  for user " + user.getUserId());        }    }      /**     * Downloads latest datafile from DATAFILE_URL. Then verify and call {@link MainActivity#runQuickStart(String)} (String)} if datafile got updated.     * Fetch any datafile changes, which result from configuration updates you make to traffic percentage sliders, flag variable values, etc.     */    public class DatafilePoller extends TimerTask {        static final String DATAFILE_URL = "https://cdn.optimizely.com/datafiles/%s.json";        private String currentDatafile = "";        @Override        public void run() {            try {                BufferedInputStream in = new BufferedInputStream(new URL(String.format(DATAFILE_URL, SDK_KEY)).openStream());                byte[] contents = new byte[1024];                int bytesRead;                String latestDatafile = "";                while ((bytesRead = in.read(contents)) != -1) {                    latestDatafile += new String(contents, 0, bytesRead);                }                if (!currentDatafile.equals(latestDatafile)) {                    currentDatafile = latestDatafile;                    runQuickStart(currentDatafile);                }            } catch (IOException e) {                e.printStackTrace();            }        }    }}

2. Delete other rules in free accounts

If you have a free Optimizely account, you need to pause the Targeted Delivery you created inPart 2 before you create your A/B test:

  1. Select the flag that contains the Targeted Delivery you created in Part 2 from theFlags tab.

  2. Select the primary environment and the Targeted Delivery rule you created in Part 2.

  3. ClickMore Options >Delete:

  4. ClickSave.

3. Create the A/B test flag rule

To create an A/B Test rule in your Feature Experimentation project, in the flag you created inPart 2:

  1. clickAdd Rule and selectA/B Test.
  2. EnterExperiment for theName field.
  3. Keep the defaultKey andAudiences
  4. Keep theTraffic Allocation slider set to 100%.

4. Add an event

In an experiment, you track users' relevant actions to measure how they react to your flag variations. To define the actions you want to track, calledevents:

  1. Click on theMetrics field.
  2. ClickCreate new event.
  1. Enterpurchase for theEvent Name, and theEvent Key will be automatically filled.
  2. (Optional) Enter aDescription. You want to know whether the new sorting flag helps customers figure out what to buy, so track whether the user makes a purchase after they are shown the products in a new order.
  3. ClickCreate Event.
  1. In theAdd Metric modal, leave the defaults, measureincrease inunique conversions.
  1. ClickAdd Metric.
  2. Leave the defaultOff variation as a control. Select theOn variation you configured inPart 2:
📘

Note

You are not limited to two variations; you can also create A/B tests with multiple variations.

  1. ClickSave to create your A/B Test rule.

  2. ClickRun on the A/B test rule.

5. Run the A/B test

Ensure your ruleset's (flag's) status isRunning, and the rule's status isRunning so your experiment can run:

ClickRun in Android Studio and answer the command-line prompts. Output displays similar to the following:

Flag on. User number 1496 saw flag variation: on and got products sorted by: popular_first config variable as part of flag rule: experiment_1Pretend that user made a purchase? y/nnOptimizely didn't record a purchase in experiment results for user 1496Flag off. User number 1194 saw flag variation: off and got products sorted by: alphabetical config variable as part of flag rule: experiment_1Pretend that user made a purchase? y/nyOptimizely recorded a purchase in experiment results for user 1194Flag off. User number 5815 saw flag variation: off and got products sorted by: alphabetical config variable as part of flag rule: experiment_1Pretend that user made a purchase? y/nyOptimizely recorded a purchase in experiment results for user 5815Flag on. User number 1248 saw flag variation: on and got products sorted by: popular_first config variable as part of flag rule: experiment_1Pretend that user made a purchase? y/nyOptimizely recorded a purchase in experiment results for user 1248Flag off. User number 9580 saw flag variation: off and got products sorted by: alphabetical config variable as part of flag rule: experiment_1Pretend that user made a purchase? y/nnOptimizely didn't record a purchase in experiment results for user 9580Done with your mocked A/B test.Check out your report at  https://app.optimizely.com/v2/projects/19957465438/reportsBe sure to select the environment that corresponds to your SDK key

6. See your A/B test results

Go to theReports tab and select your experiment to see your results.

Your results should look similar:

📘

Notes

  • You might not see the exact user traffic percentages you configured for your flag variations until you have larger numbers of users.
  • You might not see your user traffic immediately. Refresh the browser to refresh traffic.
  • Your experiment results will not tell you a winning variation or declarestatistical significance until you have a large number of visitors, on the order of 100,000.

7. How it works

For an A/B test, you need a way to tell Optimizely when a user made a purchase in your app and map this event in your application code to the specific event you created in Optimizely. Luckily the SDK has a method for that. Use theTrack Event method and pass in the key for the event you created (purchase). In your sample application:

// Track how users behave when they see a flag variation// e.g., after your app processed a purchase, let Optimizely know what happened:user.trackEvent("purchased");
📘

Note

Optionally add tags to your event to enrich it (not shown in your sample app). You can also use reserve tag keys likerevenue to track quantitative results. For example:

Map tags = new HashMap<String, Object>();tags.put("category", "shoes");tags.put("revenue", 6432);user.trackEvent("purchase", tags);

Conclusion

Congratulations! You successfully set up and launched your first Optimizely Feature Experimentation experiment using the Android SDK. While this example focused on optimizing sales, Optimizely’s experimentation platform can support an open-ended set of experimentation use cases.

See our completeAndroid SDK documentation to learn more ways to optimize your software using experimentation.

Updated 17 days ago



[8]ページ先頭

©2009-2025 Movatter.jp