web-dev-qa-db-ja.com

Android)のライブラリプロジェクトのGradleでバリアントをビルドする

いくつかの外部ライブラリを含むプロジェクトをGradleで構成しようとしています。 Gradleを使用すると、ビルドバリアントを使用してメインアプリケーションのさまざまな環境構成(構成ファイル内のクラスを使用)をセットアップできるため、この変数に従ってコードを実行できます。

問題は、どうすれば図書館プロジェクトで同じことができるのかということです。このプロジェクト用にこのライブラリを作成しました。シナリオごとに異なるビルドバリアントを設定したいと思います。

例:ライブラリで、デバッグモードで実行している場合は、すべてのログを印刷して、開発中にログを確認できるようにします。リリースモードではいけません。

ファイルの構造:

src ----- > debug -> Java -> config -> PlayerEnvConfig
            main -> com.mypackagename -> etc...
            release -> Java -> config -> PlayerEnvConfig

デバッグ中のコード:package config;

/**
 * Environment configuration for Release
*/
public final class PlayerEnvConfig {
    public static final boolean USE_REPORTING = true;
    public static final boolean USE_ANALYTICS = true;
    public static final boolean USE_LOGGING = false;
    public static final boolean USE_DEBUG_LOGGING = false;
    public static final boolean USE_DEBUGING = false;
}

リリース中のコード:

package config;

/**
 * Environment configuration for Release
*/
public final class PlayerEnvConfig {
    public static final boolean USE_REPORTING = true;
    public static final boolean USE_ANALYTICS = true;
    public static final boolean USE_LOGGING = false;
    public static final boolean USE_DEBUG_LOGGING = false;
    public static final boolean USE_DEBUGING = false;
}

問題は、メインプロジェクトでは、このビルドタイプを使用して、シナリオごとにアプリケーションを異なる方法で構成できることですが、ライブラリプロジェクトでも同じことを行うにはどうすればよいですか?

なぜなら、私が読んだものから http://tools.Android.com/tech-docs/new-build-system/user-guide ライブラリは、テスト中にデバッグモードのみを使用するからです。

何か案は?

ありがとう!

22
Javier Tarazaga

それは グーグルコードの問題 からの@bifmadeiの答えであり、それは私にとって役立ちます:

依存関係プロジェクトでこれを設定してみてください

Android {
    publishNonDefault true
    ...
}

そしてこれを使用するプロジェクトでこれ

dependencies {
    releaseCompile project(path: ':theotherproject', configuration: 'release')
    debugCompile project(path: ':theotherproject', configuration: 'debug')
}

ここから取得: https://code.google.com/p/Android/issues/detail?id=66805

14
Beloo

構成の何が問題になっているのかわかりませんが、必要性については、別の方法で行います。

Gradleビルドファイルでは、buildConfigキーワードを使用して、BuildConfig.Javaで生成されたクラスに特定の行を追加できます。

したがって、build.gradleにそのようなことを追加できます:

    release {
        buildConfig "public static final String USE_REPORTING = true;"
    }
    debug {

        buildConfig "public static final String USE_REPORTING = false;"
    }

したがって、PlayerEnvConfigは1つだけです。

public static final boolean USE_REPORTING = BuildConfig.USE_REPORTING;

または、これ以上PlayerEnvConfigを使用せず、BuildConfigクラスを直接使用します。


編集更新以降、構文が変更されました:

buildConfigField "<type>", "<name>", "<value>"
12
tbruyelle

これは https://code.google.com/p/Android/issues/detail?id=52962 に記載されています。ご存知のように、ビルドタイプはライブラリプロジェクトに伝播されず、適切な回避策はありません。ライブラリプロジェクトのコードを制御できる場合は、デバッグステータスを可変グローバル変数にして、起動時にメインアプリケーションから設定できます。これはちょっとしたハックであり、コンパイラがリリースビルドから離れた未使用のコードパスを最適化できないという欠点がありますが、何か異常が発生しない限り、機能するはずです。

4
Scott Barta

更新-この投稿の時点から、gradleビルドプロセスは大幅に進歩しているため、この回答は推奨されるベストプラクティスではない可能性があり、新しい変更によってさらに問題が発生する可能性があります。あなた自身の裁量を使用してください。

プロジェクト全体の構造と構成には少し混乱があると思います。次のbuild.gradle構成があるとしましょう

_sourceSets {

    main {
        manifest.srcFile 'src/main/AndroidManifest.xml'
        Java.srcDirs = ['src/main/Java']
        //resources.srcDirs = ['src/main']
        //aidl.srcDirs = ['src/main']
        //renderscript.srcDirs = ['src/main']
        res.srcDirs = ['src/main/res']
        assets.srcDirs = ['src/main/assets']
    }

    debug.setRoot('build-types/debug')
    release.setRoot('build-types/release')
}
_

プロジェクトのフォルダ構造は次のようになります

_project_root
   -src
      -main
         -Java
            -com
               -example
   -build-types
      -debug
         -Java
            -com
               -example
                  -FooBar.Java
      -release
         -Java
            -com
               -example
                  -FooBar.Java
_

_FooBar.Java_は_prooject_root/src/main/Java/com/example_に含まれていてはなりません。 debugフォルダーの外側であるが_build-types_フォルダー内にあるreleaseおよびsrcフォルダー内にある必要があります。これはsetRoot('build-types/*****')メソッドによって構成されます。多くの人は、「debug/Java」と「main/Java」を見て混乱します。後者は、プレゼンテーションから「src/main/Java」の方法で参照され、最終的に「debug/Java」をsrcに入れます。間違ったフォルダ。これがお役に立てば幸いです。

他のライブラリが関係するより複雑な環境については、ここで私の答えを確認できます https://stackoverflow.com/a/19918834/319058

3
Win Myo Htet

Scott が指摘しているように、これはGradleの既知の欠点です。回避策として、リフレクションを使用してアプリ(ライブラリではなく)からフィールド値を取得するこのメソッドを使用できます。

/**
 * Gets a field from the project's BuildConfig. This is useful when, for example, flavors
 * are used at the project level to set custom fields.
 * @param context       Used to find the correct file
 * @param fieldName     The name of the field-to-access
 * @return              The value of the field, or {@code null} if the field is not found.
 */
public static Object getBuildConfigValue(Context context, String fieldName) {
    try {
        Class<?> clazz = Class.forName(context.getPackageName() + ".BuildConfig");
        Field field = clazz.getField(fieldName);
        return field.get(null);
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
    return null;
}

たとえば、DEBUGフィールドを取得するには、Activityからこれを呼び出します。

boolean debug = (Boolean) getBuildConfigValue(this, "DEBUG");

AOSP Issue Tracker でもこのソリューションを共有しました。

0
Phil

あなた自身が述べたように、これは図書館プロジェクトでは不可能です。

ライブラリプロジェクトをアプリケーションプロジェクトに変更するだけです。それはうまくいくようです(少なくとも理論的には、私はそれを自分でテストしていません)。

もう1つの方法は、アプリケーションプロジェクトでそのクラスをオーバーライドすることです。マージが行われるときにアプリケーションプロジェクトクラスが選択され、それらの値を使用できるようになります。

0
Saad Farooq