Android Gradleのマルチフレーバーライブラリに基づくマルチフレーバーアプリ


102

私のアプリには、いくつかの市場のアプリ内課金システム向けのフレーバーがいくつかあります。

すべてのプロジェクトの基本コードを共有する単一のライブラリがあります。そこで、これらの支払いシステムを製品のフレーバーとしてこのライブラリーに追加することにしました。

問題は、Androidライブラリに製品のフレーバーを設定できるかどうかです。

もしそうなら、どうすればアプリのそれぞれのフレーバーに異なるフレーバーを含めることができますか?

何度も検索しましたが、このシナリオについては何も見つかりませんでした。私が見つけた唯一の近いものは、http//tools.android.com/tech-docs/new-build-system/user-guideにあるこれです:

dependencies {
    flavor1Compile project(path: ':lib1', configuration: 'flavor1Release')
    flavor2Compile project(path: ':lib1', configuration: 'flavor2Release')
}

構成を別のものに変更しましたが、機能しませんでした!

Android Studio 0.8.2を使用しています。


多くの検索の後、私はこれを達成する方法を見つけられませんでした、私はアンドロイドプラグインを最新3.4.2バージョンにアップグレード、最新にグラドルします、5.5.1それでもコンパイル時に失敗した、またはリソースリンクが aaptで失敗した、またはライブラリ内のシンボル見つけることができませんモジュール
VinceStyling

回答:


141

最後にこれを行う方法を見つけました、同じ問題に直面している他の人のためにここで説明します:

重要な部分は、ライブラリbuild.gradleでpublishNonDefaultをtrueに設定することです。その後、ユーザーガイドで提案されているように依存関係を定義する必要があります。

プロジェクト全体は次のようになります。

ライブラリbuild.gradle:

apply plugin: 'com.android.library'

android {        
    ....
    publishNonDefault true
    productFlavors {
        market1 {}
        market2 {}
    }
}

プロジェクトbuild.gradle:

apply plugin: 'com.android.application'

android {
    ....
    productFlavors {
        market1 {}
        market2 {}
    }
}

dependencies {
    ....
    market1Compile project(path: ':lib', configuration: 'market1Release')
    market2Compile project(path: ':lib', configuration: 'market2Release')
}

これで、アプリフレーバーと[ビルドバリアント]パネルを選択でき、それに応じてライブラリが選択され、選択したフレーバーに基づいてすべてのビルドと実行が行われます。

ライブラリに基づいた複数のアプリモジュールがある場合、Android Studioはバリアントの選択の競合について不平を言うでしょう。問題ありません。無視してください。

ここに画像の説明を入力してください


共有いただきありがとうございます。今、defaultPublishConfigの回避策を取り除くことができます。
デルブランコ2014

2
AS 1.1.0を実行している場合、上記のソリューションはまだ機能しているようですが、1)デバッグ/リリースビルドの選択が失われ、適切なコードの生成に失敗するAIDLの問題がライブラリに見つかり続けます。これについて何か考えはありますか?
3c71、2015年

1
@IgorGanapolsky buildTypesはこれとは何の関係もありません。すべてのフレーバーにはすべてのビルドタイプ(通常はデバッグとリリース)があり、それらはすべてこのアプローチで動作します。
アリ

1
@ An-droidは、market1フレーバーに使用されるライブラリーを定義します!
2016

1
なぜ「リリース」ビルドタイプに設定されているのですか?「リリース」ビルドタイプはデバッグビルド中に選択されますか?
WindRider 2016

35

Aliの回答には1つの問題があります。ビルドバリアントでは1つの非常に重要な側面を失っています。すべてのオプションが必要な場合(私の例では4(2 x 2)の例)、メインモジュールのbuild.gradleファイルにカスタム構成を追加して、ですべてのマルチフレーバーmulti-buildTypeを使用できるようにする必要があります。ライブラリモジュールのbuild.gradleファイルでpublishNonDefaultをtrueに設定する必要もあります。Build Variants

ソリューションの例:

lib build.gradle

android {

    publishNonDefault true

    buildTypes {
        release {
        }
        debug {
        }
    }
    productFlavors {
        free {
        }
        paid {
        }
    }
}

アプリbuild.gradle

android {

    buildTypes {
        debug {
        }
        release {
        }
    }
    productFlavors {
        free {
        }
        paid {
        }
    }
}

