2012-09-17 7 views
7

In C++ würde ich normalerweise 2 Builds - debuggen und release mit jeweils DEBUG und RELEASE vordefiniert. Ich würde dann diese Definitionen verwenden, um konstante Werte zu bestimmen, wie Protokollierung aktiviert/deaktiviert, Server-URL und etc.Release-Debug Builds für Android-Anwendung

Im Moment, in Java/Android kommentieren ich einige Sachen vor der Erstellung der Veröffentlichung. Das ist kein guter Weg, kann ich sagen. Ich kann etwas vergessen.

Wie ist es üblich sicherzustellen, dass beim Erstellen einer Release-Version (signiert) oder einer Debug-Version (unsigniert) nichts vergessen wird?

Antwort

8

Es gibt keine (Standard) jede Präprozessor für Java, so dass keine #ifdef Sachen bei der Kompilierung. Aber wenn es Ihnen nichts ausmachen Debug-Code in der App zu verlassen, dann können Sie überprüfen, ob App-Release oder Debug zur Laufzeit mit diesem Code ist:

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

die debuggable Flag-Wert überprüft. Und flad wird automatisch auf false für Release-Builds und true für Debug-Builds festgelegt.

Wenn Sie Debug-Code loswerden möchten, können Sie ProGuard verwenden, um bestimmte Klassen oder Methoden zu entfernen. Und standardmäßig ist ProGuard nur für Release Builds am Erstellungsprozess beteiligt.

+3

Ich würde BuildConfig.DEBUG empfehlen, da dies in der Kompilierzeit passiert, arbeitet Ihre Lösung Laufzeit. Daher befindet sich der Protokollierungscode im Paket. Zur Kompilierzeit berücksichtigt der Java-Compiler den Code innerhalb der if-Anweisung nicht. –

+0

Bitte überprüfen Sie meine aktualisierte Antwort. Dies wird klarstellen, dass es wahr ist =) –

+0

Sie können auch überlegen, wie Sie Ihren eigenen globalen 'public static final boolean DEBUG = false;' für eine bessere Kontrolle über das Ergebnis definieren ... (es gab Fälle, in denen 'BuildConfig.DEBUG 'war nicht wirklich den Zustand des Systems widerspiegeln). –

14

Wenn Sie die Anwendung von Eclipse ausführen, wird es immer ein Debug sein.

Wenn Sie die Anwendung exportieren (Android Tools -> Export (un) unterzeichnet Anwendungspaket)

Wenn Sie dynamisch, wenn seine Freigabe oder Debug wissen wollen, Sie BuildConfig.DEBUG (Es liegt in der gen verwenden können Ordner, ich weiß nicht, ob dies von allen API-Ebenen unterstützt wird)

wie wie folgt:

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

wenn man sich die erzeugten Bytecode sehen Sie die folgende (im Debug-Modus sehen):

public class Sample{ 

    private static final boolean LOG_ENABLED = true; 

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

Erzeugt die folgenden Bytecode:

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 

} 

Und wenn die BuildConfig.DEBUG falsch ist

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

ich normalerweise eine separate Protokoll Klasse erstellen, wo ich eine statische DEBUG Variable gesetzt. Jetzt muss ich nur noch gehen, um einen Produktions-Build zu erhalten, indem ich diese DEBUG-Variable auf false setze.

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

Für die Protokollierung -

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

Ich habe 6 Logging-Konstanten in meinem Logging-Objekt. Ich habe 2 davon falsch gesetzt, als ich eine Veröffentlichung erstellt habe. – Pijusn

0

Ich hatte das gleiche Problem wie jedes Mal, wenn ich das Projekt als Android-Anwendung lief es im Debugger-Modus zu öffnen, aber dann das Problem gelöst wurde.

-Wenn Sie in Eclipse arbeiten, müssen Sie Java EE Perspektive verwenden -Stellen Sie nur Java-Perspektive.

- Reinigen Sie Ihre App. -Installieren Sie die App vom Gerät. -Restart Ihr Gerät (So, dass kein Cache gespeichert ist) -Rennen Sie Ihre App.

Der Debugger-Modus wird dieses Mal nicht angezeigt. Kopieren Sie die apk erzeugt in Ihrem Ordner bin und probieren Sie es aus auf anderen Geräten als auch

0

ich einen Weg gefunden, um anständig eine Präprozessordirektive zu emulieren:

In meinem Gradle buildTypes Ich definiere:

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

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

dann in meinem Code, ich wie folgt:

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

und bei Bedarf natürlich:

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

Beiden Blöcke sind in dem debug APK, aber wenn eine release Version Aufbau, Proguard ist klug genug, um zu bestimmen, dass der debug Block entfernt werden kann, da sie abhängig von einem if (false) ist (die ebenfalls aus dem entfernt wird, resultierender Code).

sollten Sie einige Debug-spezifische Klassen aus dem debug Block aufrufen und nur dort aus, werden sie aus der resultierenden APK werden gezupft, da sie ungenutzt betrachtet werden, und dies auch ein interessanter Punkt: Ihr Code kann nicht temperiert werden in gewisser Weise würde es diesen Code benutzen.

Ich konnte das alles feststellen, indem ich meine Proguard-Ausgabedateien dump, mapping und usage überprüfte.

Verwandte Themen