Jak włączyć / wyłączyć poziomy logów w systemie Android?

Mam na przykład wiele instrukcji logowania do debugowania.

Log.v(TAG, "Message here");
Log.w(TAG, " WARNING HERE");

Podczas wdrażania tej aplikacji na telefonie urządzenia chcę wyłączyć rejestrowanie, z którego mogę włączyć / wyłączyć rejestrowanie.

Author: Frank Kusters, 2010-01-07

16 answers

Powszechnym sposobem jest utworzenie int o nazwie loglevel i zdefiniowanie jego poziomu debugowania na podstawie loglevel.

public static int LOGLEVEL = 2;
public static boolean ERROR = LOGLEVEL > 0;
public static boolean WARN = LOGLEVEL > 1;
...
public static boolean VERBOSE = LOGLEVEL > 4;

    if (VERBOSE) Log.v(TAG, "Message here"); // Won't be shown
    if (WARN) Log.w(TAG, "WARNING HERE");    // Still goes through

Później możesz po prostu zmienić LOGLEVEL dla wszystkich poziomów wyjściowych debugowania.

 79
Author: Cytown,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-23 18:49:13

Dokumentacja Androida mówi o poziomach logów :

Verbose nigdy nie powinien być kompilowany do aplikacji, z wyjątkiem okresu programowania. Dzienniki debugowania są kompilowane, ale usuwane w czasie wykonywania. Dzienniki błędów, ostrzeżeń i informacji są zawsze przechowywane.

Więc możesz rozważyć usunięcie logowania wyrażonych wyrażeń, ewentualnie za pomocą ProGuard, jak sugerowano w innej odpowiedzi .

Zgodnie z dokumentacją, ty może skonfigurować logowanie na urządzeniu deweloperskim przy użyciu właściwości systemu. Właściwością do Ustawienia jest log.tag.<YourTag> i należy ją ustawić na jedną z następujących wartości: VERBOSE, DEBUG, INFO, WARN, ERROR, ASSERT, lub SUPPRESS. więcej informacji na ten temat można znaleźć w dokumentacji metody isLoggable().

Właściwości można tymczasowo ustawić za pomocą polecenia setprop. Na przykład:

C:\android>adb shell setprop log.tag.MyAppTag WARN
C:\android>adb shell getprop log.tag.MyAppTag
WARN

Alternatywnie można je określić w pliku ' / data / local.prop " as następuje:

log.tag.MyAppTag=WARN
[[14]}późniejsze wersje Androida wydają się wymagać tego /data / local.prop be read only . Ten plik jest odczytywany podczas rozruchu, więc musisz go ponownie uruchomić po aktualizacji. Jeśli {[12] } jest zapisywalny na świecie, prawdopodobnie zostanie zignorowany.

Wreszcie, można ustawić je programowo za pomocą System.setProperty() metoda .

 188
Author: Dave Webb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:08

Najprostszym sposobem jest prawdopodobnie uruchomienie skompilowanego JAR przez ProGuard przed wdrożeniem, z konfiguracją w stylu:

-assumenosideeffects class android.util.Log {
    public static int v(...);
}

To - poza wszystkimi innymi optymalizacjami ProGuard-usunie wszelkie szczegółowe instrukcje dziennika bezpośrednio z kodu bajtowego.

 88
Author: Christopher Orr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-07 08:10:06

Wybrałem prostą trasę-stworzenie klasy wrapper, która również korzysta z list zmiennych parametrów.

 public class Log{
        public static int LEVEL = android.util.Log.WARN;


    static public void d(String tag, String msgFormat, Object...args)
    {
        if (LEVEL<=android.util.Log.DEBUG)
        {
            android.util.Log.d(tag, String.format(msgFormat, args));
        }
    }

    static public void d(String tag, Throwable t, String msgFormat, Object...args)
    {
        if (LEVEL<=android.util.Log.DEBUG)
        {
            android.util.Log.d(tag, String.format(msgFormat, args), t);
        }
    }

    //...other level logging functions snipped
 18
Author: kdahlhaus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-16 08:21:21

Lepszym sposobem jest użycie API SLF4J + część jego implementacji.

Dla aplikacji Android można użyć następujących:

  1. Android Logger jest lekką, ale łatwą do skonfigurowania implementacją SLF4J (
  2. LOGBack jest najpotężniejszą i najbardziej zoptymalizowaną implementacją, ale jej rozmiar to około 1 Mb.
  3. Każdy inny według Twojego gustu: slf4j-android, slf4android.
 10
Author: Fortess Nsk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-16 17:41:13

Powinieneś użyć

    if (Log.isLoggable(TAG, Log.VERBOSE)) {
        Log.v(TAG, "my log message");
    }
 8
Author: Diego Torres Milano,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-07 14:32:08

Usunięcie logowania za pomocą proguard (zobacz odpowiedź od @Christopher ) było łatwe i szybkie, ale spowodowało, że ślady stosu z produkcji nie pasowały do źródła, jeśli w pliku było logowanie debugowania.

Zamiast tego, oto technika, która wykorzystuje różne poziomy logowania w rozwoju vs produkcji, zakładając, że proguard jest używany tylko w produkcji. Rozpoznaje produkcję sprawdzając, czy proguard zmienił nazwę danej klasy (w przykładzie używam "com.foo.Bar" -- zamieniłbyś to z pełną nazwą klasy, którą znasz, zostanie przemianowana przez proguard).

Ta technika wykorzystuje logowanie commons.

private void initLogging() {
    Level level = Level.WARNING;
    try {
        // in production, the shrinker/obfuscator proguard will change the
        // name of this class (and many others) so in development, this
        // class WILL exist as named, and we will have debug level
        Class.forName("com.foo.Bar");
        level = Level.FINE;
    } catch (Throwable t) {
        // no problem, we are in production mode
    }
    Handler[] handlers = Logger.getLogger("").getHandlers();
    for (Handler handler : handlers) {
        Log.d("log init", "handler: " + handler.getClass().getName());
        handler.setLevel(level);
    }
}
 4
Author: larham1,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-30 16:44:01

Log4j lub slf4j mogą być również używane jako frameworki logowania w Androidzie wraz z logcat. Zobacz projekt android-logging-log4j lub obsługa log4j w Androidzie

 3
Author: Rolf Kulemann,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:17

Istnieje mały zamiennik standardowej klasy dziennika Androida- https://github.com/zserge/log

W zasadzie wszystko, co musisz zrobić, to zastąpić import z android.util.Log na trikita.log.Log. Następnie w swoim Application.onCreate() lub w statycznym sprawdzeniu initalizera dla BuilConfig.DEBUG lub innej flagi i użyj Log.level(Log.D) lub Log.level(Log.E), aby zmienić minimalny poziom dziennika. Możesz użyć Log.useLog(false), aby w ogóle wyłączyć logowanie.

 3
Author: Eric Weyant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-14 07:47:56

Być może możesz zobaczyć tę klasę rozszerzenia dziennika: https://github.com/dbauduin/Android-Tools/tree/master/logs .

Pozwala na precyzyjną kontrolę logów. Można na przykład wyłączyć wszystkie dzienniki lub tylko dzienniki niektórych pakietów lub klas.

Ponadto dodaje kilka przydatnych funkcjonalności(na przykład nie musisz podawać znacznika dla każdego dziennika).

 2
Author: Donkey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-15 14:58:21

Stworzyłem narzędzie / Wrapper, które rozwiązuje ten problem + inne typowe problemy związane z logowaniem.

Narzędzie do debugowania z następującymi funkcjami:

  • typowe funkcje dostarczane przez klasę Log owinięte wokół LogMode s.
  • Method Entry-Exit logs: można wyłączyć za pomocą przełącznika
  • selektywne debugowanie: debugowanie specyficznych klas.
  • method Execution-time Measurement: pomiar czasu wykonania dla poszczególnych metod, jak również czasu zbiorowego wydane na wszystkie metody zajęć.

Jak Używać?

  • Dołącz klasę do swojego projektu.
  • Użyj go tak, jak używasz Androida.util.Zaloguj metody, na początek.
  • Użyj funkcji dzienniki wejścia-Wyjścia, umieszczając wywołania metod entry_log()-exit_log() na początku i końcu metod w aplikacji.

Starałem się, aby dokumentacja była samowystarczalna.

Sugestie dotyczące poprawy tego narzędzia są mile widziane.

Free To użyj / Udostępnij.

Pobierz go z GitHub.

 2
Author: Vinay Wadhwa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-23 07:35:32

Oto bardziej złożone rozwiązanie. Otrzymasz pełny ślad stosu i metoda toString () zostanie wywołana tylko w razie potrzeby (Performance). Atrybut BuildConfig.DEBUG będzie fałszywy w trybie produkcyjnym, więc wszystkie dzienniki śledzenia i debugowania zostaną usunięte. Kompilator hot spot ma szansę usunąć wywołania, ponieważ wyłącza końcowe właściwości statyczne.

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import android.util.Log;

public class Logger {

    public enum Level {
        error, warn, info, debug, trace
    }

    private static final String DEFAULT_TAG = "Project";

    private static final Level CURRENT_LEVEL = BuildConfig.DEBUG ? Level.trace : Level.info;

    private static boolean isEnabled(Level l) {
        return CURRENT_LEVEL.compareTo(l) >= 0;
    }

    static {
        Log.i(DEFAULT_TAG, "log level: " + CURRENT_LEVEL.name());
    }

    private String classname = DEFAULT_TAG;

    public void setClassName(Class<?> c) {
        classname = c.getSimpleName();
    }

    public String getClassname() {
        return classname;
    }

    public boolean isError() {
        return isEnabled(Level.error);
    }

    public boolean isWarn() {
        return isEnabled(Level.warn);
    }

    public boolean isInfo() {
        return isEnabled(Level.info);
    }

    public boolean isDebug() {
        return isEnabled(Level.debug);
    }

    public boolean isTrace() {
        return isEnabled(Level.trace);
    }

    public void error(Object... args) {
        if (isError()) Log.e(buildTag(), build(args));
    }

    public void warn(Object... args) {
        if (isWarn()) Log.w(buildTag(), build(args));
    }

    public void info(Object... args) {
        if (isInfo()) Log.i(buildTag(), build(args));
    }

    public void debug(Object... args) {
        if (isDebug()) Log.d(buildTag(), build(args));
    }

    public void trace(Object... args) {
        if (isTrace()) Log.v(buildTag(), build(args));
    }

    public void error(String msg, Throwable t) {
        if (isError()) error(buildTag(), msg, stackToString(t));
    }

    public void warn(String msg, Throwable t) {
        if (isWarn()) warn(buildTag(), msg, stackToString(t));
    }

    public void info(String msg, Throwable t) {
        if (isInfo()) info(buildTag(), msg, stackToString(t));
    }

    public void debug(String msg, Throwable t) {
        if (isDebug()) debug(buildTag(), msg, stackToString(t));
    }

    public void trace(String msg, Throwable t) {
        if (isTrace()) trace(buildTag(), msg, stackToString(t));
    }

    private String buildTag() {
        String tag ;
        if (BuildConfig.DEBUG) {
            StringBuilder b = new StringBuilder(20);
            b.append(getClassname());

            StackTraceElement stackEntry = Thread.currentThread().getStackTrace()[4];
            if (stackEntry != null) {
                b.append('.');
                b.append(stackEntry.getMethodName());
                b.append(':');
                b.append(stackEntry.getLineNumber());
            }
            tag = b.toString();
        } else {
            tag = DEFAULT_TAG;
        }
    }

    private String build(Object... args) {
        if (args == null) {
            return "null";
        } else {
            StringBuilder b = new StringBuilder(args.length * 10);
            for (Object arg : args) {
                if (arg == null) {
                    b.append("null");
                } else {
                    b.append(arg);
                }
            }
            return b.toString();
        }
    }

    private String stackToString(Throwable t) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream(500);
        baos.toString();
        t.printStackTrace(new PrintStream(baos));
        return baos.toString();
    }
}

Użyj TAK:

Loggor log = new Logger();
Map foo = ...
List bar = ...
log.error("Foo:", foo, "bar:", bar);
// bad example (avoid something like this)
// log.error("Foo:" + " foo.toString() + "bar:" + bar); 
 2
Author: Andreas Mager,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-16 13:58:57

W bardzo prostym scenariuszu logowania, gdzie dosłownie próbujesz napisać do konsoli podczas programowania w celu debugowania, najłatwiej jest po prostu wyszukać i zastąpić przed kompilacją produkcyjną i skomentować wszystkie połączenia do logu lub systemu.Wynocha.println.

Na przykład, zakładając, że nie użyłeś " Log."gdziekolwiek poza wywołaniem do logowania.d lub Log.e, etc, można po prostu zrobić znaleźć i zastąpić w całym rozwiązaniu, aby zastąpić " Log."z" / / Log."do skomentuj wszystkie połączenia logowania, lub w moim przypadku po prostu używam systemu.Wynocha.println wszędzie, więc przed rozpoczęciem produkcji po prostu wykonam pełne wyszukiwanie i zamienię na "System.Wynocha.println "i zastąp przez" / / System.Wynocha.println".

Wiem, że to nie jest idealne, i byłoby miło, gdyby możliwość znalezienia i komentowania połączeń do logu i systemu.Wynocha.println zostały wbudowane w Eclipse, ale do tego czasu najprostszym i najszybszym i najlepszym sposobem na to jest skomentowanie przez wyszukiwarkę i zastąp. Jeśli to zrobisz, nie musisz się martwić o niedopasowanie numerów linii śledzenia stosu, ponieważ edytujesz kod źródłowy i nie dodajesz żadnych kosztów ogólnych, sprawdzając konfigurację poziomu dziennika itp.

 1
Author: Jim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-28 19:54:49

W moich aplikacjach mam klasę, która zawija klasę Log, która ma statyczny Boolean var o nazwie "state". W całym kodzie sprawdzam wartość zmiennej "state" używając statycznej metody przed zapisem do dziennika. Następnie mam statyczną metodę, aby ustawić zmienną "state", która zapewnia, że wartość jest wspólna dla wszystkich instancji utworzonych przez aplikację. Oznacza to, że mogę włączyć lub wyłączyć wszystkie Logowanie dla aplikacji w jednym połączeniu - nawet gdy aplikacja jest uruchomiona. Przydatne do połączeń wsparcia... Informatyka oznacza to, że musisz trzymać się swoich broni podczas debugowania i nie cofać się do używania standardowej klasy dziennika...

Jest również przydatne (wygodne), że Java interpretuje zmienną logiczną jako false, jeśli nie ma przypisanej wartości, co oznacza, że można ją pozostawić jako false, dopóki nie trzeba włączyć logowania: -)

 1
