Dynamically Change Backend Environment in Android at Runtime
Speed up your Android application development by using all environments at once
When working on big scale applications, it’s always important to separate the environments on the service. This helps us to prevent any unwanted issues that will affect the service that the end-user is using.
In the context of Android applications, usually developer use build variant
or build flavor
to separate the app by their back-end’s environment.
Today, we will learn how to dynamically change the backend’s environment on runtime without using build variant
or build flavor
.
The Environments
The key word that we will be using to change the environment on Android application is interceptor
. But what is it actually?
“Interceptors are a powerful mechanism that can monitor, rewrite, and retry calls.”
Basically, by using interceptor
we will change all the API call using the environment that we will define.
Let’s say we will have three environments, that is Development, Staging, and Production.
So then we will define all those three environments inside annotation class in Kotlin like this:
Creating the interceptor
After defining the environments that we will be using, it’s time to create the interceptor
for changing base URL based on the chosen environment on the app’s runtime.
In this new class, we inherit interceptor
and override its’ intercept
method.
We also define a variable called env
that will define which environment we will be used when calling the API. And also three other base URL for each environment.
Inside intercept
method, we define a variable to use based on the chosen environment, and we will return a new request by changing the host with the base URL we define before.
We also will define another method called setEnvironment
that will prompt the user to choose which environment to use for the next API call.
Injection
We are going to inject EnvironmentInteceptor
using Koin to ensure that when the app is running, there’s only one instance of that class in our application. Doing it like this:
Add yourModule
to Application
class inside Koin defintion
Implementation
Finally, we’re going to prompt the user with the dialog we defined earlier inside EnvironmentInterceptor
for defining which environment we will be using.
Call your setEnvironment
before the first API call in your application. Here is an example of doing that inside SplashScreenActivity
:
whoosh…!! and just like that, you can change the backend’s environment without building separate APKs.
Improve Security
Changing environment would only needed in the development phase, and this can not be released to the version of the application that end-user will be using.
How do we separate that seamlessly? we’re going to differentiate EnvironmentInterceptor
for each build variant
. By default, Android Project have 2 build variant
, that is:
- Debug variant of the app that we use during development
- Release variant of the app that we will release to the end-user
So we will create two classes in a different directory. Let’s say the EnvironmentInterceptor
is located at the data package. Then we will store it at:
app\src\debug\java\<PACKAGE_NAME>\data\EnvironmentInterceptor.ktapp\src\release\java\<PACKAGE_NAME>\data\EnvironmentInterceptor.kt
Move the EnvironmentInterceptor
that we created earlier in debug
directory. And for release
directory, define the EnvironmentInterceptor
like this:
That will make the release variant of our application will not prompt the dialog to the user and will be using an embedded environment that is already defined in the app.