11
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

FlutterからXcodeへ環境変数を渡す

Last updated at Posted at 2020-12-28

概要

FlutterでiOSアプリをビルドする際には、本番環境と開発環境でGoogleService-info.plistBundle Identifierの切り替えが必要となるケースが多いと思います。
この切替には複数のSchemeを用意する方法、Flavorを使う方法、ビルド時の--release--debugを使って切り分ける方法がありますが、Flutter 1.17からビルド引数の--dart-defineで定数を渡せるようになりました。今回はこのビルド変数の渡し方を説明します。

Android編はこちら

前提

  • Flutterのサンプルプロジェクトを作成しシミュレーターで実行できる
  • Flutter 1.20以降

環境

$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 1.22.4, on Mac OS X 10.15.7 19H2 darwin-x64, locale en-JP)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 12.1)
[✓] Android Studio (version 4.1)
[✓] Connected device (1 available)      

サンプルコード

前半の設定

前半では、FlutterからXcodeへ変数を渡し確認してみます。

Flutterプロジェクトの用意

既存のプロジェクトでも、新規にプロジェクトを作成しても問題ありません。
一度ビルドして、シミュレーター上で実行できることを確認しておいてください。

Xcodeの設定

Android StudioのProject Windowから下記の[project]/iosを右クリックしFlutter内のOpen iOS module in Xcodeをクリックします。すると該当ProjectのXcodeが開きます。
Screen_Shot_2020-12-29_at_8_30_13.png

XcodeメニューのProduct>Scheme>Edit Schemeをクリックします。
Screen_Shot_2020-12-28_at_10_29_16.png

開いたウィンドウのBuild>Pre-actionsを開き、Provide build setting fromを設定し、画面下部の+を押してNew Run Script Actionを追加します。
Runner_xcworkspace.png

以下のスクリプトを追加します。urldecode()を挟むことで、文字列がURLデコードされ見やすくなります。${PROJECT_DIR}はFlutterのiosディレクトリです。$DART_DEFINESはFlutterからXcodeに渡される定数です。
そして、このスクリプトが実行されると[project]/ios/prebuild.logが自動的に生成され、その中にFlutterから渡したビルド引数が書き込まれます。

function urldecode() { : "${*//+/ }"; echo "${_//%/\\x}"; }

exec > ${PROJECT_DIR}/prebuild.log 2>&1
echo $(urldecode "$DART_DEFINES")

Flutterの設定

Flutter側はビルド時に指定します。

flutter build ios --dart-define=DEFINE_HELLO=world --dart-define=DEFINE_FOO=bar

Android Studio を使っている場合Run/Debug Configurationsにて設定可能です。
Run_Debug_Configurations.png

前半の動作確認

Flutterをビルドすると[project]/ios/prebuild.logが出力されていると思いますので確認してみてください。以下のように出力されていれば、ここまでは成功です。

DEFINE_HELLO=world,DEFINE_FOO=bar

後半の設定

後半では、実際にXcodeへ渡した変数の値をFlutter上で確認してみます。

Xcodeの設定

Flutterから渡された変数をXcode上で扱えるように設定していきます。
まずFlutterから渡された変数のデフォルト値を作成します。

※ このデフォルト値の設定について、私は必要性を理解できませんでした。参照元のDenisさんの記事では以下のようにだけ書かれています。もしかすると、複数人で開発をしたとき、うっかりビルド引数を指定することを忘れるとエラーとなってしまうのを避けるためかもしれません。

Consider putting Defineexample.xcconfig after Defineexample-defaults.xcconfig, so values from Flutter Run command could override default values.

XcodeのFlutterディレクトリで右クリックしNew Fileを追加します。
Screen_Shot_2020-12-28_at_13_17_35.png
Configuration Settings Fileを選択しTargetsにチェックを入れ、DartDefineDefaults.xcconfigという名前でFlutterディレクトリに保存します。(名称は何でも大丈夫です)
Save_and_Runner_xcworkspace.png

次に作成したDartDefineDefaults.xcconfigを開きデフォルト値を設定します。
DartDefineDefaults_xcconfig.png

その後Debug.xcconfigRelease.xcconfigに、先程つくったDartDefineDefaults.xcconfigと、このあと設定するDartDefine.xcconfigincludeする設定を追加していきます。
Debug_xcconfig.png

このときDartDefineDefaults.xcconfigが先に読み込まれ、その後にDartDefine.xcconfig(後のスクリプトで自動生成される)が読み込まれるようにしてください。こうすることで、例えば先にDEFINE_FOO=barが定義され、後からDEFINE_FOO=hogeが定義された場合、後からの値で上書きすることができます。後からの値が定義されていなければ、デフォルト値のみが定義されるという仕組みです。

次にPre-actionsの中身を変えていきましょう。
Release_xcconfig.png

このような形にスクリプトを修正します。Denisさんの元記事ではビルド引数のPrefixでgrepし、特定の引数のみを読み込むように工夫されています) [2020/12/31 下記に修正]
工夫されていますではなく、対応したほうが良さそうです。
下の例のように定数のPrefixでgrepするのが良さそうです。これをやらないとdefine_items[@]の中にはflutter.inspector.structuredErrors=trueなどが入ってきます。これが原因なのかは定かではありませんが、意図しない値がDartDefine.xcconfigに書き込まれることで、うまくコンパイルできないケースがありました。(実際には落ちずに中途半端な形でコンパイルが通ってしまい、原因を特定するのにすごく時間がかかりました。)

function urldecode() { : "${*//+/ }"; echo "${_//%/\\x}"; }

#exec > ${PROJECT_DIR}/prebuild.log 2>&1
#echo $(urldecode "$DART_DEFINES")

IFS=',' read -r -a define_items <<< "$DART_DEFINES"

for index in "${!define_items[@]}"
do
    define_items[$index]=$(urldecode "${define_items[$index]}");
done

#printf "%s\n" "${define_items[@]}" > ${SRCROOT}/Flutter/DartDefine.xcconfig
printf "%s\n" "${define_items[@]}"|grep '^DEFINE_' > ${SRCROOT}/Flutter/DartDefine.xcconfig

Xcodeの設定の最後にBundle nameBundle identiferに定義した変数が反映するよう修正します。
Runner_xcodeproj.png
これでXcode側の設定は完了です。

Flutterの設定

基本的には、下記のサンプルコードを参考にしてもらえれば大丈夫なはずです。
https://github.com/yana1316/flutter_define

pubspec.yamlに追記します。

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.0
  package_info: ^0.4.3+2 # 追加

あとはmain.dartでパッケージ名を表示させます。

Text(
  'Package Name',
  style: Theme.of(context).textTheme.headline5,
),
FutureBuilder<PackageInfo>(
    future: PackageInfo.fromPlatform(),
    builder: (context, value) {
      if (!value.hasData) {
        return Container();
      }
      return Text(
        value.data.packageName,
        style: Theme.of(context).textTheme.headline6,
      );
    }
),

後半の動作確認

うまく行けば、アプリの名前の後ろに指定した値(DEFINE_FOO=barとしたならbar)が付き、画面上ではパッケージ名の後ろに値がついていると思います。
iPhone_SE_–_2nd_generation_–_14_3.png

参考

11
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?