ProductFlavors を設定してるライブラリを使用するときは BuildVariant を指定する必要がある

More than 1 year has passed since last update.

問題解決するまで少しハマったので備忘録として残します。

http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Library-Publication

問題

アプリはライブラリに依存してます。

app/build.gradle
apply plugin: 'com.android.application'

android {
    ...

    buildTypes {
        debug   {...}
        release {...}
    }
}

dependencies {
    compile project(':library')
}

使用するライブラリは ProductFlavors を設定しています。

library/build.gradle
apply plugin: 'com.android.library'

android {
    ...

    buildTypes {
        debug   {...}
        release {...}
    }

    productFlavors {
        flavorRed   {...}
        flavorGreen {...}
        flavorBlue  {...}
    }
}

この状態ではビルドは通らず、ライブラリを参照できません。

// Cannot resolve symbol Library
import com.sample.library.Library;

原因

ライブラリの場合、BuildVariant は release がデフォルトとなってます。

公式では By default a library only publishes its release variant. と言ってるけど、ライブラリではなくアプリケーションの場合もそうなのだろうか...?

BaseExtension.java
package com.android.build.gradle

/**
 * Base 'android' extension for all android plugins.
 *
 * <p>This is never used directly. Instead,
 *<ul>
 * <li>Plugin <code>com.android.application</code> uses {@link AppExtension}</li>
 * <li>Plugin <code>com.android.library</code> uses {@link LibraryExtension}</li>
 * </ul>
 */
public abstract class BaseExtension {

    private String defaultPublishConfig = "release"

    ...
}

しかし、Flavor を設定している場合は BuildType と ProductFlavor を組み合わせた BuildVariant の名前を指定する必要があり、当然 release のままでは参照できません。なので上記の問題に沿うなら flavorRedRelease などを指定するべきです。

解決方法

1. defaultPublishConfig を変更する

ライブラリ側で、デフォルトの BuildVariant を指定します。

library/build.gradle
apply plugin: 'com.android.library'

android {
    ...

    defaultPublishConfig "flavorRedRelease"

    buildTypes {
        debug   {...}
        release {...}
    }

    productFlavors {
        flavorRed {}
        flavorGreen {}
        flavorBlue {}
    }
}

しかし、この場合では flavorRedRelease しか使えず、他の BuildVariant を指定すると怒られます。

app/build.gradle
dependencies {
//  compile project(':library') // OK
    compile project(path: ':library', configuration: 'flavorRedDebug') // NG
}

イケてないです。

Error:Configuration with name 'flavorRedDebug' not found.

2. publishNonDefault を true にする

ライブラリ側で、すべての BuildVariant を公開する設定を true にします。

library/build.gradle
apply plugin: 'com.android.library'

android {
    ...

    publishNonDefault true

    buildTypes {
        debug   {...}
        release {...}
    }

    productFlavors {
        flavorRed {}
        flavorGreen {}
        flavorBlue {}
    }
}

publishNonDefault はデフォルトでは false となっています。

BaseExtension.java
package com.android.build.gradle

/**
 * Base 'android' extension for all android plugins.
 *
 * <p>This is never used directly. Instead,
 *<ul>
 * <li>Plugin <code>com.android.application</code> uses {@link AppExtension}</li>
 * <li>Plugin <code>com.android.library</code> uses {@link LibraryExtension}</li>
 * </ul>
 */
public abstract class BaseExtension {

    private boolean publishNonDefault = false

    ...
}

これによりアプリ側から、ライブラリの全ての BuildVariant を使用することが可能となります。ただし、ライブラリ側で defaultPublishConfig を変更していない場合は、アプリ側から BuildVariant を指定しないと怒られます。

app/build.gradle
dependencies {
    compile project(':library') // NG
//  compile project(path: ':library', configuration: 'flavorRedDebug')     // OK
//  compile project(path: ':library', configuration: 'flavorRedRelease')   // OK
//  compile project(path: ':library', configuration: 'flavorGreedDebug')   // OK
//  compile project(path: ':library', configuration: 'flavorGreedRelease') // OK
//  compile project(path: ':library', configuration: 'flavorBlueDebug')    // OK
//  compile project(path: ':library', configuration: 'flavorBlueRelease')  // OK
}
// Cannot resolve symbol Library
import com.sample.library.Library;

defaultPublishConfigpublishNonDefault のどちらも設定しておくのがベストかと思います。

library/build.gradle
apply plugin: 'com.android.library'

android {
    ...

    defaultPublishConfig "flavorRedRelease"
    publishNonDefault true

    buildTypes {
        debug   {...}
        release {...}
    }

    productFlavors {
        flavorRed {}
        flavorGreen {}
        flavorBlue {}
    }
}
app/build.gradle
dependencies {
//  compile project(':library') // OK
    compile project(path: ':library', configuration: 'flavorRedDebug')     // OK
//  compile project(path: ':library', configuration: 'flavorRedRelease')   // OK
//  compile project(path: ':library', configuration: 'flavorGreedDebug')   // OK
//  compile project(path: ':library', configuration: 'flavorGreedRelease') // OK
//  compile project(path: ':library', configuration: 'flavorBlueDebug')    // OK
//  compile project(path: ':library', configuration: 'flavorBlueRelease')  // OK
}

検証用プロジェクト
https://github.com/ShogoMizumoto/SampleFlavorsLibrary