簡體   English   中英

Android應用程序的發布 - 調試版本

[英]Release-Debug Builds for Android Application

在C ++中,我通常會設置2個版本 - 調試和發布,每個版本分別預定義了DEBUGRELEASE 然后,我將使用這些定義來確定常量值,例如啟用/禁用日志記錄,服務器URL等。

現在,在Java / Android中,我在構建發布之前注釋掉了一些內容。 我可以說,這不是一個好方法。 我可能會忘記一些事情

在構建發布版本(簽名)或調試版本(未簽名)時,確保不遺漏任何內容的常見做法是什么?

如果從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
}

沒有(默認情況下)Java的任何預處理器,所以在編譯時沒有#ifdef東西。 但是如果您不介意在您的應用程序中保留調試代碼,那么您可以使用以下代碼檢查應用程序是否在運行時發布或調試:

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

它檢查debuggable標志值。 並且對於發布版本,flad會自動設置為false ,對於調試版本則為true

如果您想擺脫一些調試代碼,可以嘗試使用ProGuard去除某些類或方法。 默認情況下,ProGuard僅參與構建發布版本的過程。

我通常創建一個單獨的日志類,其中我設置一個靜態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.");

我遇到了同樣的問題,因為每次我運行項目時,它都是用於在調試器模式下打開的android應用程序,但問題解決了。

- 如果您在eclipse中工作,則必須使用Java EE透視圖 - 而不是選擇Java透視圖。

- 清理你的應用程序。 - 從設備上卸載應用程序。 - 重新啟動您的設備(就像這樣,以便不存儲緩存) - 運行您的應用程序。

調試器模式此時不會顯示。 復制bin文件夾中生成的apk,並在其他設備上試用

我找到了一種方法來正確模擬預處理指令:

在我的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輸出文件來確定所有這些。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM