Подтвердить что ты не робот

Построить варианты в Gradle для проекта библиотеки на Android

Я пытаюсь настроить с помощью Gradle проекта, который содержит некоторые внешние библиотеки. С помощью Gradle я могу настроить другую конфигурацию среды (с классом внутри файла конфигурации) для основного приложения с использованием вариантов сборки, чтобы я мог выполнять код в соответствии с этими переменными.

Проблема в том, как я могу сделать то же самое для проекта библиотеки? Я создал эту библиотеку для этого проекта, и я хотел бы настроить различные варианты сборки для разных сценариев.

В качестве примера: В библиотеке при запуске в режиме отладки распечатайте все журналы, чтобы я мог их видеть при разработке. В режиме выпуска нет.

Структура файлов:

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

Код в отладке: пакет конфигурации;

/**
 * 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, библиотека будет использовать режим отладки во время тестирования.

Любые идеи?

Спасибо!

4b9b3361

Ответ 1

Это ответ @bifmadei из проблема с кодом google, и это помогает мне:

Попробуйте установить это в проекте зависимостей

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

Ответ 2

Не уверен, что не так с вашей конфигурацией, но с вашей потребностью, я бы сделал это по-другому.

В файле сборки 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.


EDIT С момента обновления синтаксис изменился:

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

Ответ 3

Это описано в https://code.google.com/p/android/issues/detail?id=52962. Как вы узнали, тип сборки не распространяется на проекты библиотеки, и нет хорошего способа обхода. Если у вас есть контроль над кодом проекта библиотеки, вы можете сделать статус отладки изменчивой глобальной переменной и установить ее из основного приложения при запуске. Это немного хак, и у него есть тот недостаток, что компилятор не может оптимизировать неиспользуемые коды кода вдали от релизов, но если ничего необычного не происходит, он должен работать.

Ответ 4

UPDATE - со времени этой публикации в процессе сборки 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 и release, которая должна находиться вне папки src, но внутри папки build-types. Это настраивается с помощью метода setRoot('build-types/*****'). Многие люди путаются от просмотра "debug/java" и "main/java", где более поздняя ссылка указывается в форме "src/main/java" из презентации и в конечном итоге помещает "debug/java" в src, неправильная папка. Я надеюсь, что эта помощь.

Для более сложной среды, связанной с другими библиотеками, вы можете проверить мой ответ здесь fooobar.com/questions/201925/...

Ответ 5

Это невозможно в библиотечных проектах, как вы сами упоминали.

Вы можете просто сменить проект библиотеки на проект приложения. Кажется, что он работает нормально (по крайней мере, теоретически, я сам его не тестировал).

Другой способ - переопределить этот класс в вашем проекте приложения. Класс вашего прикладного проекта будет выбран при слиянии, и вы получите эти значения.

Ответ 6

Как Скотт указывает, что это известный недостаток Gradle. В качестве обходного пути вы можете использовать этот метод, который использует отражение для получения значения поля из приложения (а не библиотеки):

/**
 * Gets a field from the project 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.