Установка переменных среды в Flutter
Например, создание клиента для API, такого как Twitch.
В двоичном файле Dart CLI я мог бы использовать общую переменную среды или переменную определения Dart. Например, используя оба как запасные варианты:
main() {
String clientId =
// dart -dCLIENT_ID='abc bin/example.dart
// This is considered "compiled-into" the application.
const String.fromEnvironment('CLIENT_ID') ??
// CLIENT_ID='abc' dart bin/example.dart
// This is considered a runtime flag.
Platform.environment['CLIENT_ID'];
// Use clientId.
}
Есть ли у Flutter способ установить один или оба из них, в частности...
- Во время разработки
- Когда отправлен в продукт
Рад помочь с некоторыми документами, как только я выясню, как:)
11 ответов
Начиная с Flutter 1.17, вы можете определять переменные времени компиляции, если хотите.
Для этого просто используйте --dart-define
аргумент во время flutter run
или flutter build
Если вам нужно передать несколько пар ключ-значение, просто определите --dart-define
многократно:
flutter run --dart-define=SOME_VAR=SOME_VALUE --dart-define=OTHER_VAR=OTHER_VALUE
а затем в любом месте вашего кода вы можете использовать их, например:
const SOME_VAR = String.fromEnvironment('SOME_VAR', defaultValue: 'SOME_DEFAULT_VALUE');
const OTHER_VAR = String.fromEnvironment('OTHER_VAR' defaultValue: 'OTHER_DEFAULT_VALUE');
Кроме того, их можно использовать и в собственных слоях.
Если что - вот статья, которая объясняет больше
Для конфигурации общий шаблон, который я видел, состоит в использовании отдельных основных файлов. т.е.
flutter run -t lib/production_main.dart
а также
flutter build apk -t lib/debug_main.dart
А затем в этих разных основных файлах настройте нужные конфигурации.
С точки зрения чтения идентификаторов, вы можете сделать это из произвольных активов https://flutter.io/assets-and-images/.
Я полагаю, что во Flutter можно читать из среды, как вы предлагаете, однако я не знаю, как установить эти переменные среды на iOS или Android.
Так как я пытался решить эту проблему и столкнулся с этой темой, я просто хотел добавить это для людей, которые ищут решение в будущем... Если все, что вам нужно, это среды PROD/DEV, то теперь есть поддерживаемый способ получить, если приложение находится в производстве или нет:
const bool isProduction = bool.fromEnvironment('dart.vm.product');
По предложению:
Чтобы запустить ваше приложение (в
flutter run
)
-
flutter run --dart-define=EXAMPLE_API_ENDPOINT=https://api.example.com/
Чтобы выпустить ваше приложение (в
flutter build
)
Мое приложение не позволяло пользователям входить в систему. Я понял, что переменные среды были пустыми строками в приложении, а не их фактическими значениями.
- iOS:
flutter build ipa --dart-define=EXAMPLE_API_ENDPOINT=https://api.example.com/
- Андроид:
flutter build apk --dart-define=EXAMPLE_API_ENDPOINT=https://api.example.com/
документация
От
flutter run --help
или же
flutter build ipa --help
,
--dart-define
показывает:
Additional key-value pairs that will be available as
constants from the String.fromEnvironment, bool.fromEnvironment,
int.fromEnvironment, and double.fromEnvironment constructors.
Multiple defines can be passed by repeating "--dart-define"
multiple times.
Я использую простой сценарий оболочки для создания определений дротиков. В моем приложении есть 3 варианта сборки:, и. Переменные среды были определены в обычном файле.
env/
├── dev.env
├── prod.env
└── staging.env
Вот сценарий для создания
dart-defines
из
.env
файл.
#!/bin/bash
# scripts/generate_dart_defines.sh
case "$1" in
"dev") INPUT="env/dev.env"
;;
"staging") INPUT="env/staging.env"
;;
"prod") INPUT="env/prod.env"
;;
*)
echo "Missing arguments [dev|staging|prod]"
exit 1
;;
esac
while IFS= read -r line
do
DART_DEFINES="$DART_DEFINES--dart-define=$line "
done < "$INPUT"
echo "$DART_DEFINES"
Вот сценарий для запуска сборки.
#!/bin/bash
# build.sh
if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ]; then
echo -e "Missing arguments: [apk|appbundle|ios] [release|debug|profile] [dev|staging|prod]"
# invalid arguments
exit 128
fi
DART_DEFINES=$(scripts/generate_dart_defines.sh $3)
if [ $? -ne 0 ]; then
echo -e "Failed to generate dart defines"
exit 1
fi
echo -e "artifact: $1, type: $2, flavor: $3\n"
echo -e "DART_DEFINES: $DART_DEFINES\n"
eval "flutter build $1 --$2 --flavor $3 $DART_DEFINES"
Скрипт принимает 3 аргумента. Первый - артефакт
apk
,
appbundle
или
ios
. Второй - тип сборки
release
,
debug
или
profile
. Третий - вкус сборки,
dev
,
staging
или
prod
.
./build.sh apk release prod
Обратите внимание, что вам также необходимо отдельно настроить android и ios для разных сборок. https://developer.android.com/studio/build/build-variants
https://shockoe.com/ideas/development/how-to-setup-configurations-and-schemes-in-xcode/
Если у вас есть несколько переменных среды, используйте опцию--dart-define-from-file=env.json
.
Бывший:
flutter build web --dart-define-from-file=env.json
или
flutter run --dart-define-from-file=env_dev.json
Поместите env.json в корень, где находится pubspec.yaml.
Примеры json-файлов
окр.json
{ "backend_url": "https://server.com" }
env_dev.json
{ "backend_url": "https://dev.server.com" }
Пример использования:
const backendUrl = String.fromEnvironment('backend_url', defaultValue: 'SOME_DEFAULT_VALUE');
Если вы используете версию Flutter >= 3.7, вы можете передать переменные среды двумя способами: через аргумент или через файл конфигурации. например:
flutter run --dart-define=BASE_URL=http://localhost:3000
Или вы можете создать файл, такой как env.json, и установить в нем все нужные переменные, например:
{
"BASE_URL": "http://localhost:3000",
"TEST_USER": "test_user"
}
а затем передайте файл:
flutter run --dart-define-from-file=env.json
И если ваша версия Flutter <3.7, у вас есть только первый вариант.
Я делаю
agree
с ответом, опубликованным @tatsuDn, но я хотел предоставить решение, которое загружает ваши переменные среды из файла .env .
Сначала создайте файл в корневой папке вашего проекта.
Убедитесь, что вы добавили файл в свой
pubspec.yaml
а также
[git] ignore
Это.
Вот как должен выглядеть ваш файл
API_KEY=sampleapikey
# This line is a comment
# The white line above will be ignored
HEADER=sampleapiheader
ANOTHER_UNIQUE_KEY=theValueOfThisKey
KEY_CONTAINS_#=*234*5#
KEY_CONTAINS_EQUALS=IP8iwe=0&
Вот как будет выглядеть раздел ваших активов.
# To add assets to your application, add an assets section, like this:
assets:
- assets/images/
- assets/flags/
- .env
Наконец, загрузите переменную среды, прочитав и проанализировав файл, чтобы получить
Map<String, String>
который содержит ваши пары ключ-значение.
Future<Map<String, String>> parseStringToMap({String assetsFileName = '.env'}) async {
final lines = await rootBundle.loadString(assetsFileName);
Map<String, String> environment = {};
for (String line in lines.split('\n')) {
line = line.trim();
if (line.contains('=') //Set Key Value Pairs on lines separated by =
&&
!line.startsWith(RegExp(r'=|#'))) {
//No need to add emty keys and remove comments
List<String> contents = line.split('=');
environment[contents[0]] = contents.sublist(1).join('=');
}
}
return environment;
}
Вы можете поместить быструю кнопку в свой код, чтобы проверить, правильно ли загружаются переменные среды.
ElevatedButton(
onPressed: () async {
final env = await parseStringToMap(assetsFileName: '.env');
print(env);
},
child: Text('Print Environment Variables')
),
Вот вывод файла .env выше.
>>>I/flutter ( 7182): {API_KEY: sampleapikey, HEADER: sampleapiheader, ANOTHER_UNIQUE_KEY: theValueOfThisKey, KEY_CONTAINS_#: *234*5#, KEY_CONTAINS_EQUALS: IP8iwe=0&}
Примечания. Вам нужно будет перезапустить приложение (не перезагружать в горячем режиме), чтобы
.env
Актив загружен.
Вы также можете просто загрузить свои переменные в файл json [это может быть полезно, когда у вас есть нестроковые переменные среды, и вы не хотите анализировать строку.
Чтобы избежать ввода-вывода, рекомендуется просто загрузить переменные среды один раз и получить к ним доступ через приложение, используя локаторы сервисов, такие как
GetIt
.
Flutter ввел переменные среды во время компиляции, используя--dart-define
аргумент. Если у вас есть более одной переменной среды, используйте--dart-define-from-file
аргумент желательно.
Для одной переменной среды выполните следующие действия:
flutter run --dart-define=VAR_NAME=SOME_VALUE
Если существует более одной переменной среды, выполните следующие действия:
- Создайте файл JSON, содержащий переменные.
{
"VAR_A": someValue,
"VAR_B": anotherValue
}
- передать этот файл команде сборки/запуска флаттера
flutter run --dart-define-from-file=config.json
где config.json — созданный файл JSON, содержащий переменные.
Чтобы получить эти переменные из вашего кода, в зависимости от типа данных можно использовать любое из следующих действий:
const VAR_A = String.fromEnvironment('VAR_A', defaultValue: 'SOME_DEFAULT_VALUE');
const VAR_B = int.fromEnvironment('VAR_B', defaultValue: 1);
const VAR_C = bool.fromEnvironment('VAR_C', defaultValue: false);
Следует отметить, что для double не существует конструкторов fromEnvironment. Приведенные выше аргументы также можно использовать сflutter build
команда.
В статье здесь подробно объясняется, как это сделать.
хотя приведенные выше ответы верны из python и reactjs, я использовал dotenv и нашел то же самое для флаттера для загрузки файла .env https://pub.dev/packages/dotenv
Создайте класс:
import 'package:flutter/foundation.dart';
class AppUtils {
static String get clientId {
if (kDebugMode) return 'debug_id';
else if (kProfileMode) return 'profile_id';
else if (kReleaseMode) return 'production_id';
else if (kIsWeb) return 'web_mode_id';
throw ArgumentError('No mode detected');
}
}
Применение:
var id = AppUtils.clientId;