簡體   English   中英

在Gradle中為Android中的庫項目構建變體

[英]Build variants in Gradle for a Library Project in Android

我正在嘗試使用Gradle配置一個包含一些外部庫的項目。 使用Gradle我可以使用Build Variants為主應用程序設置不同的環境配置(在配置文件中有一個類),這樣我就可以根據這些變量執行代碼。

問題是我如何為圖書館項目做同樣的事情? 我為這個項目創建了這個庫,我想為不同的場景設置不同的Build Variants。

例如:在庫中,當在調試模式下運行時,然后打印所有日志,以便我可以在開發時看到它們。 在發布模式下不要。

文件結構:

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

debug中的代碼: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;
}

問題是,對於主項目,我可以使用此Build類型為不同場景配置不同的應用程序,但我如何為庫項目執行相同操作?

因為目前我在http://tools.android.com/tech-docs/new-build-system/user-guide中讀到的內容,庫只會在測試時使用調試模式。

有任何想法嗎?

謝謝!

這是來自谷歌代碼問題的@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

不確定您的配置有什么問題,但有關您的需求,我會采用不同的方式。

在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

public static final boolean USE_REPORTING = BuildConfig.USE_REPORTING;

甚至沒有更多的PlayerEnvConfig並直接使用BuildConfig類。


編輯自更新以來,語法已更改:

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

這在https://code.google.com/p/android/issues/detail?id=52962中有記錄。 正如您所知,構建類型不會傳播到庫項目,並且沒有一個好的解決方法。 如果您可以控制庫項目的代碼,則可以將調試狀態設置為可變全局變量,並在啟動時從主應用程序設置它。 這有點像黑客,它的缺點是編譯器無法優化未使用的代碼路徑遠離發布版本,但除非發生異常,否則它應該有效。

更新 - 自發布之日起,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 它必須位於debugrelease文件夾中,該文件夾位於src文件夾之外但位於build-types文件夾中。 這是由setRoot('build-types/*****')方法配置的。 很多人因為看到'debug / java'和'main / java'而感到困惑,后者在演示中以'src / main / java'的方式引用,最后在src中放入'debug / java',錯文件夾。 我希望這有幫助。

對於涉及其他庫的更復雜的環境,您可以在這里查看我的答案https://stackoverflow.com/a/19918834/319058

對於您自己提到的庫項目,這是不可能的。

您可以將庫項目更改為應用程序項目。 這似乎工作正常(至少在理論上,我自己沒有測試過)。

另一種方法是在應用程序項目中覆蓋該類。 合並發生時將選擇您的應用程序項目類,並且您將獲得這些值。

斯科特指出,這是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問題跟蹤器上分享了這個解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM