使用gradle构建库项目时,BuildConfig.DEBUG始终为false

时间:2013-11-24 15:29:44

标签: android gradle android-library

当我在调试模式下运行我的应用程序时,

BuildConfig.DEBUG无效(=逻辑设置为false)。 我用Gradle来构建。我有一个图书馆项目,我在这里检查。 BuildConfig.java在构建调试文件夹中看起来像这样:

/** Automatically generated the 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;

在库项目和应用程序项目中。

我试图通过检查一个设置了我的项目类的变量来解决这个问题。该类继承自库并在启动时启动。

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

这导致了另一个问题:我在应用程序类之前运行的DataBaseProvider中使用我的DEBUG变量,并且由于此错误它将无法正常运行。

14 个答案:

答案 0 :(得分:86)

使用Android Studio 1.1并且还有1.1版的gradle版本:

<强>库

android {
    publishNonDefault true
}

应用

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

完整文档可在http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Library-Publication

找到

修改

issue刚刚被标记为Android Studio Gradle 3.0版已修复。在那里,您只需使用implementation project(path: ':library'),它就会自动选择正确的配置。

答案 1 :(得分:51)

这是预期的行为。

图书馆项目仅发布其版本变体供其他项目或模块使用。

我们正在努力解决这个问题,但这非常重要,需要大量的工作。

您可以在https://code.google.com/p/android/issues/detail?id=52962

跟踪问题

答案 2 :(得分:39)

检查imports,有时 BuildConfig 是从任意类库中无意中导入的。 例如:

import io.fabric.sdk.android.BuildConfig;

在这种情况下, BuildConfig.DEBUG 将始终返回 false ;

import com.yourpackagename.BuildConfig;

在这种情况下, BuildConfig.DEBUG 将返回您真正的构建变体。

答案 3 :(得分:7)

这就像Phil的答案,除了它不需要上下文:

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

答案 4 :(得分:6)

作为一种变通方法,您可以使用此方法,该方法使用反射从应用程序(而不是库)获取字段值:

/**
 * 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字段,例如,只需从Activity调用此字段:

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

我也在AOSP Issue Tracker上分享了这个解决方案。

答案 5 :(得分:5)

检查您是否处于调试风格并不是正确的方法,但您可以通过以下方式检查应用程序本身是否可调试:

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

答案 6 :(得分:2)

您可以使用gradle

为每种构建类型创建自己的BuildConfig类
public class MyBuildConfig
{
    public static final boolean DEBUG = true;
}

/ src / debug /.../ MyBuildConfig.java 和...

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

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

然后使用:

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

答案 7 :(得分:2)

这是另一种解决方案。

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();

答案 8 :(得分:1)

我们遇到了同样的问题。我想出了类似的东西:

我们有一个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也是如此。但调试有点困难。请评论。

答案 9 :(得分:1)

这是我的解决方法: 反映app模块的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;
}`

答案 10 :(得分:0)

您可以在每个项目buildTypes上尝试这个:

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

答案 11 :(得分:0)

在我的情况下,我导入了错误的BuildConfig,因为我的项目有很多库模块。解决方法是为我的BuildConfig模块导入正确的app

答案 12 :(得分:0)

在gradle文件中使用可调试的true。

buildTypes {
  demo{
 debuggable true
    }
  live{
 debuggable true
    }
}

答案 13 :(得分:0)

BuildConfig.DEBUG根本不可靠,Android提供了一个内部标志,该标志在全球范围内可用,指示内部版本处于调试模式还是非调试模式

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

如果在调试中,则为true

信用:https://medium.com/@elye.project/checking-debug-build-the-right-way-d12da1098120