BIS Tech
BIS Tech

Reputation: 19424

how to get flavor name on Flutter?

Is it possible to get flavor name Flutter side? for both android and ios

build.gradle

flavorDimensions "app"

productFlavors {
    dev {
        dimension "app"
        versionCode 2
        versionName "1.0.0"
    }
    qa {
        dimension "app"
        applicationId "com.demo.qa"
        versionCode 3
        versionName "1.0.2"
    }
}

Upvotes: 34

Views: 22842

Answers (6)

kforjan
kforjan

Reputation: 1394

If you've setup your flavors like it is shown in the official Flutter documentation you can use the globally available appFlavor variable to access the flavor name you defined with --flavor upon running the app. appFlavor variable is part of services.dart library. You can access it by importing the library:

import 'package:flutter/services.dart';

Now you can use it in your code like this:

if (appFlavor == 'prod') {
    // do something
  }

EXPLANATION:

The flavor.dart within services.dart contains the following code:

const String? appFlavor = String.fromEnvironment('FLUTTER_APP_FLAVOR') != '' ?
  String.fromEnvironment('FLUTTER_APP_FLAVOR') : null;

This means that it's not necessary to define the flavor anywhere else one more time or use --dart-define to define the flavor. The parameter you provide to --flavor is automatically dart-defined under FLUTTER_APP_FLAVOR key and can be accessed in the same way as shown in the flavor.dart.

Upvotes: 36

Lucas de Miranda Lima
Lucas de Miranda Lima

Reputation: 99

I haven't seen any answer describing how to get the current flavor directly from runtime config, after a lot of search I found this way: For Android is quite simple, put this code in your MainActivity.kt:


    private val CHANNEL = "flavor_channel"

  override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
    super.configureFlutterEngine(flutterEngine)
    MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {
      call, result ->
            when (call.method) {
                "getFlavor" -> {
                    result.success(BuildConfig.FLAVOR)
                }
            }
    }
  }

For iOS, put that in the AppDelegate.swift:

let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let flavorChannel = FlutterMethodChannel(name: "flavor_channel",
                                          binaryMessenger: controller.binaryMessenger)
flavorChannel.setMethodCallHandler({
  (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
  // This method is invoked on the UI thread.
  guard call.method == "getFlavor" else {
    result(FlutterMethodNotImplemented)
    return
  }
  self.receiveCurrentFlavor(result: result)
})

Then create this method at the bottom of AppDelegate class:

    private func receiveCurrentFlavor(result: FlutterResult) {
    var config: [String: Any]?
        
    if let infoPlistPath = Bundle.main.url(forResource: "Info", withExtension: "plist") {
        do {
            let infoPlistData = try Data(contentsOf: infoPlistPath)
            
            if let dict = try PropertyListSerialization.propertyList(from: infoPlistData, options: [], format: nil) as? [String: Any] {
                config = dict
            }
        } catch {
            print(error)
        }
    }

    result(config?["Flavor"])
  }

We now need to make the Flavor available in the infoDictionary. In Xcode, open Runner/Info.plist and add a key Flavor mapped to ${PRODUCT_FLAVOR}: info.plist

Now, under Targets/Runner/Build Settings/User-Defined and add a setting PRODUCT_FLAVOR. Add the flavor name for each configuration: User-Defined settings

Then in Dart:

final flavor =  await const MethodChannel("flavor_channel").invokeMethod("getFlavor");

Then you're done!

Upvotes: 8

Elihai David Vanunu
Elihai David Vanunu

Reputation: 163

Just write a channel method for that.

 override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)

        channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
        channel.setMethodCallHandler { call, result ->
            when (call.method) {
                "getFlavor" -> {
                    result.success(BuildConfig.FLAVOR)
                }
            }
        }
    }

Than in dart:

final flavor = await platform.invokeMethod("getFlavor");

Upvotes: 4

Till A. S. Friebe
Till A. S. Friebe

Reputation: 1439

You could use the solution from jonahwilliams.

  1. Set a key-value pair when creating the app:
flutter build apk --flavor=paid --dart-define=app.flavor=paid
  1. Access the value in Dart:
const String flavor = String.fromEnvironment('app.flavor');

void main() {
  print(flavor);
}

This would print "paid" when run.

The advantages are that you can use this on platforms where flavors are not supported yet and that the variable is const. The disadvantage that you have to set the key-value pair for the build.

Upvotes: 31

NeoKree
NeoKree

Reputation: 409

There is not a simple way to know the flavor name, however I would suggest you to use an environment variable, loaded from flutter_dotenv for example.

file .env

FLAVOR=dev

file main.dart

void main() async {
  await DotEnv().load('.env');
  final flavor = DotEnv().env['FLAVOR'];

  String baseUrl;
  if (flavor == 'dev') {
    baseUrl = 'https://dev.domain.com';
  } else if (flavor == 'qa') {
    baseUrl = 'https://qa.domain.com';
  } else {
    throw UnimplementedError('Invalid FLAVOR detected');
  }
}

This will allow you (as developer) to easily change the behaviour of your app and switch from different environments seamlessy.

Upvotes: 3

Josh
Josh

Reputation: 1151

As long as every flavor has a different packageName you could do it like this:

enum EnvironmentType { dev, qa }

class Environment {
  EnvironmentType current;

  Environment() {
    PackageInfo.fromPlatform().then((PackageInfo packageInfo) {
      switch (packageInfo.packageName) {
        case "com.demo.qa":
          current = EnvironmentType.qa;
          break;
        default:
          current = EnvironmentType.dev;
      }
    });
  }
}

Upvotes: 31

Related Questions