web-dev-qa-db-fra.com

BuildConfig.DEBUG toujours faux lors de la construction de projets de bibliothèque avec gradle

BuildConfig.DEBUG ne fonctionne pas (= la valeur logique est définie sur false) lorsque j'exécute mon application en mode débogage . J'utilise Gradle pour créer. J'ai un projet de bibliothèque où je fais cette vérification. BuildConfig.Java ressemble à ceci dans le dossier de débogage de la construction:

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

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

}

et dans le dossier de publication:

public static final boolean DEBUG = false;

à la fois dans le projet de bibliothèque et dans le projet d'application.

J'ai essayé de contourner cela en vérifiant une variable qui est définie dans une classe de mon projet. Cette classe hérite de la bibliothèque et démarre au démarrage.

<application
        Android:name=".MyPrj" ...

Cela pose un autre problème: c’est que j’utilise ma variable DEBUG dans un DataBaseProvider qui s’exécute avant la classe d’application, et elle ne fonctionnera pas correctement en raison de ce bogue.

80
user1324936

C'est le comportement attendu pour cela.

Les projets de bibliothèque publient uniquement leurs variantes de version pour être utilisés par d'autres projets ou modules.

Nous travaillons à la résolution de ce problème, mais ce n’est pas anodin et demande beaucoup de travail.

Vous pouvez suivre le problème à l’adresse https://code.google.com/p/Android/issues/detail?id=52962

51
Xavier Ducrohet

Avec Android Studio 1.1 et ayant également la version graduée à 1.1, il est possible:

Bibliothèque

Android {
    publishNonDefault true
}

App

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

Une documentation complète est disponible ici http://tools.Android.com/tech-docs/new-build-system/user-guide#TOC-Library-Publication

MODIFIER:

Le problème vient d'être marqué comme résolu pour Android Studio Gradle Version 3.0. Là, vous pouvez simplement utiliser implementation project(path: ':library') et cela sélectionnera automatiquement la configuration correcte.

86
Niklas

Recherchez imports, parfois BuildConfig est importé de toute classe de bibliothèque par inadvertance . Par exemple:

import io.fabric.sdk.Android.BuildConfig;

Dans ce cas BuildConfig.DEBUG retournera toujours false ;

import com.yourpackagename.BuildConfig;

Dans ce cas, BuildConfig.DEBUG renverra votre variante réelle build.

38
Gent Berani

C'est comme la réponse de Phil, sauf qu'elle n'a pas besoin du contexte:

private static Boolean sDebug;

/**
 * Is {@link BuildConfig#DEBUG} still broken for library projects? If so, use this.</p>
 * 
 * See: https://code.google.com/p/Android/issues/detail?id=52962</p>
 * 
 * @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
Jared Rummler

Pour contourner le problème, vous pouvez utiliser cette méthode, qui utilise la réflexion pour obtenir la valeur de champ de l'application (et non de la bibliothèque):

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

Pour obtenir le champ DEBUG, par exemple, appelez simplement ceci à partir de votre Activity:

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

J'ai également partagé cette solution sur AOSP Issue Tracker .

6
Phil

Ce n'est pas vraiment la bonne façon de vérifier si vous êtes dans le style de débogage, mais vous pouvez vérifier si l'application elle-même est débogable via:

private static Boolean sIsDebuggable;

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

Le comportement par défaut des applications et des bibliothèques correspondra parfaitement. 

Si vous avez besoin d'une meilleure solution de contournement, vous pouvez utiliser ceci à la place:

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;
}
5
android developer

Voici une autre solution.

1) Créer une interface

public interface BuildVariantDetector {

    boolean isDebugVariant();

}

2) Utiliser cette interface sur la classe d’application (module d’application)

public class MyApplication extends Application implements BuildVariantDetector {

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

}

3) Et ensuite dans le module de bibliothèque:

boolean debugVariant = ((BuildVariantDetector)getApplication()).isDebugVariant();
2

Vous pouvez créer votre propre classe BuildConfig pour chaque type de construction en utilisant gradle

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

pour /src/debug/.../MyBuildConfig.Java and ...

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

pour /src/release/.../MyBuildConfig.Java

Alors utilisez:

if (MyBuildConfig.DEBUG)
    Log.d(TAG, "Hey! This is debug version!");
2
Cluster

Voici ma solution de contournement: Reflète BuildConfig du module d'application:

`public statique 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;
}`
1
dalizhang

Nous avons eu le même problème. Je suis venu avec quelque chose comme ça:

Nous avons un SDK (bibliothèque) et un projet de démonstration, la hiérarchie ressemble à ceci:

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

:SDK:jarjarDebug et :SDK:jarjarRelease sont des tâches spécifiques à :SDK qui produisent des fichiers jar post-traités:

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

Cela fonctionne même pour plusieurs buildTypes construits à la fois. Le débogage est un peu difficile cependant. Commentez s'il vous plaît.

1
javaj

Travailler avec debuggable true dans le fichier Gradle.

buildTypes {
  demo{
 debuggable true
    }
  live{
 debuggable true
    }
}
0
Manikandan

BuildConfig.DEBUG n'est pas du tout fiable, Android a fourni un indicateur interne globalement disponible indiquant si une génération est en mode débogage ou non.

(getContext().getApplicationInfo().flags &ApplicationInfo.FLAG_DEBUGGABLE) != 0) 

sera vrai s'il est en débogage

Crédits: https://medium.com/@elye.project/checking-debug-build-the-right-way-d12da109812

0
Eldhopj

Vous pouvez essayer ceci sur chacun des projets buildTypes:

parent.allprojects.each{ project -> Android.defaultConfig.debuggable = true}
0
pablisco

Dans mon cas, j'importais la mauvaise BuildConfig car mon projet comporte de nombreux modules de bibliothèque. Le correctif consistait à importer la BuildConfig correcte pour mon module app.

0
Ryan R