たかぎとねこの忘備録

プログラミングに関する忘備録を自分用に残しときます。マサカリ怖い。

ビルドバリアントごとに処理の実装を切り替えたい場合に発生したコンフリクトを解消する方法

ビルドバリアントでは、mainディレクトリに置いてあるファイルとの差分の内容を、ビルドバリアントのディレクトリに配置することで、そのビルドバリアントを選択してビルドした際に優先的に読み込まれるのかと思っていた。

結論から言うと、ビルドタイプの名称をもつディレクトリを作成し、mainディレクトリと構成の齟齬が無いように差分のファイルを配置することが必要です。

Androidのビルドバリアントをイチから理解する | フューチャー技術ブログ

これを踏まえて、sodaビルドタイプとcolaビルドタイプを作成してみた。

buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
    debug {
        applicationIdSuffix ".debug"
        debuggable true
    }
    cola {
        applicationIdSuffix ".cola"
        debuggable true
    }
    soda {
        applicationIdSuffix ".soda"
        debuggable true
    }
}

そして、次のようにmain/ソースセットにGreeting.ktを配置した。

package com.takagimeow.material3catalog.components

class Greeting {
    fun greet() = "Main Greeting"
}

ファイル階層は次の通り。

  • src
    • main
      • java
        • com.takagimeow.material3catalog
          • components
            • Greeting.kt

そして、sodaビルドタイプ固有のファイルを作成するために次のディレクトリ階層を作成した。

  • src
    • soda
      • java
        • com.takagimeow.material3catalog
          • components
            • Greeting.kt

Greeting.ktの内容は次の通り。

package com.takagimeow.material3catalog.components

import androidx.compose.material3.Text
import androidx.compose.runtime.Composable


class Greeting {
    fun greet() = "Soda Greeting"
}

すると、次のようなRedeclaration: Greetingエラーが発生した。

色々調べた結果、実装をビルドバリアント毎に変えたいクラスやコンポーザブルなどのリリース用の実装は、main/ソースセットに配置するのではなく、新たにreleaseビルドタイプ固有のファイルを作成する必要があることがわかった。

gradle - Error Redeclaration class configuring Android build variants - Stack Overflow

なので、main/ソースセットに配置したGreeting.ktは一旦削除する。そして、releaseビルドタイプ固有のファイルとしてGreeting.ktを新たに作成する。

  • src
    • release
      • java
        • com.takagimeow.material3catalog
          • components
            • Greeting.kt

これにより、Redeclarationエラーは解消される。

試しに、上記で定義したGreetingクラスのgreet()MainActivityで呼び出してみる。

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.d("MainActivity", "${Greeting().greet()}")
        setContent {
            Material3CatalogTheme {
                // A surface container using the 'background' color from the theme
                Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
                    Greeting(stringResource(id = R.string.app_name))
                }
            }
        }
    }
}

[Build] -> [Select Build Variant]に移動して、ビルドバリアントをsodaに切り替えて実行してみると、sodaビルドタイプで定義した内容が優先的に実行されるようになる。

実行した結果、LogcatにSoda Greetingと表示されていることがわかる。

今度は、colaビルドバリアントに変更して実行してみることにする。

もちろんcolaビルドタイプ固有のGreeting.ktを作成していないので、Unresolved referenceエラーが発生する。

このように、ビルドバリアントごとに実装を切り替えたい場合はその実装をmainディレクトリには配置せずにreleaseディレクトリを作成してその中に本番用の実装を定義するようにすることで、同じパッケージ名でファイルを作成したとしてもエラーを回避することができるようになる。

参考

ビルドバリアントによる複数バージョンのAPKのビルド - ZOZO TECH BLOG

ビルド バリアントを設定する  |  Android デベロッパー  |  Android Developers