Author: Darnst,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-19 15:25:34

Możemy użyć klasy Log w naszym lokalnym komponencie i zdefiniować metody jako v/i/e / d. Na podstawie potrzeby możemy zadzwonić dalej.
przykład przedstawiono poniżej.

    public class Log{
        private static boolean TAG = false;
        public static void d(String enable_tag, String message,Object...args){
            if(TAG)
            android.util.Log.d(enable_tag, message+args);
        }
        public static void e(String enable_tag, String message,Object...args){
            if(TAG)
            android.util.Log.e(enable_tag, message+args);
        }
        public static void v(String enable_tag, String message,Object...args){
            if(TAG)
            android.util.Log.v(enable_tag, message+args);
        }
    }
    if we do not need any print(s), at-all make TAG as false for all else 
    remove the check for type of Log (say Log.d).
    as 
    public static void i(String enable_tag, String message,Object...args){
    //      if(TAG)
            android.util.Log.i(enable_tag, message+args);
    }

Tutaj wiadomość jest dla string i {[3] } jest wartością, którą chcesz wydrukować.

 1
Author: Gyanendra Tripathi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-06 13:05:22

Dla mnie często przydaje się możliwość ustawienia różnych poziomów logów dla każdego tagu.

Używam tej bardzo prostej klasy wrapper:

