BuildConfig.DEBUG siempre es falso cuando se crean proyectos de biblioteca con gradle

BuildConfig.DEBUG no funciona (= lógicamente establecido en falso) cuando ejecuto mi aplicación en modo de depuración. Uso gradle para comstackr. Tengo un proyecto de biblioteca donde hago este control. BuildConfig.java se ve así en la carpeta de depuración de comstackción:

/** Automatically generated file. DO NOT MODIFY */ package common.myProject; public final class BuildConfig { public static final boolean DEBUG = Boolean.parseBoolean("true"); } 

y en la carpeta de lanzamiento:

 public static final boolean DEBUG = false; 

tanto en el proyecto de la biblioteca como en el proyecto de la aplicación.

Traté de evitar esto comprobando una variable que está configurada como una clase de mi proyecto. Esta clase hereda de la biblioteca y comienza al inicio.

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

Esto condujo a otro problema: es usar mi variable DEBUG en un DataBaseProvider que se ejecuta antes de la clase de aplicación.

Este es el comportamiento esperado para esto.

Los proyectos de biblioteca solo publican sus variantes de publicación para el consumo de otros proyectos o módulos.

Estamos trabajando para solucionar esto, pero esto no es trivial y requiere una gran cantidad de trabajo.

Puede realizar un seguimiento del problema en https://code.google.com/p/android/issues/detail?id=52962

Con Android Studio 1.1 y también con la versión gradle en 1.1, es posible:

Biblioteca

 android { publishNonDefault true } 

Aplicación

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

La documentación completa se puede encontrar aquí http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Library-Publication

EDITAR :

El problema acaba de marcarse como arreglado para la versión 3.0 de Android Studio Gradle. Allí puede simplemente usar el implementation project(path: ':library') y seleccionará la configuración correcta automáticamente.

Compruebe las imports , a veces BuildConfig se importa de cualquier clase de biblioteca de forma involuntaria. Por ejemplo:

 import io.fabric.sdk.android.BuildConfig; 

En este caso, BuildConfig.DEBUG siempre devolverá falso ;

 import com.yourpackagename.BuildConfig; 

En este caso, BuildConfig.DEBUG devolverá su variante de construcción real .

Esta es como la respuesta de Phil, excepto que no necesita el contexto:

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

Como solución alternativa, puede usar este método, que usa la reflexión para obtener el valor de campo de la aplicación (no de la biblioteca):

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

Para obtener el campo DEBUG , por ejemplo, solo llame a esto desde su Activity :

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

También he compartido esta solución en AOSP Issue Tracker .

No es realmente la forma correcta de verificar si tiene un aspecto depurado, pero puede verificar si la aplicación en sí misma se puede depurar a través de:

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

El comportamiento predeterminado de las aplicaciones y las bibliotecas coincidirá perfectamente.

Si necesita una mejor solución alternativa, puede usar esto en su lugar:

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

Puede crear su propia clase BuildConfig para cada tipo de comstackción usando gradle

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

para /src/debug/…/MyBuildConfig.java y …

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

para /src/release/…/MyBuildConfig.java

Luego usa:

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

Aquí hay otra solución.

1) Crea una interfaz

 public interface BuildVariantDetector { boolean isDebugVariant(); } 

2) Utilice esta interfaz en la clase de aplicación (módulo de aplicación)

 public class MyApplication extends Application implements BuildVariantDetector { @Override public boolean isDebugVariant() { return BuildConfig.DEBUG; //application (main module) Buildonfig } } 

3) Y luego en el módulo de la biblioteca:

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

Tuvimos el mismo problema. Se me ocurrió algo como esto:

Tenemos un SDK (biblioteca) y un proyecto de demostración, la jerarquía se ve así:

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

Para la aplicación de demostración que tenemos, se encuentran :SDK:jarjarDebug y :SDK:jarjarRelease son algunas tareas específicas para :SDK que producen algunas jarras post-procesadas:

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

Esto funciona incluso para múltiples buildTypes construidos a la vez. La depuración es un poco difícil sin embargo. Por favor comenta.

Puede intentar esto en cada uno de los proyectos buildTypes:

 parent.allprojects.each{ project -> android.defaultConfig.debuggable = true} 

En mi caso, estaba importando el BuildConfig incorrecto ya que mi proyecto tiene muchos módulos de biblioteca. La solución fue importar el BuildConfig correcto para mi módulo de app .

Esta es mi solución: reflejar BuildConfig del módulo de la aplicación:

`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; }`