見出し画像

【Flutter】ビルド環境別の設定

Flutterプロジェクトの環境別設定についてさまざまなやり方がWebで紹介されているが、今回はシンプルな構成を目指す。



作成する環境

ビルドモードとバックエンドが1対1になるようにする。

Staging環境向けのビルドはフレーバーで切り分けるべきかも。が、フレーバーの数だけiOSプロジェクトのConfigurationを用意するのは煩わしいので、ここではProfileビルドに紐づける。

アプリ識別子
Bundle IDやパッケージ名。別にすることで、個別にFirebaseプロジェクトを持たせたり、同じ端末へインストールしたり、などを可能にする。

バックエンド
APIの接続先など。実行中の環境(=ビルドモード)をプログラムで判断して切り分ける。

環境変数
GoogleマップSDKのAPIキーなどネイティブコードで使用したい環境変数は、ビルドモードやフレーバーで切り分けるのはなかなか面倒。なので、ビルドパラメータの環境変数(dart-define)として設定する。

ビルドコマンド

# 環境変数を個別に定義する
$ flutter run --ビルドモード [--dart-define key=value]

# 環境変数ファイルにまとめて定義する
$ flutter run --ビルドモード --dart-define-from-file=path/to/file

個別に定義するやり方しかなかったが、環境変数ファイルにまとめて定義できるようになったのでそちらをベースに考える。


1. アプリ識別子の設定

iOS

TARGETS Runner > Signing & Capabilities
Xcodeで、ConfigurationごとにBundle IDを設定する。

Develop以外のビルドモードはシミュレータで使えないので、実機にインストールしてBundle IDをXcodeで確認する。

$ flutter run --debug
$ flutter run --profile
$ flutter run --release
Devices & Simulators

Android

android/app/build.gradle
ビルドタイプ別に識別子のサフィックスを追加する。

android {
    ...

    buildTypes {
        debug {
            applicationIdSuffix ".dev"
        }
        profile {
            applicationIdSuffix ".stg"
        }
        release {
            ...
        }
    }
}

Google Playからアプリ「Package Names」をエミュレータにインストールし、それぞれのアプリ名を確認する。

2. 環境変数ファイルの作成

プロジェクトルートにenvフォルダを作成し、dev.json、stg.json、prd.jsonの3つの環境変数ファイルを作成する(名前は適当に)

{
  "key": "value"
}

3. 環境変数の取得

dart-define-from-fileオプションをつけてアプリを起動することで、ファイルから読み込んだ環境変数を使えるようになる。

final value = const String.fromEnvironment('key');

4. 環境変数の取得(ネイティブ)

ネイティブのコードで環境変数を取得するのは少し面倒だ。厄介なことに、Googleマップのパッケージはこれが必要である。

iOS

dart-defineの受け皿をInfo.plistにを追加する。

<key>DartDefines</key>
<string>$(DART_DEFINES)</string>

AppDelegate.swift
Info.plistから環境変数を取得する。

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
    ...

    // dart-defineをInfo.plistから取得する
    let dartDefinesString = Bundle.main.infoDictionary!["DartDefines"] as! String
    var dartDefines = [String:String]()
    for definedValue in dartDefinesString.components(separatedBy: ",") {
        let decoded = String(data: Data(base64Encoded: definedValue)!, encoding: .utf8)!
        let values = decoded.components(separatedBy: "=")
        dartDefines[values[0]] = values[1]
    }
    // dart-defineの取り出し方
        // let value = dartDefines["key"]!

    ...
  }
}

Android

android/app/build.gradle
ビルドスクリプトでdart-defineを取得する。

// dart-defineを取得する
def dartDefines= []
if (project.hasProperty('dart-defines')) {
    dartDefines = project.property('dart-defines').split(',').collectEntries{ entry ->
        def pair = new String(entry.decodeBase64(), 'UTF-8').split('=')
        [(pair.first()): pair.last()]
    }
}

// dart-defineを取り出してマニフェストのプレースホルダーへ
// manifestPlaceholders['key'] = dartDefines.key

参考サイト

この記事が気に入ったらサポートをしてみませんか?