Построить варианты в 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, библиотека будет использовать режим отладки во время тестирования.
Любые идеи?
Спасибо!
Ответы
Ответ 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.