DEV Community

Jazib Jafri
Jazib Jafri

Posted on

Making environment based apks for a react native application for android

An Android device identifies each application with its associated package name, and normally would only allow single instance of an application to be installed at a time.
So if a device has an application installed with a package name com.org.weatherapp, it will be the only instance installed at a time, and any application with the same package name would update the existing installation.

So what if we have to allow our teams to be able to install multiple copies of our application.

Like if a tester has a production release installed in his device and he has to test a new feature on development environment, it would be awful if had to uninstall the production copy to install a development apk that he would only use temporarily.

That doesn't sound like something that happens in reality?

Well you're right, it doesn't.

Let me show you how we can create different apks for different environments in react-native, that will allow all of them to be installed simultaneously on any device!
Not only that but we are also going to use different application launcher icons, so it is easier to differentiate between different copies.

We will start by using a different package name for each copy of our application

com.org.weatherapp.test // For test environment
com.org.weatherapp.dev  // For dev environement
com.org.weatherapp // For production environment
Enter fullscreen mode Exit fullscreen mode

I'm using three different package names, but it will work for any number of environments as you might need. Just keep in mind, every copy must have a unique package name or else it override the existing installation.

1. Create assets for each environment

Open Android Studio and change the left side menu to Android, right click on the assets folder and click on New -> Image Asset.
Configure the name and any other properties you like and click on Finish.

Repeat for each environment, and name them accordingly.

ic_test_launcher.png // For test environment
ic_dev_launcher.png  // For dev environement
ic_launcher.png // For production environment
Enter fullscreen mode Exit fullscreen mode

Android Studio will create all variations of assets and put them in mipmap and drawable folders.

2. Use different icons for each environment

Now we need to tell our application to use different launcher icons on each environment.

Open android/app/src/main/AndroidManifest.xml and change the following lines:

    <application
        android:name=".MainApplication"
        android:allowBackup="false"
        android:label="@string/app_name"
---     android:icon="@mipmap/ic_launcher"
---     android:roundIcon="@mipmap/ic_launcher_round"
+++     android:icon="${appIcon}"
+++     android:roundIcon="${appIconRound}"
        android:theme="@style/AppTheme">
        ...
        ...
    </application>
Enter fullscreen mode Exit fullscreen mode

We use placeholders for app launcher icons. Which we will define in the next step.

3. Define different application flavors

We have to define different application flavors.
Open android/app/build.gradle and add the following lines:

    android {
        ...
        defaultConfig {
            ...
        }
        flavorDimensions "version"
        productFlavors {
            test {
                applicationIdSuffix ".test"
                manifestPlaceholders = [
                    appIcon: "@mipmap/ic_test_launcher",
                    appIconRound: "@mipmap/ic_test_launcher_round"
                ]
            }
            dev {
                applicationIdSuffix ".dev"
                manifestPlaceholders = [
                    appIcon: "@mipmap/ic_dev_launcher",
                    appIconRound: "@mipmap/ic_dev_launcher_round"
                ]
            }
            production {
                manifestPlaceholders = [
                    appIcon: "@mipmap/ic_launcher",
                    appIconRound: "@mipmap/ic_launcher_round"
                ]
            }
        }
    }
Enter fullscreen mode Exit fullscreen mode

So what we did here?

  1. We defined three product flavors for our application, test, dev, and production.
  2. applicationIdSuffix is a property that will be used to append the package name to the application id. So test apk will have the package name com.org.weatherapp.test and dev apk will have the package name com.org.weatherapp.dev. We didn't define applicationIdSuffix for production because we don't want to append anything to it.
  3. manifestPlaceholders are the variables we defined earlier in AndroidManifest.xml they will be used to replace the placeholders in the manifest file. This will allow us to use different icons for each environment.

4. Updating build scripts

We have to update our build scripts that will be used to create different flavored apks.

Open package.json and add the following lines:

"scripts": {
    "bundle": "react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest",
    "android": "react-native run-android --variant testDebug --appId com.org.weatherapp.test",
    "dev-apk": "yarn bundle && cd android && ./gradlew assembledevDebug",
    "prod-apk": "yarn bundle && cd android && ./gradlew assembleproductionDebug"
}
Enter fullscreen mode Exit fullscreen mode
  1. bundle is the command that will be used to create the index.bundle file.
  2. We update android script to use the testDebug variant of the application.
  3. We use dev-apk script to use the devDebug variant of the application.
  4. Same for production, ofcourse production build will be a release variant instead of debug, but that is a different process out of scope of this tutorial.

That's It!
Now you can install all flavors of your application on any device at the same time.

If you found this guide useful, leave a like. If you have any questions or feedback, drop it below. Thanks 👍

Top comments (0)