configurations {
    freeDebugCompile
    paidDebugCompile
    freeReleaseCompile
    paidReleaseCompile
}

dependencies {

    freeDebugCompile project(path: ':lib', configuration: 'freeDebug')
    paidDebugCompile project(path: ':lib', configuration: 'paidDebug')
    freeReleaseCompile project(path: ':lib', configuration: 'freeRelease')
    paidReleaseCompile project(path: ':lib', configuration: 'paidRelease')

}

私のアプリケーションで同じことを行った後Error:java.lang.RuntimeException: Error: more than one library with package name、発生しました
Chetan Joshi

21

Androidプラグイン3.0.0以降のアップデート

公式のAndroidドキュメント- ローカルモジュールの依存関係構成を移行するによると、

バリアント対応の依存関係の解決により、ローカルモジュールの依存関係にfreeDebugImplementationなどのバリアント固有の構成を使用する必要がなくなりました。プラグインがこれを処理します。

代わりに、次のように依存関係を構成する必要があります。

dependencies {
    // This is the old method and no longer works for local
    // library modules:
    // debugImplementation project(path: ':library', configuration: 'debug')
    // releaseImplementation project(path: ':library', configuration: 'release')

    // Instead, simply use the following to take advantage of
    // variant-aware dependency resolution. You can learn more about
    // the 'implementation' configuration in the section about
    // new dependency configurations.
    implementation project(':library')

    // You can, however, keep using variant-specific configurations when
    // targeting external dependencies. The following line adds 'app-magic'
    // as a dependency to only the "debug" version of your module.

    debugImplementation 'com.example.android:app-magic:12.3'
}

だからアリの答えでは、変更

dependencies {
    ....
    market1Compile project(path: ':lib', configuration: 'market1Release')
    market2Compile project(path: ':lib', configuration: 'market2Release')
}

implementation project(':lib')

また、プラグインはバリアント固有の構成を自動的に処理します。他の人がAn​​droid Studioプラグインを3.0.0以降にアップグレードするのに役立つことを願っています。


7

私のAndroidプラグインは3.4.0ですが、今は設定が不要であることがわかりました。必要なのは、アプリケーション内のflavorDimensionsとproductFlavorsに、同じflavorDimensionsとproductFlavorsの1つのproductFlavorがライブラリに含まれていることを確認することだけです。サンプル:

mylibraryのbuild.gradle

apply plugin: 'com.android.library'

android {        
    ....
    flavorDimensions "mylibFlavor"

    productFlavors {
        market1
        market2
    }
}

アプリケーションのbuild.gradle:

apply plugin: 'com.android.application'

android {
    ....
    flavorDimensions "mylibFlavor", "appFlavor"
    productFlavors {
        market1 {
            dimension "mylibFlavor"
        }
        market2 {
            dimension "mylibFlavor"
        }
        common1 {
            dimension "appFlavor"
        }
        common2 {
            dimension "appFlavor"
        }
    }
}

dependencies {
    ....
    implementation project(path: ':mylibrary')
}

同期後、[バリアントの作成]ウィンドウですべてのオプションを切り替えることができます。 ここに画像の説明を入力してください


しかし、メインのアプリモジュールで同じフレーバーを使用したくない場合はどうなりますか?独自のフレーバーを持つ複数のアプリモジュールと独自のフレーバーを持つ1つの共通モジュールがあり、自分のアプリで特定のフレーバーを持つlibを使用したいとします。どうしますか 私のlibフレーバーをすべてのアプリにコピーすることは意味がありません。
ビルダ

@Billdaすべてをコピーする必要はありません。1つの同じproductFlavorをアプリに保存してください。私のサンプルでは、​​market1またはmarket2をアプリケーションのbuild.gradleに保存できます。
JiajiaGu

2

AARライブラリでフレーバーを機能させるには、Androidライブラリモジュールのbuild.gradleファイルでdefaultPublishConfigを定義する必要があります。

詳細については、「Library Publication」を参照してください。

図書館出版

デフォルトでは、ライブラリはそのリリースバリアントのみを公開します。このバリアントは、どのバリアントが自分でビルドしたかに関係なく、ライブラリを参照するすべてのプロジェクトで使用されます。これは、削除に向けて取り組んでいるGradleの制限による一時的な制限です。公開するバリアントを制御できます。

android {defaultPublishConfig "debug"}

