注意:Xavierの回答の後に編集された回答
Android Studioの同じアプリケーションプロジェクトに対して異なる Build Flavors を使用しようとしています。しかし、適切に機能するように設定するのにひどい時間がかかっているようです。
手順:
Build.gradle *を開き、次の行を追加しました。
productFlavors {
flavor1 {
packageName 'com.Android.studio.test.flavor1'
}
flavor2 {
packageName 'com.Android.studio.test.flavor2'
}
}
flavor1;の新しいソースフォルダーを作成しました;ただし、正しい方法で実行しているかどうかはわかりません。以下がその方法です。
com.foo.test
src
フォルダーを右クリックして、flavor1の場合、構造がsrc/flavor1/Java/com/foo/test/MainActivity.Java
になるように、実際にエクスプローラーで個々のフォルダーを作成しました。私は何か間違っていますか?それとも何か不足していますか?さらに情報が必要な場合はお知らせください。
*私のプロジェクトにはtwobuild.gradleファイルがあるようです。プロジェクトフォルダー(\ GradleTest)のルートにある1つは空です。\GradleTestのサブフォルダーのルートにある2つ目は、「GradleTest」(GradleTest-GradleTest)というラベルが付けられています。これは、開いたときに既にコードが入っているものです。したがって、それが私が編集したものです。
**私はgradleの設定を確認し、明らかにauto-importを使用は すでに有効になっています にもかかわらず、ビルドに変更を加えます.gradleファイル 自動更新しない ビルドバリアント。 注:また、Build-Rebuild Project、および/またはBuild-Make Project、no-goを使用してみました。プロジェクトを閉じて、変更を有効にするために再度開く必要があります。
Studioの設定で[Gradle]セクションの下にある場合、プロジェクトの自動インポートを有効にできます(これは後でデフォルトで有効になります)。これにより、編集するたびにStudioでbuild.gradleを再インポートできます。
フレーバーを作成しても、カスタムコードを使用するわけではないため、フォルダーは作成しません。自分で作成する必要があります。
my IO talk を見ると、バリアントを作成するためのフレーバーとビルドタイプ。
Javaソースの場合:
src/main/Java
src/flavor1/Java
src/debug/Java
3つすべてが単一の出力の作成に使用されます。これは、同じクラスを定義できないことを意味します。
2つのフレーバーで同じクラスの異なるバージョンを使用する場合は、両方のフレーバーで作成する必要があります。
src/flavor1/Java/com/foo/A.Java
src/flavor2/Java/com/foo/A.Java
そして、src/main/Javaのコードでできること
import com.foo.A
選択したフレーバーに応じて、com.foo.Aの適切なバージョンが使用されます。
これはまた、Aの両方のバージョンが同じAPIを持たなければならないことを意味します(少なくともsrc/main/Java/...のクラスで使用されるAPIに関しては...)。
修正された質問に合わせて編集する
さらに、相互に排他的なソースフォルダーにのみ同じAクラスを配置することが重要です。この場合、src/flavor1/Javaとsrc/flavor2/Javaが一緒に選択されることはありませんが、mainとflavor1は選択されません。
異なるフレーバーで異なるバージョンのアクティビティを提供する場合は、src/main/Javaに配置しないでください。
3つのフレーバーがあり、flavor1のカスタムフレーバーのみが必要で、flavor2とflavor3が同じアクティビティを共有する場合、これら2つの他のアクティビティの共通ソースフォルダーを作成できることに注意してください。新しいソースフォルダーを作成し、それらを使用するようにソースセットを構成する際に、完全な柔軟性があります。
他のポイントへ:
通常、2番目のフレーバーソースフォルダーは青ではありません。 2番目のフレーバーに切り替えて有効にする必要があります。そうすれば、内部でパッケージとクラスを作成できます。それまで、Studioはそれをソースフォルダーと見なしません。 IDEがこれらのunactiveソースフォルダーを認識できるように、将来的にこれを改善することを願っています。
Resフォルダにリソースファイルを作成できないことも普通だと思います。メニューシステムは、これらすべての追加のリソースフォルダーを処理するように更新されていません。これは後で来ます。
Androidの「製品フレーバー」
同じアプリの異なるバージョンに依存して、異なるホスト、アイコン、またはパッケージ名で作業する方法について時々尋ねられました。
これを行う理由はたくさんあり、簡単な方法は製品フレーバーです。
Build.gradleスクリプトで、これまでに説明したこのようなことを定義できます。
製品フレーバーこの記事の一部は、製品フレーバーについて考えて書かれています。 Androidドキュメントに関して:
製品フレーバーは、プロジェクトによってビルドされるアプリケーションのカスタマイズバージョンを定義します。単一のプロジェクトは、生成されるアプリケーションを変更するさまざまなフレーバーを持つことができます。
それらをどのように定義できますか? build.gradleに、定義するフレーバーを記述する必要があります。
productFlavors {
...
devel {
...
}
prod {
...
}
}
これで、アプリの2つの異なるフレーバーができました。 Android Studioの[ビルドバリアントの作成]タブでも確認できます
バリアントの構築
複数のパッケージ名
開発状態のアプリと本番状態のアプリを電話機にインストールしたい場合はどうでしょう。ご存知かもしれませんが、同じパッケージ名のアプリは1つしかインストールできません(お使いの携帯電話にインストールされているものと同じ新しいAPKをインストールしようとすると、更新を試みます)。
あなたがしなければならない唯一のことは、あなたの製品フレーバーのそれぞれでそれを定義することです:
Android {
productFlavors {
devel {
applicationId "zuul.com.Android.devel"
}
prod {
applicationId "zuul.com.Android"
}
}
}
フレーバーに応じて複数のホストにリクエストを送信する前と同様に、製品フレーバーの設定フィールドにいくつかのパラメーターを含める必要があります。
Android {
productFlavors {
devel {
applicationId "zuul.com.Android.devel"
buildConfigField 'String', 'Host', '"http://192.168.1.34:3000"'
}
prod {
applicationId "zuul.com.Android"
buildConfigField 'String', 'Host', '"http://api.zuul.com"'
}
}
}
例として、これをRetrofitと統合して、どのサーバーを指しているか、フレーバーに基づいて処理することなく、適切なサーバーに要求を送信する方法を示します。この場合、これはZuul Androidアプリの抜粋です:
public class RetrofitModule {
public ZuulService getRestAdapter() {
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(BuildConfig.Host)
.setLogLevel(RestAdapter.LogLevel.FULL)
.build();
return restAdapter.create(ZuulService.class);
}
}
ご覧のように、BuildConfigclassを使用して、定義した変数にアクセスするだけです。
コードを介して利用可能な変数ホスト変数は、コードで公開できる唯一の変数ではありません。あなたはあなたが望むものでそれを行うことができます:
prod {
applicationId "zuul.com.Android"
buildConfigField 'String', 'Host', '"http://api.zuul.com"'
buildConfigField 'String', 'FLAVOR', '"prod"'
buildConfigField "boolean", "REPORT_CRASHES", "true"
}
次のようにアクセスできます。
BuildConfig.Host
BuildConfig.FLAVOR
BuildConfig.REPORT_CRASHES
フレーバーごとに異なるアイコンフレーバーごとに異なるアイコンが必要な場合は、開いているアイコンを視覚的に検出できます(名前でもできますが、スペースに収まりません!)。フレーバーごとに新しいディレクトリ構造を定義します。
先ほど使用した例では、develとprodの2つのフレーバーがあります。次に、2つの新しいディレクトリ構造を定義して、必要なリソースを定義できます。
構造
これは、strings.xml, integers.xml, arrays.xml
などの他のタイプのリソースで機能します。
署名設定を構成する
Gradleビルド構成を使用して、リリースビルドタイプの署名構成を手動で構成するには:
1.キーストアを作成します。キーストアは、プライベートキーのセットを含むバイナリファイルです。キーストアは安全で安全な場所に保管する必要があります。 2.秘密鍵を作成します。秘密鍵は、個人や会社など、アプリで識別されるエンティティを表します。 3.モジュールレベルのbuild.gradleファイルに署名構成を追加します。
Android {
...
defaultConfig {...}
signingConfigs {
release {
storeFile file("myreleasekey.keystore")
storePassword "password"
keyAlias "MyReleaseKey"
keyPassword "password"
}
}
buildTypes {
release {
...
signingConfig signingConfigs.release
}
}
}
署名付きAPKを生成:
署名済みAPKを生成するには、メインメニューから[ビルド]> [署名付きAPKの生成]を選択します。 app/build/apk/app-release.apkのパッケージは、リリースキーで署名されました。
build.gradle
に新しいフレーバーを追加した後、プロジェクトをリロードする必要があるようです。その後、Build Variantsビューに4つのビルドVariantが表示されます(ウィンドウの左端からアクセスできます)。
追加のソースディレクトリに関しては、手動で作成する必要があるようです:src/flavor1/Java
およびsrc/flavor2/Java
。 [ビルドバリアント]ビューでフレーバーを変更すると、現在アクティブなソースディレクトリが変更されることがわかります(アクティブソースの場合、ディレクトリは青色です)ディレクトリ)
最後に、「gradleは新しいフレーバーの新しいsourceSetsを作成します」とは、gradleがオブジェクトAndroid.sourceSets.flavor1
およびAndroid.sourceSets.flavor2
を作成し、build.gradleスクリプトで使用できることを意味します。しかし、これらのオブジェクトは動的に作成されるため、build.gradle
に表示されません(これを読むことをお勧めします: http://www.gradle.org/docs/current/userguide/tutorial_using_tasks.html =特に6.6:動的なタスクの作成を説明します。gradleスクリプトはgroovyスクリプトなので、groovyにも精通することをお勧めします)
プロジェクトをGradleに移行したときにも同じ問題が発生しました。問題は、ビルドが適切なリソースフォルダーを見つけられなかったことです。 build.gradleのAndroid要素の下にこれを追加して修正しました。
sourceSets {
main {
res.srcDirs = ['myProject/res']
}
}
重要であり、かなり長い間私を妨げていたのは、gradleのフレーバー定義内で定義されたパッケージではなく、パッケージと一致する必要があるフレーバー名です。例えば:
src/flavor1/Java/com/foo/A.Java
一致します
productFlavors {
flavor1 {
packageName 'com.Android.studio.test.foobar'
}
}
しかし
src/foobar/Java/com/foo/A.Java
は、flavor1ビルドには使用されません。
gradle:
ビルドタイプの場合、必要なのは以下のみです。
buildTypes {
release{
//proguard, signing etc.
}
debug {
//development
}
}
}
そして、フレーバーには必要なものを追加します
productFlavors {
pro {
applicationIdSuffix '.paid'
buildConfigField 'boolean', 'PRO', 'true'
}
free {
applicationIdSuffix '.free'
buildConfigField 'boolean', 'PRO', 'false'
}
}