A Guide to Getting Started Quickly With Android Feature Flags
Read on to learn how to quickly build an Android feature flag and go deeper into feature flag management for mobile app development.
Join the DZone community and get the full member experience.
Join For FreeWhen 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. For now, let's make your very first feature flag.
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:
- It's not a fully baked feature flag.
- 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 year's 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 year's 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 Rollout
You can create a Rollout 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 Rollout 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 Rollout 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 xmlns:android="http://schemas.android.com/apk/res/android"
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 Rollout 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 Rollout 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 Rollout 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.
Published at DZone with permission of , DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments