Laut Google muss ich " alle Aufrufe von Protokollierungsmethoden im Quellcode deaktivieren ", bevor ich meine Android-App bei Google Play veröffentliche. Auszug aus Abschnitt 3 der Publikations-Checkliste :
Stellen Sie sicher, dass Sie die Protokollierung deaktivieren und die Debugging-Option deaktivieren, bevor Sie Ihre Anwendung für die Freigabe erstellen. Sie können die Protokollierung deaktivieren, indem Sie Aufrufe von Protokollmethoden in Ihren Quelldateien entfernen.
Mein Open-Source-Projekt ist groß und es ist mühsam, es jedes Mal manuell zu machen, wenn ich es veröffentliche. Darüber hinaus ist das Entfernen einer Protokollzeile möglicherweise schwierig, z. B.:
if(condition)
Log.d(LOG_TAG, "Something");
data.load();
data.show();
Wenn ich die Protokollzeile kommentiere, gilt die Bedingung für die nächste Zeile, und es besteht die Möglichkeit, dass load () nicht aufgerufen wird. Sind solche Situationen selten genug, dass ich entscheiden kann, dass sie nicht existieren sollten?
Gibt es eine bessere Möglichkeit, dies auf Quellcode-Ebene zu tun? Oder vielleicht eine clevere ProGuard-Syntax, um alle Protokollzeilen effizient, aber sicher zu entfernen?
quelle
sed 's_^\(\s*Log\.\)_;//'`date|tr -s \ -`'\1_g'
stattdessen verwenden.Antworten:
Ich finde eine viel einfachere Lösung, alle
if
Überprüfungen überall zu vergessen und einfach ProGuard zu verwenden, um alleLog.d()
oderLog.v()
Methodenaufrufe zu entfernen, wenn wir unser Ant-release
Ziel aufrufen .Auf diese Weise werden immer die Debug-Informationen für reguläre Builds ausgegeben und wir müssen keine Codeänderungen für Release-Builds vornehmen. ProGuard kann den Bytecode auch mehrfach durchlaufen, um andere unerwünschte Anweisungen und leere Blöcke zu entfernen, und gegebenenfalls automatisch kurze Methoden einbinden.
Hier ist zum Beispiel eine sehr grundlegende ProGuard-Konfiguration für Android:
Sie würden das also in einer Datei speichern und dann ProGuard von Ant aus aufrufen und Ihre gerade kompilierte JAR und die von Ihnen verwendete Android-Plattform-JAR übergeben.
Siehe auch die Beispiele im ProGuard-Handbuch.
Update (4,5 Jahre später): Heutzutage habe ich Timber für die Android-Protokollierung verwendet.
Es ist nicht nur ein bisschen schöner als die Standardimplementierung
Log
- das Protokoll-Tag wird automatisch festgelegt und es ist einfach, formatierte Zeichenfolgen und Ausnahmen zu protokollieren -, sondern Sie können auch zur Laufzeit unterschiedliche Protokollierungsverhalten angeben.In diesem Beispiel werden Protokollierungsanweisungen nur in Debug-Builds meiner App in logcat geschrieben:
Holz wird in meiner
Application
onCreate()
Methode eingerichtet:Dann kann ich mich überall in meinem Code einfach anmelden:
In der Timber-Beispiel-App finden Sie ein erweitertes Beispiel, in dem alle Protokollanweisungen während der Entwicklung an logcat gesendet werden und in der Produktion keine Debug-Anweisungen protokolliert werden, Fehler jedoch unbemerkt an Crashlytics gemeldet werden.
quelle
Alles gute Antworten, aber als ich mit meiner Entwicklung fertig war, wollte ich weder if-Anweisungen für alle Log-Aufrufe verwenden, noch wollte ich externe Tools verwenden.
Die Lösung, die ich verwende, besteht darin, die android.util.Log-Klasse durch meine eigene Log-Klasse zu ersetzen:
Das einzige, was ich in allen Quelldateien tun musste, war, den Import von android.util.Log durch meine eigene Klasse zu ersetzen.
quelle
Log.d("tag", someValue.toString());
sehr leicht zu vergessen ist, someValue auf Null zu überprüfen, was bedeutet, dass möglicherweise ein WertNullPointerException
in der Produktion ausgelöst wird . Es schlägt eine sichere Lösung vor, aber es wird Sie austricksen. Wir uns einprivate static boolean DEBUG
und dannif(DEBUG)Log.d(TAG, msg);
String
. Komplettlösung ist decribed hier . Dies hat anscheinend einen weiteren Nachteil: Jeder Anruf sollte bearbeitet werden (nicht nur eine Importzeile).static final boolean LOG = BuildConfig.DEBUG
diese Datei verwenden und müssen sie nie ändern.Ich schlage vor, irgendwo einen statischen Booleschen Wert zu haben, der angibt, ob protokolliert werden soll oder nicht:
Dann tun Sie einfach, wo immer Sie Ihren Code anmelden möchten:
Wenn Sie MyDebug.LOG auf false setzen, entfernt der Compiler den gesamten Code in solchen Überprüfungen (da es sich um ein statisches Finale handelt, weiß er zur Kompilierungszeit, dass kein Code verwendet wird.)
Bei größeren Projekten möchten Sie möglicherweise Boolesche Werte in einzelnen Dateien verwenden, um die Protokollierung dort bei Bedarf einfach aktivieren oder deaktivieren zu können. Dies sind beispielsweise die verschiedenen Protokollierungskonstanten, die wir im Fenstermanager haben:
Mit entsprechendem Code wie:
quelle
Die Proguard-Lösung von Christopher ist die beste, aber wenn Sie Proguard aus irgendeinem Grund nicht mögen, finden Sie hier eine sehr Low-Tech-Lösung:
Kommentarprotokolle:
Kommentarprotokolle:
Eine Einschränkung besteht darin, dass sich Ihre Protokollierungsanweisungen nicht über mehrere Zeilen erstrecken dürfen.
(Führen Sie diese Zeilen in einer UNIX-Shell im Stammverzeichnis Ihres Projekts aus. Wenn Sie Windows verwenden, rufen Sie eine UNIX-Ebene ab oder verwenden Sie entsprechende Windows-Befehle.)
quelle
//
vs.;//
)Ich möchte einige Präzisionen zur Verwendung von Proguard mit Android Studio und gradle hinzufügen, da ich viele Probleme hatte, Protokollzeilen aus der endgültigen Binärdatei zu entfernen.
Um
assumenosideeffects
in Proguard Werke zu machen , gibt es eine Voraussetzung.In Ihrer Gradle-Datei müssen Sie die Verwendung der
proguard-android-optimize.txt
Standarddatei angeben .In der Standarddatei
proguard-android.txt
ist die Optimierung mit den beiden Flags deaktiviert:Die
proguard-android-optimize.txt
Datei fügt diese Zeilen nicht hinzu, sodass sie jetztassumenosideeffects
funktionieren können.Dann persönlich verwende ich SLF4J , umso mehr, wenn ich einige Bibliotheken entwickle, die an andere verteilt werden. Der Vorteil ist, dass standardmäßig keine Ausgabe erfolgt. Wenn der Integrator einige Protokollausgaben wünscht, kann er Logback für Android verwenden und die Protokolle aktivieren, sodass Protokolle in eine Datei oder in LogCat umgeleitet werden können.
Wenn ich die Protokolle wirklich aus der endgültigen Bibliothek entfernen muss, füge ich sie meiner Proguard-Datei hinzu (nachdem ich die
proguard-android-optimize.txt
Datei natürlich aktiviert habe ):quelle
proguard-android-optimize.txt
als Standard-Proguard-Datei als auch-assumenosideeffects
als benutzerdefinierte Proguard-Datei benötigt! Ich verwende R8 Shinker (heutzutage die Standardeinstellung) und die Standard-Android-Protokollierung.Ich empfehle dringend, Timber von Jake Wharton zu verwenden
https://github.com/JakeWharton/timber
Es löst Ihr Problem mit dem Aktivieren / Deaktivieren und fügt automatisch Tag-Klassen hinzu
gerade
Protokolle werden nur in Ihrer Debug-Version verwendet und dann verwendet
oder
zu drucken
"Deine Klasse / Nachricht" ohne Angabe des Tags
quelle
Ich habe eine LogUtils- Klasse wie in der Google IO-Beispielanwendung verwendet. Ich habe dies geändert, um eine anwendungsspezifische DEBUG-Konstante anstelle von BuildConfig.DEBUG zu verwenden, da BuildConfig.DEBUG unzuverlässig ist . Dann habe ich in meinen Klassen Folgendes.
quelle
Build.DEBUG
, den ich früher verwendet habe. Ich habe auch die verschiedenen "richtigen" Problemumgehungen aufgegeben und eine ähnliche Lösung wie Sie verwendet.Ich würde in Betracht ziehen, die Protokollierungsfunktion von roboguice zu verwenden anstelle des integrierten android.util.Log zu verwenden
Ihre Funktion deaktiviert automatisch Debug- und ausführliche Protokolle für Release-Builds. Außerdem erhalten Sie einige nützliche Funktionen kostenlos (z. B. anpassbares Protokollierungsverhalten, zusätzliche Daten für jedes Protokoll und mehr).
Mit proguard ziemlich lästig sein könnte und ich würde die Mühe der Konfiguration und macht es nicht durchgehen arbeitet mit Ihrer Anwendung , wenn Sie einen guten Grund dafür haben (Deaktivierung Protokolle ist nicht gut)
quelle
Ich poste diese Lösung, die speziell für Android Studio-Benutzer gilt. Ich habe kürzlich auch Timber entdeckt und es erfolgreich in meine App importiert, indem ich Folgendes getan habe:
Fügen Sie die neueste Version der Bibliothek in Ihr build.gradle ein:
Gehen Sie dann in Android Studios zu Bearbeiten -> Suchen -> In Pfad ersetzen ...
Geben
Log.e(TAG,
Sie in das"Text to find"
Textfeld ein oder wie auch immer Sie Ihre Protokollnachrichten definiert haben . Dann ersetzen Sie es einfach durchTimber.e(
Klicken Sie auf Suchen und ersetzen Sie alle.
Android Studios durchsucht nun alle Ihre Dateien in Ihrem Projekt und ersetzt alle Protokolle durch Timbers.
Das einzige Problem, das ich mit dieser Methode hatte, ist, dass gradle danach eine Million Fehlermeldungen ausgibt, weil es nicht "Timber" in den Importen für jede Ihrer Java-Dateien finden kann. Klicken Sie einfach auf die Fehler und Android Studios importiert automatisch "Timber" in Ihr Java. Sobald Sie dies für alle Ihre Fehlerdateien getan haben, wird gradle erneut kompiliert.
Sie müssen diesen Code auch in Ihre
onCreate
Methode IhrerApplication
Klasse einfügen :Dies führt nur dann zur App-Protokollierung, wenn Sie sich im Entwicklungsmodus befinden und nicht in der Produktion. Sie können sich auch
BuildConfig.RELEASE
im Release-Modus anmelden.quelle
import android\.util\.Log\;
Ersetzen durch:import android\.util\.Log\;\nimport timber\.log\.Timber\;
Per android.util.Log bietet eine Möglichkeit zum Aktivieren / Deaktivieren des Protokolls:
Standardmäßig gibt die Methode isLoggable (...) false zurück, erst nachdem Sie setprop im Gerät wie folgt eingestellt haben:
Dies bedeutet, dass jedes Protokoll über der DEBUG-Ebene ausgedruckt werden kann. Referenz Android Doc:
Wir könnten also ein benutzerdefiniertes Protokoll verwenden:
quelle
Wenn Sie ein globales Ersetzen (einmal) ausführen und danach einige Codierungskonventionen beibehalten können, können Sie dem im Android- Framework häufig verwendeten Muster folgen .
Anstatt zu schreiben
habe es als
Jetzt kann proguard den StringBuilder und alle Strings und Methoden, die er unterwegs verwendet, aus dem optimierten Release-DEX entfernen. Verwenden
proguard-android-optimize.txt
Sie und Sie müssen sich keine Sorgen um android.util.Log in Ihremproguard-rules.pro
:Mit dem Android Studio Gradle Plugin ist es ziemlich zuverlässig, sodass Sie keine zusätzlichen Konstanten benötigen, um das Strippen zu steuern.
BuildConfig.DEBUG
quelle
Fügen Sie Ihrer Datei proguard-rules.txt Folgendes hinzu
quelle
Das habe ich bei meinen Android-Projekten gemacht.
In Android Studio können wir ähnliche Vorgänge ausführen, indem wir Strg + Umschalt + F aus dem gesamten Projekt suchen (Befehl + Umschalt + F in MacOs) und Strg + Umschalt + R ersetzen ((Befehl + Umschalt + R in MacOs)).
quelle
Ich habe eine sehr einfache Lösung. Ich verwende IntelliJ für die Entwicklung, daher variieren die Details, aber die Idee sollte für alle IDEs gelten.
Ich wähle das Stammverzeichnis meines Quellbaums aus, klicke mit der rechten Maustaste und wähle "Ersetzen" aus. Ich beschließe dann, alle "Log" zu ersetzen. mit "// Log.". Dadurch werden alle Protokollanweisungen entfernt. Um sie später wieder zurückzusetzen, wiederhole ich das gleiche Ersetzen, diesmal jedoch als Ersetzen aller "// Log". mit "Log.".
Funktioniert einfach super für mich. Denken Sie daran, den Ersatz auf Groß- und Kleinschreibung zu setzen, um Unfälle wie "Dialog" zu vermeiden. Für zusätzliche Sicherheit können Sie auch den ersten Schritt mit "Protokoll" ausführen. als zu suchende Zeichenfolge.
Brillant.
quelle
Wie aus dem Kommentar von zserge hervorgeht ,
seine Logbibliothek bietet einen einfachen Schalter zum Aktivieren / Deaktivieren des Protokolldrucks (siehe unten).
Außerdem müssen nur die
import
Zeilen geändert werden, und für die Anweisung muss nichts geändertLog.d(...);
werden.quelle
Ich habe die obige Lösung verbessert, indem ich Unterstützung für verschiedene Protokollebenen bereitgestellt und die Protokollebenen automatisch geändert habe, je nachdem, ob der Code auf einem Live-Gerät oder auf dem Emulator ausgeführt wird.
quelle
ProGuard erledigt dies für Sie bei Ihrem Release-Build und jetzt für die guten Nachrichten von android.com:
http://developer.android.com/tools/help/proguard.html
Das ProGuard-Tool verkleinert, optimiert und verschleiert Ihren Code, indem nicht verwendeter Code entfernt und Klassen, Felder und Methoden mit semantisch undurchsichtigen Namen umbenannt werden. Das Ergebnis ist eine kleinere APK-Datei, deren Reverse Engineering schwieriger ist. Da ProGuard das Reverse Engineering Ihrer Anwendung erschwert, ist es wichtig, dass Sie es verwenden, wenn Ihre Anwendung sicherheitsrelevante Funktionen verwendet, z. B. wenn Sie Ihre Anwendungen lizenzieren.
ProGuard ist in das Android-Build-System integriert, sodass Sie es nicht manuell aufrufen müssen. ProGuard wird nur ausgeführt, wenn Sie Ihre Anwendung im Release-Modus erstellen, sodass Sie sich beim Erstellen Ihrer Anwendung im Debug-Modus nicht mit verschleiertem Code befassen müssen. Das Ausführen von ProGuard ist völlig optional, wird jedoch dringend empfohlen.
In diesem Dokument wird beschrieben, wie Sie ProGuard aktivieren und konfigurieren sowie das Retrace-Tool zum Dekodieren verschleierter Stapelspuren verwenden
quelle
Ich verwende gerne Log.d (TAG, ein String, oft ein String.format ()).
TAG ist immer der Klassenname
Transformiere Log.d (TAG, -> Logd (im Text deiner Klasse)
Auf diese Weise setzen Sie MainClass.debug auf false, wenn Sie bereit sind, eine Release-Version zu erstellen!
quelle
Protokolle können mit bash unter Linux und sed entfernt werden:
Funktioniert für mehrzeilige Protokolle. In dieser Lösung können Sie sicher sein, dass keine Protokolle im Produktionscode vorhanden sind.
quelle
Ich weiß, dass dies eine alte Frage ist, aber warum haben Sie nicht alle Ihre Protokollaufrufe durch etwas wie Boolean logCallWasHere = true ersetzt? // --- Rest deines Logs hier
Aus diesem Grund wissen Sie, wann Sie sie zurücksetzen möchten, und sie wirken sich nicht auf Ihren if-Anweisungsaufruf aus :)
quelle
Warum nicht einfach tun
? Es werden keine zusätzlichen Bibliotheken benötigt, keine Proguard-Regeln, die dazu neigen, das Projekt zu vermasseln, und der Java-Compiler lässt nur den Bytecode für diesen Aufruf aus, wenn Sie einen Release-Build durchführen.
quelle
Log.d("tag","msg");
, und es ist auch leicht zu vergessen, denif(BuildConfig.DEBUG)
Teil zu schreiben .Hier ist meine Lösung, wenn Sie nicht mit zusätzlichen Bibliotheken herumspielen oder Ihren Code manuell bearbeiten möchten. Ich habe dieses Jupyter-Notizbuch erstellt , um alle Java-Dateien zu durchsuchen und alle Protokollnachrichten zu kommentieren. Nicht perfekt, aber es hat den Job für mich erledigt.
quelle
auf meine Art:
1) Aktivieren Sie den Spaltenauswahlmodus (Alt + Umschalt + Einfügen).
2) Wählen Sie auf einem Log.d (TAG, "Text"); der Teil 'Log'.
3) dann Shift + Strg + Alt + J.
4) Klicken Sie auf den Pfeil nach links
5) Shift + End
6) Klicken Sie auf Löschen.
Dadurch werden alle LOG-Aufrufe in einer Java-Datei gleichzeitig entfernt.
quelle
Sie können versuchen, diese einfache konventionelle Methode zu verwenden:
Ctrl+ Shift+R
ersetzen
Mit
quelle
Einfach mit Kotlin, deklarieren Sie einfach ein paar Top-Level-Funktionen
quelle
der einfachste Weg;
verwenden
DebugLog
Alle Protokolle werden von DebugLog deaktiviert, wenn die App veröffentlicht wird.
https://github.com/MustafaFerhan/DebugLog
quelle