BuildConfig.DEBUG завжди є помилковим при побудові бібліотечних проектів з посиленням

BuildConfig.DEBUG не працює (= логічно встановлено як false), коли я запускаю свою програму в режимі налагодження. Я використовую gradle для побудови. У мене є проект бібліотеки, де я роблю цю перевірку. BuildConfig.java виглядає так в папці налагодження збирання:

/** Automatically generated file. DO NOT MODIFY */
package common.myProject;

public final class BuildConfig {
    public static final boolean DEBUG = Boolean.parseBoolean("true");

}

і в папці звільнення:

public static final boolean DEBUG = false;

як в бібліотечному проекті, так і в проекті додатків.

Я спробував обійти це, перевіривши змінну, яка встановила клас мого проекту. Цей клас наслідує бібліотеку та починає роботу з запуску.

Це призвело до ще однієї проблеми: це використання моєї змінної DEBUG в DataBaseProvider, що запускається перед класом програми.

76
Це нормальна поведінка. Де це питання? Вам потрібно переключитися між BuildVariants
додано Автор Gabriele Mariotti, джерело
Файл BuildConfig створюється правильно, але під час виконання він невірний. У мене така ж проблема.
додано Автор jophde, джерело

12 Відповіді

У програмі Android Studio 1.1, що також має версію gradle на рівні 1.1, можливо:

Бібліотека

android {
    publishNonDefault true
}

Програма

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

Complete documentation can be found here http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Library-Publication

EDIT:

випуск нещодавно позначений як фіксований для Android Studio Gradle Version 3.0. Тут ви можете просто використовувати проект implementation (шлях: ': бібліотека') , і він автоматично вибере правильну конфігурацію.

85
додано
Нам потрібно додати розділ "Програма" для кожної бібліотеки, яку ми використовуємо? Якщо це так, то це дуже дратує ...
додано Автор android developer, джерело
Спасибі, це зробило роботу!
додано Автор Aykut Çevik, джерело
Вау, вони нарешті оновили цю сторінку трошки , і вони, нарешті, додали цю функцію.
додано Автор Jared Burrows, джерело
Цей шлях працює. Але є недолік: ": бібліотека: assembleRelease" викликається навіть через вас, створюючи ": app: assembledebug", і це призведе до більш тривалого часу будівництва.
додано Автор Alan Zhiliang Feng, джерело
Чисте рішення і чудово працює.
додано Автор FMontano, джерело
@Konica Longer Gradle build time - це невелика ціна, яку потрібно заплатити - це все ж таки звите і довгі час! Це чудово працювало! Добре зроблено!
додано Автор Radu, джерело
Хороший розв'язок, але якщо я натискаю "invalidate and restart" в Android Studio, це показує мені помилку: Помилка: Модуль ': бібліотека' має вибраний варіант 'release', але модуль '': app '' залежить від варіанта 'debug' .
додано Автор anber, джерело
Це повинна бути виражена правильна відповідь;) магія тут трапляється, спасибі
додано Автор Santi Iglesias, джерело
Відмінне рішення, повинно бути прийнятною відповіддю.
додано Автор natanavra, джерело

Це очікувана поведінка для цього.

Бібліотечні проекти публікують лише свої варіанти випуску для споживання іншими проектами або модулями.

Ми працюємо над усуненням цього, але це не є тривіальним і вимагає значної кількості робіт.

You can track the issue at https://code.google.com/p/android/issues/detail?id=52962

50
додано
Що тут очікується? Це трапляється для бібліотек, які знаходяться в межах самого проекту, так чому не можна встановити значення "true", коли я запускаю весь проект у режимі налагодження ...
додано Автор android developer, джерело
Це вже не справа. Існує правильне рішення для цього. Для отримання додаткової інформації див мою відповідь .
додано Автор Niklas, джерело
@XavierDucrohet Це неочікувана і протилежна інтуїтивно зрозуміла поведінка. Ви повинні напевно спробувати виправити це, якщо зможете.
додано Автор Radu, джерело
Це так, але це потрібно робити вручну, і не дуже добре оцінювати смакові якості. Ми хочемо зробити це більш автоматичним у майбутньому.
додано Автор Xavier Ducrohet, джерело
Рішення, надане DodoEnte у питаннях відстеження працює просто чудово, немає необхідності в роботі.
додано Автор 3c71, джерело
Обхідний шлях: instaed з BuildConfig.DEBUG створити іншу логічну змінну в lib-проекті, наприклад BuildConfig.RELEASE і зв'язати його з buildType програми. Подробиці: gist.github.com/almozavr/d59e770d2a6386061fcb
додано Автор Aleksey Malevaniy, джерело

