Flutterアプリを開発/製品版で分けてビルド・実行させる

Flutterアプリを開発していると、通信先のサーバーや動作確認の都合でアプリを開発環境/製品版等で分けてビルドしたり実行したいシーンがあると思います。

そのようにビルドを分けることを「フレーバー」と呼ぶそうで、そのフレーバーを指定してビルドし、かつ実行時にフレーバーを判定して処理させるやりかたについてまとめてみました。

フレーバーを定義する

build.gradleでフレーバーを定義します。

以下は開発版(development)、製品版(production)で分けた定義の例です。

android {
    :
    flavorDimensions "flavor-type"

    productFlavors {
        // 開発版のフレーバー
        development {
            dimension "flavor-type"
            applicationIdSuffix ".development"
            manifestPlaceholders = [appName: "アプリ名(開発版)"]
        }
        // 製品版のフレーバー
        production {
            dimension "flavor-type"
            manifestPlaceholders = [appName: "アプリ名"]
        }
    }
}
  • productFlavorsの子要素の名前はdevelopment・productionとしていますが、自由に命名できるようです
    • dev、staging、prodとかでも可
  • applicationIdSuffixはdevelopmentでビルドした場合に、アプリケーションID(Javaのパッケージ名のようなもので、com.xxx.yyyのようにアプリを識別するID)の最後に付与できる文字列です
    • 「.development」をつけてビルドすることで、一つのAndroid端末に両方でビルドしたものをインストールすることができるようになります

フレーバーごとに出力するapkファイル名を変える

def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
    flutterVersionName = '1.0'
}
:
android {
    :
    defaultConfig {
        :
        versionName flutterVersionName
    }
    : 
    applicationVariants.all { variant ->
        if (variant.buildType.name != "release") {
            return
        }
        variant.outputs.all {
            variant.productFlavors.each { productFlavor ->
                outputFileName = "app-${productFlavor.name}-${versionName}.apk"
            }
        }
    }
    ;
}
  • 前節で定義したフレーバーの名前を${productFlavor.name}で参照しています
  • ${versionName}はdefaultConfigで設定された値、つまりflutterのpubspec.yamlで指定されたバージョン名になります

フレーバーごとにアプリ名を変更する

<manifest...>
    <application
        android:label="${appName}"
        :
    </application>
    :
</manifest>
  • フレーバー定義で指定したmanifestPlaceholdersのパラメータをAndroidManifest.xmlで指定できます
  • ${appName}がdevelopmentの場合は「アプリ名(開発版)」、production「アプリ名」でインストールされます
    • Android設定画面のアプリ一覧とアプリ詳細画面に表示される値になります

プログラムでフレーバーを取得する

プログラムから直接フレーバーを取得する方法はないようですが、build.gradleで指定したapplicationIdSuffixがパッケージ名になるため、それをフレーバーの判定に用いることができます。

パッケージ名の取得にはpackage_info_plusパッケージを利用します。

import 'package:package_info_plus/package_info_plus.dart';
:
PackageInfo packageInfo = await PackageInfo.fromPlatform();
if (packageInfo.packageName.contains('com.xxx.yyy.development')) {
  // TODO 開発モードでの動作
} else {
  // TODO 製品モードでの動作
}
  • .contains(‘xxx’)で判定していますが、indexOfだったり正規表現だったり他にも判定の仕方はあると思います
  • これによってassetsの読み込みも変更できるため、例えば開発・製品版それぞれの設定ファイル(例:assets/development.yaml、assets/production.yaml)を用意しておき、上記の分岐でそれぞれ読み込めば、開発版・製品版それぞれでの設定を読み込み動作させることもできます

フレーバーごとにアプリアイコンを変更する

flutter_launcher_iconsパッケージを使用します。(バージョンは0.11.0以上)

Flutterプロジェクトのルートフォルダにフレーバーに対応したファイルを置きます。

  • フレーバーdevelopment用
    • flutter_launcher_icons-development.yaml
  • フレーバーproduction用
    • flutter_launcher_icons-production.yaml

それぞれのファイルにはそれぞれ開発版・製品版に対応した画像を読み込ませておきます

flutter_icons:
  android: true
  image_path_android: "assets/icon/app_icon_development.png"
  adaptive_icon_background: "#ffffff"
  adaptive_icon_foreground: "assets/icon/app_icon_adaptive_development.png"
flutter_icons:
  android: true
  image_path_android: "assets/icon/app_icon_production.png"
  adaptive_icon_background: "#ffffff"
  adaptive_icon_foreground: "assets/icon/app_icon_adaptive_production.png"

アプリアイコンの生成コマンドは1回実行で問題ないようです。

C:\Users\xxx\app>flutter pub run flutter_launcher_icons:main

フレーバーごとにビルドする

flutter buildコマンドの–flavorオプションに定義したフレーバー名でビルドを実行します。

rem 開発版
flutter build apk --release --flavor development
rem 製品版
flutter build apk --release --flavor production