この発行構成名は完全なバリアント名を参照することに注意してください。リリースとデバッグは、フレーバーがない場合にのみ適用できます。フレーバーの使用中にデフォルトの公開バリアントを変更したい場合は、次のように記述します。

android {defaultPublishConfig "flavor1Debug"}


1

現時点では不可能ですが、私が正しく思い出せば、追加したい機能です。(編集2:linklink2

編集:今のところ、defaultPublishConfig公開するライブラリバリアントを宣言するオプションを使用しています:

android {
    defaultPublishConfig fullRelease
    defaultPublishConfig demoRelease 
}

1
それで、アプリをコンパイルするたびに、ライブラリのbuild.gradleでこれを変更する必要がありますか?
Ali 14

ええと、毎回、アプリを別のフレーバーでコンパイルする必要があります。
Delblanco 14

実際にライブラリモジュールのフレーバーを定義すると、継承されたRパッケージがアプリモジュールで見つかりません。
アリ

ASでGradleファイルを同期しましたか?
Delblanco 14

@Delblancoこれは手作業のようで非常に壊れやすいようです(開発者は怠惰で、build.gradleファイルの変更を忘れています)。
IgorGanapolsky 2015

1

私はこの件がクローズされたことを知っていますが、gradle 3.0での更新のみですこれを参照してください:https : //developer.android.com/studio/build/gradle-plugin-3-0-0-migration.html#variant_aware and grep matchingFallbacksmissingDimensionStrategy。モジュールフレーバー間の依存関係を宣言する方が簡単になりました。

...そしてこのgradle3.0の正確なケースでは、フレーバーが同じ名前を共有しているため、gradleは魔法のようにそれらをマッピングします。


私にとっては、ランタイムが生成したものはスキップされているようです。例として、simonvt->回路図生成は、私にとって新しい方法ではもう機能していません。:-/
Stefan Sprenger 2017年

1

また、さまざまなオプションのモジュールのコンパイルで問題が発生しました。

私が見つけたもの:

Gradle 3.0.1以降、publishNonDefault truelibのbuild.gradleファイルに追加する必要がないようです。

クラスを逆コンパイルした後、BaseExtensionこれが見つかりました:

public void setPublishNonDefault(boolean publishNonDefault) {
   this.logger.warn("publishNonDefault is deprecated and has no effect anymore. All variants are now published.");
}

そして代わりに:

dependencies {
...
   Compile project(path: ':lib', configuration: 'config1Debug')
}

以下を使用する必要があります。

dependencies {
...
   implementation project(':lib')
}

重要なことは、にconfigurations {...}パーツを追加することだけbuild.gradleです。

したがって、アプリのbuild.gradleファイルの最後のバリアントは次のとおりです。

buildTypes {
   debug {
      ...
   }

   release {
      ...
   }
}

flavorDimensions "productType", "serverType"
productFlavors {
   Free {
      dimension "productType"
      ...
   }
   Paid {
      dimension "productType"
      ...
   }
   Test {
      dimension "serverType"
      ...
   }
   Prod {
      dimension "serverType"
      ...
   }
}

configurations {
   FreeTestDebug
   FreeTestRelease
   FreeProdDebug
   FreeProdRelease
   PaidTestDebug
   PaidTestRelease
   PaidProdDebug
   PaidProdRelease
}

dependencies {
   implementation fileTree(dir: 'libs', include: ['*.jar'])
   implementation project(':lib')
   ...
}

また、フィルターバリアントを使用して、ビルドバリアントを制限できます。

Psは次のsettings.gradleようにファイルにモジュールを含めることを忘れないでください:

include ':app'
include ':lib'
project(':lib').projectDir = new File('app/libs/lib')

先生、ライブラリーを特定の構成に含めるかどうかをスクリプトがどのように天気を決定するかを説明できますか?特定のフレーバーにいくつかのlibを使用する必要があるが、他のフレーバーにそれを使用する必要がない場合があることを意味します
Jenya Kirmiza

そのような状況に陥らなかった。しかし、Googleチュートリアルのdeveloper.android.com/studio/build/dependenciesでは、「dependencies {...}」ブロックの「implementation」コマンドの前にプレフィックスを追加することをお勧めしています。つまり、依存関係{payedImplementation project( ':lib')}、または依存関係{debugImplementation project( ':lib')}、または複数のバリアントの組み合わせ依存関係{paydProdDebugImplementation project( ':lib')}です。ぜひチェックしてフィードバックをお寄せください:)
Sergio
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.