背景
Flutter で作ったアプリを flutter run や build する際は、以下のように --flavor オプションでビルドフレーバーを、さらに -t オプションを使ってエントリポイントの dart ファイルを指定します。
flutter run --flavor dev -t lib/main_dev.dart
Android Studio でビルド/実行するときはプロジェクトの Configuration でフレーバー名とエントリーポイントの dart ファイルを指定します。
しかし、冗長です。単に、フレーバー hoge
を設定したら自動で main_hoge.dart
が選ばれてくれないだろうか...。
(※iOSではスキーム毎に.xcconfigファイルを作ってFLUTTER_TARGETを指定すれば、自動化できます)
やってみたら、一応できましたので、やリ方をメモしておきます。
ただ、実装はかなりトリッキーな方法なので、あまりオススメではありません。
flutter run や build 以外の方法、たとえば gradle のタスクを直接実行するなどすると、正しく動かないかもしれません。
やり方
Flutter 2.2.3, gradle 6.7を前提とします。
./android/app/build.gradle
で flutter.gradle
を読み込んでいる行の後に、以下のコードを追加すると、 main.dart
の代わりに main_<flavor>.dart
が読み込まれるようになります。
...
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
// ↑この行より後に以下を追加する
def getCurrentFlavor() {
String tskReqStr = getGradle().getStartParameter().getTaskRequests().toString()
def matcher = tskReqStr =~ /(assemble|bundle)(\w+)(Release|Profile|Debug)/
if(matcher.find()) {
return matcher.group(2).toLowerCase()
}
return null
}
if (project.hasProperty('target')) {
if (project.target == null || project.target ==~ /.*main\.dart$/) {
def flavor = getCurrentFlavor()
project.target = "lib/main_${flavor}.dart"
} else {
// 外部から main.dart 以外のファイルが指定されていた場合は、
// こちらに分岐。外部から指定されたdartファイルを優先する
}
}
実行中のタスクの名称を無理やり読み込んで、そこからフレーバー名を抽出し、project.target
を書き換えるという、無茶苦茶な方法ですが、一応うごくようです。
フレーバー名の抽出ロジックは、assemble<Flavor><BuildType>
(apk 生成時)か bundle<Flavor><BuildType>
(appbundle 生成時)の Gradle タスク名を前提に書いてあるため、それ以外の名前のタスクが叩かれる場合は、適宜修正する必要があります。
補足
次のように記述すると一見、期待通り動きそうに思えますが、動きません。project.target はフレーバー毎のプロパティではないため、フレーバーの指定によらず、いちばん最後に書いた project.target が有効になってしまいます。
// 実際には動かない例
...
flavorDimensions "env"
productFlavors {
dev {
dimension "env"
applicationIdSuffix ".dev"
project.target = "lib/main_dev.dart"
}
stg {
dimension "env"
applicationIdSuffix ".stg"
project.target = "lib/main_stg.dart"
}
prod {
dimension "env"
project.target = "lib/main_prod.dart"
}
}
..