BuildConfig.DEBUG заўсёды фальшыва пры стварэнні праектаў бібліятэкі з Gradle

BuildConfig.DEBUG не працуе (= лагічна усталёўваецца ў хлусня), калі я бягу маё прыкладанне ў рэжыме выпраўленьня. Я выкарыстоўваю Gradle для build.I ёсць праект бібліятэкі, дзе я раблю гэтую праверку. 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:

Пытанне rel = "noreferrer"> толькі што быў адзначаны як фіксаваны для Android Studio Gradle версіі 3.0. Там вы можаце проста выкарыстоўваць праект ўкаранення (шлях: «: бібліятэка») , і ён будзе аўтаматычна выбіраць правільную канфігурацыю.

85
дададзена
Нам трэба дадаць «App" частка для кожнай бібліятэкі мы выкарыстоўваем? Калі так, то гэта вельмі раздражняе ...
дададзена аўтар android developer, крыніца
Дзякуй, гэта зрабіў сваю працу!
дададзена аўтар Aykut Çevik, крыніца
Нічога сабе, яны, нарэшце, абнаўляецца, што старонка <�я> трохі </я> і яны нарэшце-то дадалі гэтую функцыю.
дададзена аўтар Jared Burrows, крыніца
Такім чынам працуе. Але ёсць недахоп: «: бібліятэка: assembleRelease» завецца нават праз вы робіце «: дадатак: assembleDebug», і гэта прывядзе да больш працяглага часу будынка.
дададзена аўтар Alan Zhiliang Feng, крыніца
Чыстае рашэнне і выдатна працуе.
дададзена аўтар FMontano, крыніца
@Konica Longer Gradle пабудаваць час гэта невялікая цана, каб заплаціць - гэта заблытаныя і доўгія часы ў любым выпадку !! Гэта працавала цудоўна! Добра зроблена!
дададзена аўтар Radu, крыніца
Nice рашэнне, але калі націснуць «анулюе і перазапусціць» на Android Studio гэта паказвае мне памылку: Памылка: модуль «: бібліятэка» мае варыянт «рэліз» абраны, але модуль «»: дадатак «» залежыць ад варыянту «адладкі» ,
дададзена аўтар anber, крыніца
Гэта павінна быць адзначаны правільным адказ;) чараўніцтва тут адбываецца хех дзякуй
дададзена аўтар Santi Iglesias, крыніца
Выдатнае рашэнне, павінна быць прынята рашэнне.
дададзена аўтар natanavra, крыніца

Гэта чаканае паводзіны для гэтага.

Бібліятэчныя праекты толькі публікуюць свае варыянты вызвалення для спажывання іншых праектаў або модулямі.

Мы працуем на фіксуючы гэта, але гэта не з'яўляецца трывіяльнай і патрабуе значнага аб'ёму працы.

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

50
дададзена
Што тут чакаць? Гэта адбываецца для бібліятэк, якія знаходзяцца ў межах самога праекту, дык чаму яна не можа быць ўстаноўлена дакладна, калі я запускаю ўвесь праект у рэжыме выпраўленьня ...
дададзена аўтар android developer, крыніца
Гэта не больш не так. Існуе правільнае рашэнне для гэтага. См мой адказ для атрымання дадатковай інфармацыі.
дададзена аўтар Niklas, крыніца
@XavierDucrohet Гэта з'яўляецца нечаканым і контр інтуітыўным паводзінамі. Вы пэўна павінны паспрабаваць, каб выправіць гэта, калі вы можаце.
дададзена аўтар Radu, крыніца
Гэта праўда, але гэта павінна быць зроблена ўручную, і не вельмі добра маштабуецца з водарамі. Мы хочам зрабіць гэта больш аўтаматызаваным ў будучыні.
дададзена аўтар Xavier Ducrohet, крыніца
Рашэнне, прапанаванае DodoEnte ў выпуску трэкеры не працуе нармальна, няма неабходнасці для працы вакол.
дададзена аўтар 3c71, крыніца
Абыходны шлях: instaed з BuildConfig.DEBUG стварыць яшчэ адну лагічную зменную ў, напрыклад, Lib-праекта BuildConfig.RELEASE і звязаць яго з buildType прыкладання. Падрабязнасці: gist.github.com/almozavr/d59e770d2a6386061fcb
дададзена аўтар Aleksey Malevaniy, крыніца

Праверце імпарту , часам <�моцны> BuildConfig імпартуецца з любога класа бібліятэкі ненаўмысна. Напрыклад:

import io.fabric.sdk.android.BuildConfig;

У гэтым выпадку <�моцны> BuildConfig.DEBUG заўсёды будзе вяртаць <�моцны> хлусня ;

import com.yourpackagename.BuildConfig;

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

37
дададзена
Гэта быў выпадак са мной.
дададзена аўтар Subin Sebastian, крыніца
Жыццё застаўка, дзякуючы ...
дададзена аўтар Arif Nadeem, крыніца
@SubinSebastian мяне таксама.
дададзена аўтар 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 з любога іншага патоку, чым нітка актыўнасці (UI патоку). Халодны раствор, хоць.
дададзена аўтар 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 Issue Tracker .

6
дададзена
@shkschneider якой лініі? Вы можаце пакінуць выключэнне?
дададзена аўтар Phil, крыніца
Можа быць карысным для іншых: сцеражыцеся выкарыстання applicationIdSuffix у Gradle, які б зрабіць .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 вобласць прымянення)

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/адладжваць /.../ 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
дададзена
Ці ёсць «...» для PACKAGENAME бібліятэкі? Калі гэта так, гэта не падобна на працу. Я не магу атрымаць доступ да класа.
дададзена аўтар 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 мой Дадатак модуль.

0
дададзена

Вы можаце паспрабаваць гэта на кожным з buildTypes праектаў:

parent.allprojects.each{ project -> android.defaultConfig.debuggable = true}
0
дададзена
Ці можаце вы растлумачыць? Дадайце яго ў «адладцы» толькі buildType? І да кожнага з модуляў? Гэта дае мне памылку: Памылка: (31, 0) Няма такога ўласцівасці: адладкавыя для класа: com.android.build.gradle.internal.dsl.ProductFlavor_Decorate & ZWNJ; d
дададзена аўтар android developer, крыніца
Ці можаце вы праверыць яго і абнавіць адказ? Калі ёсць просты абыходны шлях, я хацеў бы ведаць пра гэта.
дададзена аўтар android developer, крыніца
У спецыфікацыі андроіда Gradle убудова не змянілася, дык гэта ўжо не дзейнічае. Сцяг адладцы быў перамешчаны ў buildType , а не зборкі канфігурацыі. Я тэорыя ўстаноўкі подпісы адладкі павінен рабіць той жа трук
дададзена аўтар pablisco, крыніца

Гэта мой абыходны шлях: адлюстроўваюць BuildConfig модуля прыкладання:

`Публічны статычны лагічны адладжваць = 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
дададзена