Android应用程序的发布 - 调试版本

时间:2012-09-17 12:06:33

标签: java android build release

在C ++中,我通常会设置2个版本 - 调试和发布,每个版本分别预定义DEBUGRELEASE。然后,我将使用这些定义来确定常量值,例如启用/禁用日志记录,服务器URL等。

现在,在Java / Android中,我在构建发布之前注释掉了一些内容。我可以说,这不是一个好方法。我可能会忘记一些事情。

在构建发布版本(签名)或调试版本(未签名)时,确保不遗漏任何内容的常见做法是什么?

5 个答案:

答案 0 :(得分:15)

如果从Eclipse运行应用程序,它将始终是一个调试。

导出应用程序时(Android工具 - >导出(未签名)应用程序包)

如果你想动态了解它的发布或调试,你可以使用BuildConfig.DEBUG(它位于gen文件夹中,我不知道所有API级别是否支持它)

如下所示:

if (BuildConfig.DEBUG) {
    Log.d(TAG, "Text");
}

如果查看生成的字节码,您将看到以下内容(在调试模式下):

public class Sample{

    private static final boolean LOG_ENABLED = true;

    public static void main(String args[]){
        if (BuildConfig.DEBUG){
            System.out.println("Hello World");
        }
    }
}

生成以下字节码:

public class Sample extends java.lang.Object{
    public Sample();
      Code:
       0:   aload_0
       1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
       4:   return

    public static void main(java.lang.String[]);
      Code:
       0:   getstatic   #2; //Field java/lang/System.out:Ljava/io/PrintStream;
       3:   ldc #3; //String Hello World
       5:   invokevirtual   #4; //Method Java/io/PrintStream.println(Ljava/lang/String;)V
       8:   return

}

如果BuildConfig.DEBUG为假

public class Sample extends java.lang.Object{
    public Sample();
      Code:
       0:   aload_0
       1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
       4:   return

    public static void main(java.lang.String[]);
      Code:
       0:   return
}

答案 1 :(得分:8)

没有(默认情况下)Java的任何预处理器,因此编译时没有#ifdef内容。但是如果您不介意在您的应用程序中保留调试代码,那么您可以使用以下代码检查应用程序是否在运行时发布或调试:

Boolean release = (getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE);

检查debuggable标志值。并且说flad对于发布版本自动设置为false,对于调试版本自动设置为true

如果要删除某些调试代码,可以尝试使用ProGuard去除某些类或方法。默认情况下,ProGuard仅参与构建发布版本的过程。

答案 2 :(得分:0)

我通常会创建一个单独的日志类,其中我设置了一个静态DEBUG变量。现在,在获得生产构建之前我需要做的就是将DEBUG变量设置为false。

public class Log {
     public final static String LOGTAG = "APP NAME";

      public static final boolean DEBUG = true;

      public static void v(String msg) {
        android.util.Log.v(LOGTAG, msg);
      }

      public static void e(String msg) {
        android.util.Log.e(LOGTAG, msg);
      }

      public static void d(String msg) {
          android.util.Log.d(LOGTAG, msg);
      }
}

用于记录 -

if(Log.DEBUG) Log.v("In some function x. Doing y.");

答案 3 :(得分:0)

我遇到了同样的问题,因为每次我运行项目时,它都是以调试器模式打开的android应用程序,但问题解决了。

- 如果您在eclipse中工作,则必须使用Java EE透视图 - 只需选择Java perspective。

清理您的应用。 - 从设备上卸载应用程序。 - 重新启动你的设备(就像那样,不存储任何缓存) - 运行你的应用程序。

此次调试器模式不会显示。复制bin文件夹中生成的apk,并在其他设备上试用

答案 4 :(得分:0)

我找到了一种方法来模拟预处理指令:

在我的Gradle buildTypes我定义:

release {
    buildConfigField "boolean", "isDebug", "false"
    ...
}

debug {
    buildConfigField "boolean", "isDebug", "true"
    ...
}

然后,在我的代码中,我按如下方式执行:

if (BuildConfig.isDebug) {
    ... do debug stuff ...
}

如果需要,当然:

else {
    ... do release stuff ...
}

这两个块都出现在debug APK中,但在构建release版本时, Proguard足够聪明,可以确定debug块可以删除因为它取决于if (false)(也从结果代码中删除)。

您是否应该从debug块调用某些特定于调试的类,并且仅从那里调用它们,它们将从生成的APK中被删除,因为它们被视为未使用,这也是有趣的是:您的代码无法以使用该代码的方式进行调整。

我可以通过查看我的dumpmappingusage Proguard输出文件来确定所有这些。