【问题标题】:Release-Debug Builds for Android ApplicationAndroid 应用程序的发布调试版本
【发布时间】:2012-09-09 15:26:20
【问题描述】:

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

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

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

【问题讨论】:

    标签: java android build release


    【解决方案1】:

    如果您从 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 为 false

    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
    }
    

    【讨论】:

      【解决方案2】:

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

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

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

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

      【讨论】:

      • 我建议使用 BuildConfig.DEBUG,因为这发生在编译时,您的解决方案在运行时工作。因此日志记录代码将在包内。在编译时,java 编译器不会考虑 if 语句中的代码。
      • 请查看我更新的答案。这将澄清这是真的 =)
      • 您可能还需要考虑定义自己的全局 public static final boolean DEBUG = false; 以更好地控制结果...(在某些事件中,BuildConfig.DEBUG 并未真正反映系统的状态)。
      【解决方案3】:

      我通常会创建一个单独的日志类,并在其中设置一个静态 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.");
      

      【讨论】:

      • 我的日志对象中有 6 个日志常量。我在构建版本时将其中 2 个设置为 false。
      【解决方案4】:

      每次我将项目作为 android 应用程序运行时,我都面临同样的问题,它曾经在调试器模式下打开,但后来问题解决了。

      -如果您在 Eclipse 中工作,则必须使用 Java EE 透视图 - 而只是选择 Java 透视图。

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

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

      【讨论】:

        【解决方案5】:

        我找到了一种体面地模拟预处理指令的方法:

        在我的 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 输出文件来确定所有这些。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-05-15
          • 1970-01-01
          • 2020-08-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-05-03
          相关资源
          最近更新 更多