简体   繁体   English

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

[英]Release-Debug Builds for Android Application

In C++ I would normally setup 2 builds - debug and release with each having DEBUG and RELEASE predefined respectively. 在C ++中,我通常会设置2个版本 - 调试和发布,每个版本分别预定义了DEBUGRELEASE I would then use these definitions to determine constant values, like logging enabled/disabled, server URL and etc. 然后,我将使用这些定义来确定常量值,例如启用/禁用日志记录,服务器URL等。

Right now, in Java/Android I comment out some stuff before building release. 现在,在Java / Android中,我在构建发布之前注释掉了一些内容。 That is not a good way, I can tell. 我可以说,这不是一个好方法。 I may forget something. 我可能会忘记一些事情

What is a common practice for ensuring nothing is forgotten when building a release version (signed) or debug version (unsigned)? 在构建发布版本(签名)或调试版本(未签名)时,确保不遗漏任何内容的常见做法是什么?

If you are running the application from Eclipse, it will always be a debug. 如果从Eclipse运行应用程序,它将始终是一个调试。

When you export the application (Android Tools -> Export (un)signed Application Package) 导出应用程序时(Android工具 - >导出(未签名)签名的应用程序包)

If you want to know dynamically if its release or debug, you can use BuildConfig.DEBUG (Its located in the gen folder, I don't know if this is supported by all the API levels) 如果你想动态了解它的发布或调试,你可以使用BuildConfig.DEBUG(它位于gen文件夹中,我不知道所有API级别是否支持它)

Like as followed: 如下所示:

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

If you look at the generated bytecodes you will see the following (In debug mode): 如果查看生成的字节码,您将看到以下内容(在调试模式下):

public class Sample{

    private static final boolean LOG_ENABLED = true;

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

Produces the following bytecodes: 生成以下字节码:

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

}

And if the BuildConfig.DEBUG is false 如果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
}

There's no (by default) any preprocessor for Java, so no #ifdef stuff at compile time. 没有(默认情况下)Java的任何预处理器,所以在编译时没有#ifdef东西。 But if you do not mind leaving debug code in your app, then you can check if app is release or debug at runtime with this code: 但是如果您不介意在您的应用程序中保留调试代码,那么您可以使用以下代码检查应用程序是否在运行时发布或调试:

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

which checks debuggable flag value. 它检查debuggable标志值。 And said flad is automatically set to false for release builds and true for debug builds. 并且对于发布版本,flad会自动设置为false ,对于调试版本则为true

If you want to get rid of some debug code, you may try using ProGuard to strip certain classes or methods. 如果您想摆脱一些调试代码,可以尝试使用ProGuard去除某些类或方法。 And by default ProGuard is involved in building process for release builds only. 默认情况下,ProGuard仅参与构建发布版本的过程。

I normally create a separate log class where i set a static DEBUG variable. 我通常创建一个单独的日志类,其中我设置一个静态DEBUG变量。 Now all i need to go before getting a production build is to set that DEBUG variable to false. 现在我需要在获得生成构建之前将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);
      }
}

For logging - 用于记录 -

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

I was facing the same issue as everytime I was running the project as android application it used to open in debugger mode but then the problem was solved. 我遇到了同样的问题,因为每次我运行项目时,它都是用于在调试器模式下打开的android应用程序,但问题解决了。

-If you are working in eclipse you must be using Java EE perspective -Instead just select Java perspective. - 如果您在eclipse中工作,则必须使用Java EE透视图 - 而不是选择Java透视图。

-Clean your app. - 清理你的应用程序。 -uninstall the app from the device. - 从设备上卸载应用程序。 -Restart your device (Just like that so that no cache is stored) -Run your app. - 重新启动您的设备(就像这样,以便不存储缓存) - 运行您的应用程序。

The debugger mode won't show up this time. 调试器模式此时不会显示。 Copy the apk generated in your bin folder and try it out on other devices as well 复制bin文件夹中生成的apk,并在其他设备上试用

I found a way to decently emulate a preprocessing directive: 我找到了一种方法来正确模拟预处理指令:

In my Gradle buildTypes I define: 在我的Gradle buildTypes我定义:

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

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

Then, in my code, I do as follows: 然后,在我的代码中,我做如下:

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

and if needed, of course: 如果需要,当然:

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

Both blocks are present in the debug APK, but when building a release version, Proguard is clever enough to determine that the debug block can be removed as it is dependant of a if (false) (which is also removed from the resulting code). 这两个块都存在于debug APK中,但是在构建release版本时, Proguard足够聪明地确定可以删除debug块,因为它依赖于if (false) (也从结果代码中删除)。

Should you call some debug-specific classes from the debug block and only from there, they will be stripped out from the resulting APK as they are considered unused , and this also an interesting point: your code cannot be tempered in a way it would use that code. 你应该从debug块调用一些特定于调试的类,并且只从那里调用它们,它们将从生成的APK中被删除,因为它们被认为是未使用的 ,这也是一个有趣的观点:你的代码不能以它将使用的方式进行调整那段代码。

I could determine all that by checking my dump , mapping and usage Proguard output files. 我可以通过检查我的dumpmappingusage Proguard输出文件来确定所有这些。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Android - 依赖项和代码分离(调试/发布版本) - Android - dependencies and code separation (debug/release builds) 如何为特定的应用程序构建(调试/发布)使用特定的字段? - How to use specific fields for specific application builds (debug/release)? DEBUG和RELEASE用Java(Eclipse)构建? - DEBUG and RELEASE builds in Java (Eclipse)? 为什么有.Net的Debug和Release版本,但Java没有? - Why are there Debug & Release builds for .Net, but not for Java? 如何在android ant发布和调试版本中附加不同的字符串资源文件? - How can I attach different string resource files during android ant release and debug builds? 是什么导致Android的DisplayMetrics.densityDpi在Release版本和Debug版本之间有所不同? - What could cause Android's DisplayMetrics.densityDpi to differ between Release and Debug builds? 为Android Studio中的调试版本定义类 - Define classes for debug builds in android studio Android GoogleCredential Debug vs Release - Android GoogleCredential Debug vs Release Android - Jackson JSON解析器在&#39;release&#39;版本中返回null值 - Android - Jackson JSON parser returns null value in 'release' builds 谷歌登录Android - 发布与调试 - Google Sign in for Android - Release vs Debug
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM