Extending flutter_flavorizr for your Android IDE

For those who prefer to use the GUI.

Extending flutter_flavorizr for 
your Android IDE

flutter_flavorizr is a helpful package for managing apps that require multiple flavours. For instance, you might have development, staging and production environments. Or you could be blue-green testing.

It currently provides a structure that allows you to run your app on iOS and produce archives from entirely within Xcode.

Unfortunately, comparable boilerplate for running your app on Android and producing app bundles entirely within Android Studio is not currently provided out of the box.

Let’s do something about that!

Create a new project

Create a project and add flutter_flavorizr as a dev dependency with the following commands.

flutter create flavorizr_demo —-platforms=ios,android —-empty
cd flavorizr_demo
dart pub get
dart pub add flutter_flavorizr —-dev

Define your flavour configuration

Copy the following (source from flutter_flavorizr’s pub.dev listing) into the project’s pubspec.yaml file.

flavorizr:
  flavors:
    apple:
      app:
        name: "Apple App"
      android:
        applicationId: "com.example.apple"
      ios:
        bundleId: "com.example.apple"
    banana:
      app:
        name: "Banana App"
      android:
        applicationId: "com.example.banana"
      ios:
        bundleId: "com.example.banana"

Run the flutter_flavorizr process with:

dart run flutter_flavorizr

flutter_flavorizr will have made various changes to the iOS and Android projects, in addition to generating variants of lib/main.dart for each flavour that has been defined.

As a result of this process, if you were to open Xcode and run the scheme that corresponds to a given flavour, it would run the app via lib/main_flavour.dart.

As of flutter_flavorizr 2.2.1, if you were to open Android Studio and run the default configuration, it would not behave in a similar fashion. The app’s target remains the (unflavoured) default: lib/main.dart. You may wish to verify this.

Applying the flavour at the Android project level

The target file for Android builds can be changed by providing a project property named target. You can do this by adding a key named target to gradle.properties with an empty string (no value). The modified file will resemble the following:

org.gradle.jvmargs=-Xmx4G
android.useAndroidX=true
android.enableJetifier=true
target=

Now that a property named target exists in the project, some additional code is required in app/build.gradle in order to apply flavour configuration as required.

def flavourTag = "target"

if (project.hasProperty(flavourTag) &&
    project.property(flavourTag) != '') {
    // Do not set the value of the target property,
    // assume a target has been provided.
} else {
    def targetString = ""

    // Task names are expected in the format
    // app:compileFlutterBuild[FLAVOUR][VARIANT]
    // e.g. app:compileFlutterBuildDevDebug
    if (!gradle.startParameter.taskNames.isEmpty()) {
        def activeTask = gradle.startParameter
          .taskNames[0].toLowerCase()

        if (activeTask.contains("apple")) {
            targetString = "lib/main_apple.dart"
        } else if (activeTask.contains("banana")) {
            targetString = "lib/main_banana.dart"
        }
    }

    if (targetString.isEmpty()) {
        // WARNING: No active flavour. 
        // This is the expected result during gradle sync 
        // but not during builds.
    } else {
        project.setProperty(flavourTag, targetString)
    }
}

After applying this configuration, you should be able to run your app from within Android Studio and the target will now be based on the active build variant. (e.g. appleDebug, bananaRelease)

The conditional wrapper around this block is important in order to prevent overriding arguments that are provided to builds from the command line.

Hopefully in the future these steps (or some version of them) become part of flutter_flavorizr!

"The Android robot is reproduced or modified from work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License."