A Guide to Getting Started Quickly With Android Feature Flags

Written by: Erik Francis

12 min read

When it comes to getting started with feature flags (Android feature flags or just in general), you have to understand that there are degrees of feature flag strategy.  A feature flag, in concept, is about as simple as it gets.  Slap a conditional around something in your application and call it a day.  But that's far from the end of the story.
In this guide, you'll need to keep that in mind.  I'll get you to your first Android feature flag as fast as humanly possible so you don't find yourself bored and frustrated.  But after I do that, you must stick around for a deeper understanding, or you'll turn your application into a quagmire of technical debt.  Feature flags require feature flag management.
We'll get to that, though.  Don't worry.

Overview

Here's an overview of what we'll cover today:

  • Android Feature Flags: A Working Definition

  • Feature Flags Benefits

  • Get Going with the Basics

  • The First of Your Android Feature Flags

  • Introduction to Feature Flag Management

  • Getting the Configuration Out of Code

  • Centrally Managed Feature Flags

  • Getting Started with Rollout

Let's get started.

Android Feature Flags: A Working Definition

Before you roll up your sleeves and get down to work, I'll walk you through a succinct definition of feature flags, so we're on the same page regarding this mechanism. After that, I'll briefly treat you to some of the main benefits you can expect from adopting flags. If you're already familiar with the concept of flags, feel free to skip this section entirely.

So, what are feature flags? A feature flag is a mechanism that allows you to change an app's behavior without having to change its code and redeploy it. More specifically, a feature flag allows you to switch a portion of the codebase on and off again in a very flexible way.

Feature Flags Benefits

What's the motivation behind using flags? What are the benefits?

In short, you use flags to hide parts of the application from the general public. That could be because the said portion of the application isn't ready yet. Or maybe it is ready, but you still want to test it. Also, in more advanced scenarios, you can use flags to serve different versions of a feature to different user groups, which is called A/B testing.

Here are some of the benefits of feature flags:

  • Engineers can push their changes frequently without fearing that their incomplete work will interfere with the user's experience.

  • You can hide features from the general public, allowing only certain types of users to access them, enabling testing in production in a safe way.

  • It gets easier to perform A/B testing.

  • Deployments get totally decoupled from releases, and are made frequently and consistently

In other words, we can say that feature flagging is essential if you want to achieve true continuous integration.

Get Going with the Basics

First, let's level set.  You might be an old pro with Android development, or you might be new to the whole thing.  I'm going to assume the latter so that everyone reading is on equal footing.  The first thing you need to do is set up an Android development environment and the "Hello World" app that accompanies it. Follow this tutorial.  Seriously, follow it to the letter.  Teaching the set up of a development environment would seriously bloat this guide, so it's out of scope here, but it's important that you follow their instructions exactly.  On the "Run Your App" page, follow the directions for "Run On an Emulator" so that you don't need an actual device handy.  And once you've run your app, stop, because you're ready to pick back up here.  

If you look at the screenshot, you'll notice that I named my app "Feature Toggle Demo."  (Feature toggle and feature flag are synonymous, by the way, and they're also sometimes called feature flippers.)  Apart from the app name, you should now find yourself looking at a very similar-looking window, with your app running in the emulator. It's now time to create a feature flag.

The First of Your Android Feature Flags

Now that you've seen that promising "Hello World" screen, go ahead and stop the app.  It's time to write some code. Let's say that we want to show users "Hello World" in version 1 of the app.  Mission accomplished.  But in version 2, we want to create the ability to send them a seasonal greeting message.  At the time of writing, it's right around the new year, so let's wish everyone a happy new year. To do this, let's make a few quick changes.  First, open up activity_main.xml, in the res->layout folder.  In that file, you'll see the following code:

Insert a line after the "<TextView" line, and add the following to the markup.

android:id="@+id/greeting"

Why?  Well, because we want to do something with this in the Java code.  And in order to do that, we need to have a unique identifier by which we can find it. Speaking of Java code, let's now take a look at that.  Open MainActivity.java, which should look like this:

Let's update that class to the following:

public class MainActivity extends AppCompatActivity {

    private boolean _isNewYears = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView greeting = findViewById(R.id.myTextView);

        if(_isNewYears)
            greeting.setText("Happy New Year!");
    }
}

Congratulations!  You've now (sort of) created your very first Android feature flag.

Introduction to Feature Flag Management

You might be scratching your head at this point.  "That's a feature flag?  How is that useful at all?" It's a fair question, and it's fair for two reasons:

  1. It's not a fully baked feature flag.

  2. And it's also not useful.

To understand, let's check in with the definition of a feature flag.  A feature flag allows you to modify the app's behavior without changing code.  What we've done here is to create the conceptual infrastructure for modifying behavior, but without the additional step of abstracting the control out of the code.  To turn on our new years feature, we'd have to flip the boolean to true and then redeploy and rerun, creating this output:

So we have the feature flag but no practical way of managing it.  What's the point of this if we have to redeploy for each new greeting?  We need to introduce a way to manage feature flags without redeploying.  This is why I suggested sticking around even after seeing the theoretically simplest first cut of Android feature flags.

Getting the Configuration Out of Code

In the wider world of application development throughout the years, a logical next step would have emerged.  I'm talking about the venerable config file.  Here's how that might work, in concept:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    TextView greeting = findViewById(R.id.myTextView);

    if(new FileService().readPreferenceFromAFile("IsNewYears"))
        greeting.setText("Happy New Year!");
}

Note the departure of the boolean class field.  Now, we use a "file service" to check the value of an "IsNewYears" setting stored in a file somewhere.  If that file's setting is off, then you display the normal message.  Otherwise, if someone updates the settings file, you display the special message. Historically, that was a viable option.  Consider a couple of scenarios.

  • Throughout the 90s and 2000s in the world of Windows desktop apps, it was (sorta) reasonable to ask users to manage preferences via a file.

  • In the world of web applications, with centralized administration, asking operations staff to flip a setting in a file is perfectly sensible.

In this context, though?  Not so much.  Android does offer this as a service, in the form of its Storage Options.  This is the vehicle by which you can capture and store user preferences, often set on some sort of preferences screen. But we're looking to control the greeting message centrally.  It's ridiculous to notify all users of a mobile app to say, "Hey, for a special new years greeting, go into your preferences and enable it!"  So forget implementing your own file scheme and forget using Storage Options.  Let's administer feature flags centrally.

Centrally Managed Feature Flags

To recap, we first introduced the concept of a feature flag as a simple variable.  That demonstrates the concept but actually accomplishes nothing since you need to rebuild and redeploy to change it.  Then, we looked at the conceptual idea of pulling the feature flag value out of the application and into a file.  That's a logical next step, but it doesn't get you much, particularly in a mobile environment. To really make use of feature flags, you need to do more.  Companies like Facebook use them to test out new features in production, perform gradual rollouts, and make use of split tests.  In order to make that work, you can't mess around with class fields and text files.  You need more firepower. That's where centrally managed feature flag capabilities come in.  You can actually create and administer Android feature flags as a service.

Getting Started with CloudBees Feature Management

You can create a CloudBees Feature Management account and get started for free.    You'll sign in and create a new app, selecting Java as a language and Android as a platform under installation type.

This will take you to a screen describing how to use the SDK from Android Studio.  

You can also reference the CloudBees Feature Management Android documentation

to understand these steps.  But let's go through them here. First, open your build.gradle file (for the module, not the whole project) and add the dependency it gives you to the bottom of the "dependencies section".  For instance:

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
    compile group: 'io.rollout.rox', name: 'rox-android', version: '1.2.3'
}

