Reputation: 19424
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
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
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}:
Now, under Targets/Runner/Build Settings/User-Defined and add a setting PRODUCT_FLAVOR. Add the flavor name for each configuration:
Then in Dart:
final flavor = await const MethodChannel("flavor_channel").invokeMethod("getFlavor");
Then you're done!
Upvotes: 8
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
Reputation: 1439
You could use the solution from jonahwilliams.
flutter build apk --flavor=paid --dart-define=app.flavor=paid
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
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
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