拒絕魔改,Flutter動態配置多環境

艾維碼發表於2021-05-12

介紹

多渠道打包常規方式有兩種,Flavor--dart-define,後者是 Flutter1.17新增的命令列可選引數,比Flavor配置更簡單,非常適合用於環境配置。

執行命令:

flutter run --dart-define=DARTDEFINE_APP_ENV=debug 
複製程式碼

通常不同開發環境對應不同的域名,有時候為了更直接區分不同環境,標題和 AppName 也標識區分,所以本文以標題、域名和 AppName 作為要動態更改的環境變數,開啟 --dart-define配置之旅。

Flutter 配置

環境配置

新建一個環境配置檔案,用來獲取命令列中輸入不同的環境變數。

// 環境配置
class EnvConfig {
  final String appTitle;
  final String appDomain;
  EnvConfig({
    required this.appTitle,
    required this.appDomain,
  });
}

// 獲取的配置資訊
class Env {
  // 獲取到當前環境
  static const appEnv = String.fromEnvironment(EnvName.envKey);

  // 開發環境
  static final EnvConfig _debugConfig = EnvConfig(
    appTitle: "debugTitle",
    appDomain: "http://www.debugxxx.com",
  );
  // 釋出環境
  static final EnvConfig _releaseConfig = EnvConfig(
    appTitle: "releaseTitle",
    appDomain: "http://www.releasexxx.com",
  );
  // 測試環境
  static final EnvConfig _testConfig = EnvConfig(
    appTitle: "testTitle",
    appDomain: "http://www.testxxx.com",
  );

  static EnvConfig get envConfig => _getEnvConfig();

// 根據不同環境返回對應的環境配置
  static EnvConfig _getEnvConfig() {
    switch (appEnv) {
      case EnvName.debug:
        return _debugConfig;
      case EnvName.release:
        return _releaseConfig;
      case EnvName.test:
        return _testConfig;
      default:
        return _debugConfig;
    }
  }
}

// 宣告的環境
abstract class EnvName {
  // 環境key
  static const String envKey = "DART_DEFINE_APP_ENV";
  // 環境value
  static const String debug = "debug";
  static const String release = "release";
  static const String test = "test";
}

複製程式碼

EnvName裡宣告瞭三個環境,這是執行命令和打包命令裡要填寫的值。envKey是對應的key

使用配置

main檔案裡使用前面配置的值,標題使用配置的標題,在頁面中顯示配置的域名:

return Scaffold(
      appBar: AppBar(
        title: Text(Env.envConfig.appTitle),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              '配置的域名是:',
            ),
            Text(
              Env.envConfig.appDomain,
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
    );
複製程式碼

執行

在終端輸入命令,先執行debug環境:

flutter run --dart-define=DART_DEFINE_APP_ENV=debug
複製程式碼

注意,這裡的DART_DEFINE_APP_ENVdebug是和env_config裡的對應的。

1.1debug

標題和域名是Env裡配置的對應debug的引數。

然後執行test環境:

flutter run --dart-define=DART_DEFINE_APP_ENV=test 
複製程式碼

1.2 test

IDE配置

命令列容易輸錯怎麼辦?那就配置 IDE 。

  1. 點選選單上的編輯配置

2.1as

  1. 輸入命令:

image-20210511163104710

  1. 新增test的配置:

2.3

複製了一份,命名為test,把引數改為test

image-20210511163150049

  1. 繼續複製一份release

image-20210511163256856

然後要執行哪個環境,選擇對應的配置即可。

Android 配置

不僅僅在 dart 檔案裡使用到配置資訊,原生程式碼也使用到,比如配置推送和bugly,另外測試人員為了區分環境也會要求在配置不同的應用名稱字尾,那麼就需要在原生程式碼裡修改。

build.gradle裡設定預設配置引數

// android/app/build.gradle
/// 設定預設配置引數
def dartDefine = [
        DARTDEFINE_APP_ENV: 'debug',
]
複製程式碼

然後從dart-defines裡獲取定義的鍵值對,新增到dartEnv裡。

// android/app/build.gradle
/// 設定預設配置引數
def dartDefine = [
        DART_DEFINE_APP_ENV: 'debug',
]
if (project.hasProperty('dart-defines')) {
    dartDefine = dartDefine + project.property('dart-defines')
            .split(',')
            .collectEntries { entry ->
                def pair = URLDecoder.decode(entry).split('=')
                [(pair.first()): pair.last()]
            }
}
複製程式碼

定義 resValue ,或者BuildConfig,這裡因為要改應用名,需要引用string資源,所以用 resValue

    defaultConfig {
        applicationId "com.example.flutter_flavors"
        minSdkVersion 16
        targetSdkVersion 30
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
        resValue "string","app_name","flutter_flavor${dartEnv.DART_DEFINE_APP_ENV}"
    }
複製程式碼

在清單檔案引用:

   <application
       android:label="@string/app_name"
        android:icon="@mipmap/ic_launcher">
複製程式碼

每次執行不同的環境,就可以看到不同的應用名字。在程式碼裡也可以通過getString("app_name")獲取到定義的值。

Ios 配置

右鍵專案,選擇在 xcode 裡開啟:

image-20210511154234661

右鍵 Flutter 目錄選擇 new flie,選擇如下所示的型別。填入名稱 Dart

截圖2021-05-11 下午3.43.28

新增預設值:

DART_DEFINE_APP_ENV=flutter_flavor
複製程式碼

在 Debug.xcconfig 和 Release.xcconfig 裡分別新增引用:

#include "DartDefine.xcconfig"
#include "DartDefineConfig.xcconfig"
複製程式碼

第一行是引用我們建立的配置檔案,第二行是在編譯時生成的(下一步配置生成程式碼)。

image-20210511170141342

在 Info 裡修改Bundle name為我們配置的值:

image-20210511164101020

編輯Schema:

image-20210511164222953

截圖2021-05-11 下午5.03.49

這裡有兩個地方需要注意,上面要選中 Runner ,下面的輸出檔名稱要和上一步引用的一致。

到此 Ios 也配置完成。選擇 test 配置執行:

image-20210511170610585

image-20210511170718762

應用名變成了選擇的配置。

image-20210511170753925

打包

打包命令和執行命令的字尾一樣:

flutter build apk --dart-define=DARTDEFINE_APP_ENV=release
複製程式碼

原始碼 Flutter 環境:

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 2.0.5, on Mac OS X 10.15.6 19G2021 darwin-x64,
    locale zh-Hans-CN)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[✓] Xcode - develop for iOS and macOS
[✓] Chrome - develop for the web
[✓] Android Studio (version 4.2)
[✓] VS Code (version 1.56.0)
[✓] Connected device (2 available)
複製程式碼

相關文章