BuildConfig.DEBUG este întotdeauna fals când se creează proiecte de bibliotecă cu grală

BuildConfig.DEBUG nu funcționează (= logic setat la false) când rulez aplicația în modul de depanare. Eu folosesc gral pentru a construi.Am un proiect de bibliotecă în cazul în care fac acest control. BuildConfig.java arată astfel în folderul de depanare:

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

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

}

și în dosarul de lansare:

public static final boolean DEBUG = false;

atât în ​​proiectul de bibliotecă, cât și în proiectul de aplicare.

Am incercat sa fac acest lucru verificand o variabila care este setata intr-o clasa a proiectului meu. Această clasă moștenește din bibliotecă și începe la pornire.

Acest lucru a condus la o altă problemă: este folosirea variabilei mele DEBUG într-un DataBaseProvider care rulează înainte de clasa de aplicație.

76
Este un comportament normal. Unde este problema? Trebuie să comutați între BuildVariants
adăugat autor Gabriele Mariotti, sursa
Fișierul BuildConfig este generat corect, dar la momentul executării este fals. Am aceeași problemă.
adăugat autor jophde, sursa

12 răspunsuri

Cu Android Studio 1.1 și având de asemenea versiunea de gradare la 1.1 este posibilă:

Library

android {
    publishNonDefault true
}

App

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:

problema tocmai a fost marcată ca fixă ​​pentru Android Studio Gradle Version 3.0. Acolo puteți folosi doar proiectul implementation (path: ': library') și va selecta automat configurația corectă.

85
adăugat
Trebuie să adăugăm partea "App" pentru fiecare bibliotecă pe care o folosim? Dacă da, asta e destul de enervant ...
adăugat autor android developer, sursa
Mulțumesc, asta a făcut treaba!
adăugat autor Aykut Çevik, sursa
În cele din urmă, au actualizat pagina puțin și au adăugat în final această caracteristică.
adăugat autor Jared Burrows, sursa
În felul acesta funcționează. Dar există un dezavantaj: ": library: assembleRelease" se numește chiar prin faptul că faceți ": app: assembleDebug", iar acest lucru va duce la un timp de construcție mai lung.
adăugat autor Alan Zhiliang Feng, sursa
Soluție curată și funcționează excelent.
adăugat autor FMontano, sursa
@Konica Longer Gradul de construire a timpului este un preț mic pe care îl plătiți - este oricum convoluționat și de lungă durată! Acest lucru a funcționat minunat! Foarte bine!
adăugat autor Radu, sursa
Soluție plăcută, dar dacă apăs butonul "invalidate and restart" în Android Studio, îmi arată o eroare: Eroare: Modulul "bibliotecă" are selectat versiunea "release", dar modulul "app:" depinde de varianta " .
adăugat autor anber, sursa
Acesta ar trebui să fie răspunsul corect marcat;) magia se întâmplă aici, mulțumită
adăugat autor Santi Iglesias, sursa
O soluție excelentă ar trebui să fie răspunsul acceptat.
adăugat autor natanavra, sursa

Acesta este un comportament așteptat pentru acest lucru.

Proiectele de bibliotecă publică doar variantele de eliberare pentru consum prin alte proiecte sau module.

Lucrăm la rezolvarea acestei situații, dar acest lucru nu este banal și necesită o cantitate importantă de muncă.

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

50
adăugat
Ce s-a așteptat aici? Se întâmplă pentru bibliotecile care se află în cadrul proiectului în sine, deci de ce nu poate fi setat la adevărat când execut întregul proiect în modul de depanare ...
adăugat autor android developer, sursa
Nu mai este cazul. Există o soluție adecvată pentru asta. Consultați răspunsul meu pentru mai multe informații.
adăugat autor Niklas, sursa
@XavierDucrohet Acesta este un comportament neașteptat și contra intuitiv. Ar trebui să încercați cu siguranță să remediați dacă puteți.
adăugat autor Radu, sursa
E adevărat, dar trebuie făcut manual și nu scade foarte bine cu arome. Vrem să facem acest lucru mai automat în viitor.
adăugat autor Xavier Ducrohet, sursa
Soluția oferită de DodoEnte în tracker-ul de lucrări funcționează foarte bine, fără a fi nevoie de o muncă în jur.
adăugat autor 3c71, sursa
Soluție: instaed de BuildConfig.DEBUG a crea o altă variabilă booleană la lib-projects, de ex. BuildConfig.RELEASE și conectați-l cu buildType al aplicației. Detalii: gist.github.com/almozavr/d59e770d2a6386061fcb
adăugat autor Aleksey Malevaniy, sursa

Verificați pentru imports , uneori BuildConfig este importat din orice clasă de bibliotecă neintenționat. De exemplu:

import io.fabric.sdk.android.BuildConfig;

În acest caz, BuildConfig.DEBUG va întoarce întotdeauna false ;

import com.yourpackagename.BuildConfig;

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

37
adăugat
Acesta a fost cazul cu mine.
adăugat autor Subin Sebastian, sursa
Protector de viață, mulțumesc ...
adăugat autor Arif Nadeem, sursa
@SubinSebastian și eu.
adăugat autor user1510006, sursa

