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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20176284/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 02:24:53  来源:igfitidea点击:

BuildConfig.DEBUG always false when building library projects with gradle

androidgradleandroid-library

提问by user1324936

BuildConfig.DEBUG is not working (= logically set to false) when I run my app in debug mode. I use Gradle to build. I have a library project where I do this check. BuildConfig.java looks like this in the build debug folder:

当我在调试模式下运行我的应用程序时,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");

}

and in the release folder:

并在发布文件夹中:

public static final boolean DEBUG = false;

both in the library project and in the application project.

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

I tried to get around this by checking a variable which is set a class of my project. This class inherits from the library and starts on startup.

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

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

This leads to another problem: is that I use my DEBUG variable in a DataBaseProvider which runs before the application class, and it will not run properly due to this bug.

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

采纳答案by Xavier Ducrohet

This is expected behavior for this.

这是预期的行为。

Library projects only publish their release variants for consumption by other projects or modules.

库项目仅发布其发布变体供其他项目或模块使用。

We're working at fixing this but this is non trivial and requires a significant amount of work.

我们正在努力解决这个问题,但这不是微不足道的,需要大量的工作。

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

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

回答by Niklas

With Android Studio 1.1 and having also the gradle version at 1.1 it is possible:

使用 Android Studio 1.1 并且还有 1.1 的 gradle 版本,它是可能的:

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

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

EDIT:

编辑

The issuehas just been marked as fixed for the Android Studio Gradle Version 3.0. There you can just use implementation project(path: ':library')and it'll select the correct configuration automatically.

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

回答by Gent Berani

Check for imports, sometimes BuildConfigis imported from any class of library unintentionally. For example:

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

import io.fabric.sdk.android.BuildConfig;

In this case BuildConfig.DEBUGwill always return false;

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

import com.yourpackagename.BuildConfig;

In this case BuildConfig.DEBUGwill return your real build variant.

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

回答by Jared Rummler

This is like Phil's answer except it doesn't need the context:

这就像菲尔的答案,只是它不需要上下文:

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

回答by Phil

As a workaround, you can use this method, which uses reflection to get the field value from the app (not the library):

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

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

To get the DEBUGfield, for example, just call this from your Activity:

DEBUG例如,要获取该字段,只需从您的Activity

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

I have also shared this solution on the AOSP Issue Tracker.

我还在AOSP 问题跟踪器上分享了这个解决方案。

回答by android developer

Not really the correct way to check if you are in debug flavor, but you can check if the app itself is debuggable via:

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

private static Boolean sIsDebuggable;

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

The default behavior of apps and libraries will match it perfectly.

应用程序和库的默认行为将完美匹配。

If you need a better workaround, you can use this instead:

如果您需要更好的解决方法,可以改用它:

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

回答by Dominik Suszczewicz

Here is another solution.

这是另一种解决方案。

1) Create an interface

1)创建接口

public interface BuildVariantDetector {

    boolean isDebugVariant();

}

2) Use this interface on Application class (Appplication module)

2)在Application类(应用模块)上使用这个接口

public class MyApplication extends Application implements BuildVariantDetector {

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

}

3) And then in library module:

3)然后在库模块中:

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

回答by Cluster

You can create your own BuildConfig class for each build type using gradle

您可以使用 gradle 为每种构建类型创建自己的 BuildConfig 类

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

for /src/debug/.../MyBuildConfig.javaand...

对于/src/debug/.../MyBuildConfig.java和...

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

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

对于/src/release/.../MyBuildConfig.java

Then use:

然后使用:

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

回答by javaj

We had the same problem. I came up with something like this:

我们遇到了同样的问题。我想出了这样的事情:

We have a SDK (library) and a demo project, hierarchy looks like this:

我们有一个 SDK(库)和一个演示项目,层次结构如下所示:

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

For the demo app we have, were :SDK:jarjarDebugand :SDK:jarjarReleaseare some specific tasks for :SDKthat produce some post-processed jars:

对于我们拥有的演示应用程序,过去:SDK:jarjarDebug:SDK:jarjarRelease现在是一些特定任务,:SDK用于生成一些后处理的 jars:

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

This works even for multiple buildTypesbuilt at once. Debugging is a bit difficult though. Please comment.

这甚至适用buildTypes于一次构建的多个。不过调试有点困难。请给出意见。

回答by dalizhang

This is my workaround: reflect BuildConfig of app module:

这是我的解决方法:反映应用模块的 BuildConfig:

`public static boolean debug = isDebug();

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