Next, open up the AndroidManifest.xml file and add your key.  While you're in there, you also want to enable the INTERNET permission so that the CloudBees Feature Management SDK can access their servers for you to manage your feature flags.  Here's the updated manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest
    package="com.example.featuretoggledemo">
    <uses-permission android_name="android.permission.INTERNET" />
    <application
        android_allowBackup="true"
        android_icon="@mipmap/ic_launcher"
        android_label="@string/app_name"
        android_roundIcon="@mipmap/ic_launcher_round"
        android_supportsRtl="true"
        android_theme="@style/AppTheme">
        <meta-data
            android_name="rox.apiKey"
            android_value="5a3d5550e28449605e4ddc46"
            />
        <activity android_name=".MainActivity">
            <intent-filter>
                <action android_name="android.intent.action.MAIN" />

                <category android_name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Finally, add the Rox.setup() invocation to the onCreate() method:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Rox.setup(this.getApplication());

    TextView greeting = findViewById(R.id.myTextView);
    greeting.setText("Happy New Year!");
}

Implementing Feature Flags

Once you have all of that in place, click "Next" back in the CloudBees Feature Management administration screen.  You'll see a notification that it's waiting for you to launch the SDK in the emulator.  So go ahead. Rebuild your project, and then run it.  It'll take a moment, and then reward you with a success screen.  

Now we're hooked up with the feature flag management service.  But... you'll notice we haven't actually implemented a feature flag.  Let's fix that now. To do that, we'll create a new Java class alongside MainActivity.java.  Call it "Flags."  Here's what that looks like, including imports:

package com.example.featuretoggledemo;

import io.rollout.configuration.RoxContainer;
import io.rollout.flags.RoxFlag;

public class Flags extends RoxContainer {

    public RoxFlag greeting = new RoxFlag();

}

Now we've got some work to do back in onCreate().  We need to create an instance of the Flags class and register it, and then we need to actually invoke it to figure out what our greeting should be.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Flags flags = new Flags();
    Rox.register(flags);

    Rox.setup(this.getApplication());

    if(flags.greeting.isEnabled()) {
        TextView greeting = findViewById(R.id.myTextView);
        greeting.setText("Happy New Year!");
    }
}

Build this and run the app, and you'll notice something cool.  This actually creates your feature flag on the server.

To make the flag useful, we need to add it to an experiment.  As I mentioned earlier, the main goal of a feature flag management scheme is to allow customizability in production, and CloudBees Feature Management couches this inside the concept of experiments.  Looking at the screenshot above, click on "Production" (your environment) and then click experiments in the dropdown.  This will bring up a screen with a "Create Experiment" button.  Click that, and then fill the new experiment window out appropriately.

Now you can start to do some interesting stuff!  Check out the screen this brings us to:

Controlling the Feature Flag

Go back to Android Studio now and stop the emulation.  If you then restart it and run the app again, you might find yourself disappointed to see "Hello World" in place.  Was all of this work really for nothing?  Well, no -- we've actually accomplished a lot.  Nothing changed because right now our "custom greeting" experiment is active.  It's just that it's set to true for 0% of our users.  Ergo, you see the plain old greeting when you launch the app. Kill the app again, and now change the "True" percent to 100.  Click "Update Targeting" and then relaunch your app.  

Look at that! Now, if you want to have some fun with it, you could set the flag value to somewhere between 0% and 100% and delight in the non-determinism of what greeting will appear.  But that's probably only fun for a minute, so let's think about the power of this instead. You now have a setup where you never need to touch your code at all to accomplish some important things.  You can swap between these two messages.  But you can also gradually ratchet up the number of people that see the new one in order to make sure it's doing well with your audience.  Or alternatively, you can run a split test between these two greetings to see which one produces more purchases. (Let's assume you just go ahead and build an e-commerce app behind this.) This is the power of feature flags.

You Take It From Here

My aim today was just to show you how to get started as quickly as possible.  The CloudBees Feature Management documentation has a lot more information for you in general.  You can do a whole lot more with flags, experiments, groupings, and the entire management console.  And now that you have an understanding of how this works, I suggest you do so. It's not the 1990s or 2000s anymore, so local files that you foist on your users aren't going to cut it.  If you want to respond quickly to market trends and not wait to push things through the app store, feature flags are absolutely essential.  And in order to take advantage of them, you're going to need sophisticated feature flag management.

Stay up to date

We'll never share your email address and you can opt out at any time, we promise.