【Flutter】Build flavor を使うプロジェクトを作成する
flavorのWEB対応について(追記:2024-02-26)
とある日の会話
確かにAndroidStudioのRun/Debug Configurations
にもBuild flavor
という項目は存在していまして、自分も何でここを使わないんだろうなぁ〜とは思っていました。
「どーせ、iOS側の設定が色々と面倒くさいからやろ」くらいに見過ごしてきましたが、いい機会だしやってみることに。
以下、flutter create
からの差分を記載していく流れになります。
(最低限の内容で記載していくため、実際のコードとは異なります)
Android
高度な次元で悩んでるたっつー氏は置いておいて、Android側の設定を見てみましょう。
applicationIdにsuffixをつける
android/app/build.gradle
に対して、以下のようにproductFlavorsの設定を追加します。
この例では、デフォルトをdev
として、prod
のビルド以外でapplicationIdにsuffixをつけるような設定にしてあります。
android {
+ flavorDimensions += "hoge"
+ productFlavors {
+ dev {
+ isDefault = true
+ applicationIdSuffix = ".dev"
+ dimension = "hoge"
+ }
+ stg {
+ applicationIdSuffix = ".stg"
+ dimension = "hoge"
+ }
+ prod {
+ dimension = "hoge"
+ }
+ }
}
label(ディスプレイ名)をflavorごとに分かりやすくする
AndroidManifest.xml
において、app_name
という値を使用してlabel
を表示するように修正します。
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
- android:label="app"
+ android:label="@string/app_name"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
そうしたら、以下のように各Flavor名のディレクトリを用意し、flavorName/res/values/strings.xml
のようなファイルを作ります。
このとき、Flavorごとに表示したいアプリ名を入れてください。
+<resources>
+ <string name="app_name">(dev)APP</string>
+</resources>
+<resources>
+ <string name="app_name">(stg)APP</string>
+</resources>
+<resources>
+ <string name="app_name">APP</string>
+</resources>
productFlavors
の便利なところは、Flavorのディレクトリにリソースを置いておくことで、Flavorに応じてよしなに使用されるところです。
iOS
Configurationsを複製する
プラスボタンを押すと、複製ができるので、Flavorに合わせて複製し、リネームします。
Targetsを複製する
同じようにTargetsもFlavorに合わせて複製し、リネームします。
複製時にInfo.plist
も一緒に出来上がるので、Flavorごとにフォルダを用意して、配置しなおします(ここはFinderとXcodeを駆使して頑張ってください)。
Xcodeでのファイル操作が難しいと感じた場合、こちらの記事を閲覧するとスムーズに行くと思います。
ちなみに、配置しなおす中でInfo.plist
の参照が狂っても、ここで紐つけなおせます。
Testを編集する
複製をするとHost Application
が飛んでるので、適切なTargetを選択しなおします。
また、同様に関係ないTarget(複製元)が入っているので、それも除いておきます。
Schemeを編集する
Manage Schemes ...
を開いて、プラスボタンから新しいSchemeを作成します。
このとき、Test側を選んで作成しました。
Podを編集する
package_info_plus
などpodを必要とするパッケージを追加して、一旦ビルドすると、Podfile
ができるので、それを編集していきます。
作成したConfigurationsに合う形に編集します。
project 'Runner', {
- 'Debug' => :debug,
- 'Profile' => :release,
- 'Release' => :release,
+ 'Debug-prod' => :debug,
+ 'Debug-stg' => :debug,
+ 'Debug-dev' => :debug,
+ 'Profile-prod' => :release,
+ 'Profile-stg' => :release,
+ 'Profile-dev' => :release,
+ 'Release-prod' => :release,
+ 'Release-stg' => :release,
+ 'Release-dev' => :release,
}
作成したTargetsに合う形に編集します。
-target 'Runner' do
- use_frameworks!
- use_modular_headers!
-
- flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
- target 'RunnerTests' do
- inherit! :search_paths
- end
-end
+target 'Prod' do
+ use_frameworks!
+ use_modular_headers!
+
+ flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
+ target 'ProdTests' do
+ inherit! :search_paths
+ end
+end
+
+target 'Stg' do
+ use_frameworks!
+ use_modular_headers!
+
+ flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
+ target 'StgTests' do
+ inherit! :search_paths
+ end
+end
+
+target 'Dev' do
+ use_frameworks!
+ use_modular_headers!
+
+ flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
+ target 'DevTests' do
+ inherit! :search_paths
+ end
+end
最後にxcconfigを編集します。
-#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
+#include? "Pods/Target Support Files/Pods-Dev/Pods-Dev.debug-dev.xcconfig"
+#include? "Pods/Target Support Files/Pods-Stg/Pods-Stg.debug-stg.xcconfig"
+#include? "Pods/Target Support Files/Pods-Prod/Pods-Prod.debug-prod.xcconfig"
-#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
+#include? "Pods/Target Support Files/Pods-Dev/Pods-Dev.release-dev.xcconfig"
+#include? "Pods/Target Support Files/Pods-Stg/Pods-Stg.release-stg.xcconfig"
+#include? "Pods/Target Support Files/Pods-Prod/Pods-Prod.release-prod.xcconfig"
一旦、必要な組み合わせを全て入れましたが、pre-actionなどで、flavorに必要なものだけを使う方がいいなぁと思いつつもシンプルに行きたいのでやめました。
SPMの設定をする(2024-08-07追記)
全ては公式ドキュメントを見れば分かりますが、一応。
まずは以下のコマンドを入力して、SPMをONにします。
flutter config --enable-swift-pacakge-manager
対象のアプリケーションにurl_launcher
などを入れてdart pub get
を行うと、以下のファイルが生成されます。
(余談ですが、自分はFlutter3.24.0でやれると思っており、ファイルが作成されなかったため、手動で作成しました。その後、SPMに追加がされなかったので、mainで実行して成功するアホをかましましたが、階層や名称が合っていれば動いてくれました。)
ios
└── Flutter
└── ephemeral
└── Packages
└── FlutterGeneratedPluginSwiftPackage
├── Package.swift
└── Sources
└── FlutterGeneratedPluginSwiftPackage
└── FlutterGeneratedPluginSwiftPackage.swift
この FlutterGeneratedPluginSwiftPackage
を使用してゴニョゴニョやっていきます。
- RunnerのPacakgeDependenciesで追加を選択します。
- Localファイルからの追加を選択します。
- Finderが開かれるので
FlutterGeneratedPluginSwiftPackage
のフォルダを選択し、Targetを入れます。
- 追加されると以下のように3で選択したTargetのFramework部分に追加されるので、この作業をTargetごとに実施してください。
- Schemeをいじります。
- TargetそれぞれでBuild/Pre-actionsへ以下を追加します(名称も変更しています)。
おしまいです。
PluginがSPMに対応されている場合はSPMに、そうでない場合はPodにて取得されます。
Bundle Identifier等を編集する
各Targetごとに変更したい値を編集していきます。
以下はBundle Identifier
とBundle display name
の編集例です。
なぜTargetを分けたのか?
Info.plist
やAssets.xcassets
など、Flavorごとに異なるリソースをシンプルに管理したかったからです。
Target Membership
を使い、リソースを参照できるTargetを絞りながら、各TargetのCopy Bundle Resources
で読み込ませればよいので、別途スクリプトを組む必要がありません。
終劇
アイコンとかの仕分け方法も追々、記載をしていきたいと思います。
Discussion