How to configure java.util.logging on Android?

前端 未结 5 2007
星月不相逢
星月不相逢 2020-12-04 11:49

I want to use java.util.logging on Android. I want to configure the logging system with logging.properties. But how can I tell Android using the specific configure file? For

5条回答
  •  -上瘾入骨i
    2020-12-04 11:54

    This is now an FAQ for one of my projects, hopefully more people will find this here: java.util.logging works fine on Android. Please don't use anything else in your code, logging frameworks are like a pest in the Java world.

    What is broken is the default logging handler shipped with Android, it ignores any log messages with level finer than INFO. You don't see DEBUG etc. messages.

    The reason is the call to Log.isLoggable() in AndroidHandler.java:

    https://github.com/android/platform_frameworks_base/blob/master/core/java/com/android/internal/logging/AndroidHandler.java

    Here is how you fix it:

    import android.util.Log;
    import java.util.logging.*;
    
    /**
     * Make JUL work on Android.
     */
    public class AndroidLoggingHandler extends Handler {
    
        public static void reset(Handler rootHandler) {
            Logger rootLogger = LogManager.getLogManager().getLogger("");
            Handler[] handlers = rootLogger.getHandlers();
            for (Handler handler : handlers) {
                rootLogger.removeHandler(handler);
            }
            rootLogger.addHandler(rootHandler);
        }
    
        @Override
        public void close() {
        }
    
        @Override
        public void flush() {
        }
    
        @Override
        public void publish(LogRecord record) {
            if (!super.isLoggable(record))
                return;
    
            String name = record.getLoggerName();
            int maxLength = 30;
            String tag = name.length() > maxLength ? name.substring(name.length() - maxLength) : name;
    
            try {
                int level = getAndroidLevel(record.getLevel());
                Log.println(level, tag, record.getMessage());
                if (record.getThrown() != null) {
                    Log.println(level, tag, Log.getStackTraceString(record.getThrown()));
                }
            } catch (RuntimeException e) {
                Log.e("AndroidLoggingHandler", "Error logging message.", e);
            }
        }
    
        static int getAndroidLevel(Level level) {
            int value = level.intValue();
    
            if (value >= Level.SEVERE.intValue()) {
                return Log.ERROR;
            } else if (value >= Level.WARNING.intValue()) {
                return Log.WARN;
            } else if (value >= Level.INFO.intValue()) {
                return Log.INFO;
            } else {
                return Log.DEBUG;
            }
        }
    }
    

    In the main activity/initialization code of your application:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        AndroidLoggingHandler.reset(new AndroidLoggingHandler());
        java.util.logging.Logger.getLogger("my.category").setLevel(Level.FINEST);
    ...
    

    TL;DR: Yes, you could use some magic properties, or adb shell command, or even learn how the stupid built-in logging handler's DalvikLogging.loggerNameToTag converts category names to tags (which you would have to do for those magic properties and shell commands), but why bother? Isn't logging painful enough?

提交回复
热议问题