Перевірте наявність import , іноді BuildConfig імпортується з будь-якого класу бібліотеки ненавмисно. Наприклад:

import io.fabric.sdk.android.BuildConfig;

У цьому випадку BuildConfig.DEBUG завжди повернеться false ;

import com.yourpackagename.BuildConfig;

In this case BuildConfig.DEBUG will return your real build variant.

37
додано
Це було зі мною.
додано Автор Subin Sebastian, джерело
Спаситель життя, дякую ...
додано Автор Arif Nadeem, джерело
@ СубінСебастіан мені теж.
додано Автор user1510006, джерело

Це подібно до відповіді Філа, хіба це не потребує контексту:

private static Boolean sDebug;

/**
 * Is {@link BuildConfig#DEBUG} still broken for library projects? If so, use this.

* * See: https://code.google.com/p/android/issues/detail?id=52962

* * @return {@code true} if this is a debug build, {@code false} if it is a production build. */ public static boolean isDebugBuild() { if (sDebug == null) { try { final Class<?> activityThread = Class.forName("android.app.ActivityThread"); final Method currentPackage = activityThread.getMethod("currentPackageName"); final String packageName = (String) currentPackage.invoke(null, (Object[]) null); final Class<?> buildConfig = Class.forName(packageName + ".BuildConfig"); final Field DEBUG = buildConfig.getField("DEBUG"); DEBUG.setAccessible(true); sDebug = DEBUG.getBoolean(null); } catch (final Throwable t) { final String message = t.getMessage(); if (message != null && message.contains("BuildConfig")) { //Proguard obfuscated build. Most likely a production build. sDebug = false; } else { sDebug = BuildConfig.DEBUG; } } } return sDebug; }
7
додано
@Rolf ツ Ну, ви можете скористатися контекстом програми.
додано Автор android developer, джерело
Відповідно до цього ( blog.javia.org/static-the-android-application -package ), ви ніколи не повинні викликати метод currentPackageName з будь-якої теми, відмінної від потоку активності (потоку інтерфейсу користувача). Холодний розчин, хоча.
додано Автор Rolf ツ, джерело

Як обхідний шлях, ви можете використовувати цей метод, який використовує відображення, щоб отримати значення поля з програми (а не бібліотеки):

/**
 * 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 , просто зателефонуйте це з вашого Дія :

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

Я також поділився цим рішенням у відстежуванні помилок AOSP .

6
додано
@shkschneider яка лінія? Чи можете ви опублікувати своє виключення?
додано Автор Phil, джерело
Може бути корисним для інших: остерігайтесь використання applicationIdSuffix у градуючому, що зробить клас .BuildConfig недоступним з цього вищезазначеного коду.
додано Автор shkschneider, джерело
Цей обхід дає мені StackOverflowError ...
додано Автор shkschneider, джерело

Насправді не правильний спосіб перевірити, чи є ви в налагодженому ароматі, але ви можете перевірити, чи сам додаток неможливо відновити через:

private static Boolean sIsDebuggable;

public static boolean isDebuggable(Context context) {
    if (sIsDebuggable == null)
        sIsDebuggable = (context.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
    return sIsDebuggable;
}

Стандартна поведінка додатків та бібліотек ідеально відповідатиме її.

Якщо вам потрібно краще вирішити проблему, ви можете використовувати це замість:

public static boolean isInDebugFlavour(Context context) {
    if (sDebugFlavour == null) {
        try {
            final String packageName = context.getPackageName();
            final Class<?> buildConfig = Class.forName(packageName + ".BuildConfig");
            final Field DEBUG = buildConfig.getField("DEBUG");
            DEBUG.setAccessible(true);
            sDebugFlavour = DEBUG.getBoolean(null);
        } catch (final Throwable t) {
            sDebugFlavour = false;
        }
    }
    return sDebugFlavour;
}
3
додано

Ось ще одне рішення.

1) Створіть інтерфейс

public interface BuildVariantDetector {

    boolean isDebugVariant();

}

2) Використовуйте цей інтерфейс у класі Application (Appplication module)

public class MyApplication extends Application implements BuildVariantDetector {

    @Override
    public boolean isDebugVariant() {
        return BuildConfig.DEBUG; //application (main module) Buildonfig
    }

}

3) А потім в бібліотечному модулі:

boolean debugVariant = ((BuildVariantDetector)getApplication()).isDebugVariant();
2
додано
Просте та елегантне рішення. Просто переконайтеся, що ви імпортуєте BuildConfig модуля додатка, а не бібліотеку. Це дуже прихована помилка.
додано Автор WindRider, джерело
Це не працює. BuildConfig.DEBUG все ще є помилковим для мене.
додано Автор DiscDev, джерело

Ви можете створити власний клас BuildConfig для кожного типу збірки за допомогою gradle

public class MyBuildConfig
{
    public static final boolean DEBUG = true;
}

для /src/debug /.../ MyBuildConfig.java та ...

public class MyBuildConfig
{
    public static final boolean DEBUG = false;
}

for /src/release/.../MyBuildConfig.java

Тоді використовуйте:

if (MyBuildConfig.DEBUG)
    Log.d(TAG, "Hey! This is debug version!");
2
додано
Чи "..." для пакетаназва бібліотеки? Якщо так, то це, здається, не працює. Я не можу отримати доступ до класу.
додано Автор android developer, джерело

У нас була та сама проблема. Я придумав щось на зразок цього:

У нас є SDK (бібліотека) і демонстраційний проект, ієрархія виглядає так:

Parent
  |
  + SDK (:SDK)
  |
  + DemoApp (:DemoApp)

Для демонстраційного додатку ми маємо : SDK: jarjarDebug і : SDK: jarjarRelease - деякі конкретні завдання для : SDK , які створюють деякі пост- перероблені банки:

dependencies {
    debugCompile tasks.getByPath(":SDK:jarjarDebug").outputs.files
    releaseCompile tasks.getByPath(":SDK:jarjarRelease").outputs.files
    ... more dependencies ...
}

Це працює навіть для кількох buildTypes , створених одночасно. Налагодження трохи складно, хоча. Будь ласка, коментар

1
додано

У моєму випадку я імпортував неправильний код BuildConfig , оскільки мій проект має багато бібліотечних модулів. Виправлено, щоб імпортувати правильний код BuildConfig для мого модуля app .

0
додано

Ви можете спробувати це на кожному з проектів buildTypes:

parent.allprojects.each{ project -> android.defaultConfig.debuggable = true}
0
додано
Чи можете ви, будь ласка, пояснити? Додайте його до "debug" тільки типу buildType? І до кожного з модулів? Це дає мені помилку: Помилка: (31, 0) Немає такої властивості: debuggable для класу: com.android.build.gradle.internal.dsl.ProductFlavor_Decorate & zwnj; d
додано Автор android developer, джерело
Чи можете ви, будь ласка, перевірити це та оновити відповідь? Якщо є легкий обхід, я б хотів дізнатися про це.
додано Автор android developer, джерело
Специфікації плагіна gradroid gradable змінилися, тому це більше недійсне. Флаг debuggable був перенесений до buildType , а не до конфігурації збирання. Теорія, що встановлює підпис під час налагодження, повинна виконувати той же трюк
додано Автор pablisco, джерело

Це мій шлях: відображати BuildConfig модуля додатків:

`public static boolean debug = isDebug ();

private static boolean isDebug() {
    boolean result = false;
    try {
        Class c = Class.forName("com.example.app.BuildConfig");
        Field f = c.getField("DEBUG");
        f.setAccessible(true);
        result = f.getBoolean(c);
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
    return result;
}`
0
додано
android_jobs_ua
android_jobs_ua
120 учасників

Публикуем вакансии и запросы на поиск работы по направлению Android. Здесь всё: full-time, part-time, remote и разовые подработки.

Mobile Dev Jobs UA
Mobile Dev Jobs UA
20 учасників

Публикуем вакансии и запросы на поиск работы по направлению iOS, Android, Xamarin, RN и т.д.