public class Log2 {

    public enum LogLevels {
        VERBOSE(android.util.Log.VERBOSE), DEBUG(android.util.Log.DEBUG), INFO(android.util.Log.INFO), WARN(
                android.util.Log.WARN), ERROR(android.util.Log.ERROR);

        int level;

        private LogLevels(int logLevel) {
            level = logLevel;
        }

        public int getLevel() {
            return level;
        }
    };

    static private HashMap<String, Integer> logLevels = new HashMap<String, Integer>();

    public static void setLogLevel(String tag, LogLevels level) {
        logLevels.put(tag, level.getLevel());
    }

    public static int v(String tag, String msg) {
        return Log2.v(tag, msg, null);
    }

    public static int v(String tag, String msg, Throwable tr) {
        if (logLevels.containsKey(tag)) {
            if (logLevels.get(tag) > android.util.Log.VERBOSE) {
                return -1;
            }
        }
        return Log.v(tag, msg, tr);
    }

    public static int d(String tag, String msg) {
        return Log2.d(tag, msg, null);
    }

    public static int d(String tag, String msg, Throwable tr) {
        if (logLevels.containsKey(tag)) {
            if (logLevels.get(tag) > android.util.Log.DEBUG) {
                return -1;
            }
        }
        return Log.d(tag, msg);
    }

    public static int i(String tag, String msg) {
        return Log2.i(tag, msg, null);
    }

    public static int i(String tag, String msg, Throwable tr) {
        if (logLevels.containsKey(tag)) {
            if (logLevels.get(tag) > android.util.Log.INFO) {
                return -1;
            }
        }
        return Log.i(tag, msg);
    }

    public static int w(String tag, String msg) {
        return Log2.w(tag, msg, null);
    }

    public static int w(String tag, String msg, Throwable tr) {
        if (logLevels.containsKey(tag)) {
            if (logLevels.get(tag) > android.util.Log.WARN) {
                return -1;
            }
        }
        return Log.w(tag, msg, tr);
    }

    public static int e(String tag, String msg) {
        return Log2.e(tag, msg, null);
    }

    public static int e(String tag, String msg, Throwable tr) {
        if (logLevels.containsKey(tag)) {
            if (logLevels.get(tag) > android.util.Log.ERROR) {
                return -1;
            }
        }
        return Log.e(tag, msg, tr);
    }

}

Teraz po prostu ustaw poziom dziennika dla tagu na początku każdej klasy:

Log2.setLogLevel(TAG, LogLevels.INFO);
 0
Author: Jack Miller,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-02 14:31:22