Aceasta este ca răspunsul lui Phil, cu excepția faptului că nu are nevoie de context:

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
adăugat
@Rolf ツ Ei bine, ați putea folosi în schimb contextul aplicației.
adăugat autor android developer, sursa
Potrivit acestui document ( blog.javia.org/static-the-android-application -pachetul ) Postarea pe blog nu trebuie să apelați metoda curentăPackageName din orice alt fir decât firul de activitate (firul UI). Soluție rece, totuși.
adăugat autor Rolf ツ, sursa

Ca soluție, puteți utiliza această metodă, care utilizează reflecția pentru a obține valoarea câmpului din aplicație (nu din bibliotecă):

/**
 * 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;
}

Pentru a obține câmpul DEBUG , de exemplu, sunați doar din Activity :

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

De asemenea, am împărtășit această soluție pe Trackerul de emisiuni AOSP .

6
adăugat
@shkschneider ce linie? Poți să postezi excepția ta?
adăugat autor Phil, sursa
Poate fi util altora: feriți-vă de utilizarea applicationIdSuffix în Gradle, ceea ce ar face ca clasa .BuildConfig să nu fie accesibilă din acest cod de mai sus.
adăugat autor shkschneider, sursa
Această soluție îmi dă StackOverflowError ...
adăugat autor shkschneider, sursa

Nu este chiar modul corect pentru a verifica dacă sunteți în aroma de depanare, dar puteți verifica dacă aplicația în sine este debugabilă prin:

private static Boolean sIsDebuggable;

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

Comportamentul implicit al aplicațiilor și al bibliotecilor se va potrivi perfect.

Dacă aveți nevoie de o soluție mai bună, puteți folosi în schimb:

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
adăugat

Iată o altă soluție.

1) Creați o interfață

public interface BuildVariantDetector {

    boolean isDebugVariant();

}

2) Utilizați această interfață pe clasa Application (modulul de aplicație)

public class MyApplication extends Application implements BuildVariantDetector {

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

}

3) Și apoi în modulul bibliotecii:

boolean debugVariant = ((BuildVariantDetector)getApplication()).isDebugVariant();
2
adăugat
Soluție simplă și elegantă. Doar asigurați-vă că importați modulul BuildConfig al aplicației, nu biblioteca. E o greșeală foarte plină de mânie.
adăugat autor WindRider, sursa
Acest lucru nu merge. BuildConfig.DEBUG este încă fals pentru mine.
adăugat autor DiscDev, sursa

Puteți crea propria clasă BuildConfig pentru fiecare tip de construcție folosind grală

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

pentru /src/debug /.../ MyBuildConfig.java și ...

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

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

Apoi folosiți:

if (MyBuildConfig.DEBUG)
    Log.d(TAG, "Hey! This is debug version!");
2
adăugat
Are "..." pentru pachetulName al bibliotecii? Dacă da, acest lucru nu pare să funcționeze. Nu pot accesa clasa.
adăugat autor android developer, sursa

Am avut aceeași problemă. Am venit cu ceva de genul:

Avem un SDK (bibliotecă) și un proiect demo, iar ierarhia arată astfel:

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

Pentru aplicația demo pe care o avem, au fost : SDK: jarjarDebug și : SDK: jarjarRelease bidoane prelucrate:

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

Acest lucru funcționează chiar și pentru mai multe buildTypes construite simultan. Depistarea este un pic dificil deși. Vă rugăm să comentați.

1
adăugat

În cazul meu, importați codul BuildConfig greșit deoarece proiectul meu are multe module de bibliotecă. Corecția a fost să imporți codul BuildConfig corect pentru modulul meu app .

0
adăugat

Puteți încerca acest lucru pe fiecare dintre proiectele buildTypes:

parent.allprojects.each{ project -> android.defaultConfig.debuggable = true}
0
adăugat
Puteți să vă explicați? Adăugați-l numai la "debug" buildType? Și la fiecare dintre module? Îmi dă o eroare: Eroare: (31, 0) Nu există o astfel de proprietate: debuggable pentru clasa: com.android.build.gradle.internal.dsl.ProductFlavor_Decorate & zwnj; d
adăugat autor android developer, sursa
Puteți să verificați și să actualizați răspunsul? Dacă există o soluție ușoară, aș vrea să știu despre asta.
adăugat autor android developer, sursa
Specificațiile plug-in-ului Android grade s-au modificat, deci nu mai este valabilă. Flagul debuggabil a fost mutat în buildType și nu în config. Teoria de stabilire a semnelor de depanare ar trebui să facă același truc
adăugat autor pablisco, sursa

Aceasta este soluția mea: reflectă configurația BuildConfig a aplicației:

"debug public static boolean = 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
adăugat
Android dezvoltatori, România — Moldova
Android dezvoltatori, România — Moldova
27 participanți

Parteneri: ciupacabra.com, @php_ro, @js_ro, @node_ro iOS: @ro_ios Reguli: https://github.com/js-ro/it-telegram/blob/master/RULES.md