2010-12-30 31 views
20

Quiero usar java.util.logging en Android. Quiero configurar el sistema de registro con logging.properties. ¿Pero cómo puedo decirle a Android usando el archivo de configuración específico? Por ejemplo, puse logging.properties en la raíz de la ruta de clase de la aplicación. Cómo sabe Android la ubicación de logging.properties.¿Cómo configurar java.util.logging en Android?

Gracias

Respuesta

4

En general se utiliza para iniciar sesión en android.util.Log Android. Hay algunas ventajas clave para usar ese registrador, como poder usar adb logcat para ver la salida de registro enviada a esos registros.

Puede intentar poner logging.properties en assets/ o res/raw/. Si Android no los recoge, puede usar java.util.logging.LogManager. readConfiguration(java.io.InputStream) para forzar la carga. (Puede usar las clases Resources y AssetManager para obtener el archivo como InputStream).

+0

Muchas gracias. Este enfoque lo hace bien. Ahora tengo que luchar para escribir log para sdcard. – tangjie

+0

@tangjie no estoy seguro de cuál es su objetivo final, pero consideraría almacenar los registros en su aplicación y luego enviarlos a un servidor donde tenga acceso a – philipp

47

Esto ahora es una pregunta frecuente para uno de mis proyectos, ojalá más personas lo encuentren aquí: java.util.logging funciona bien en Android. Por favor, no use nada más en su código, los marcos de registro son como una plaga en el mundo de Java.

Lo que está roto es el manejador de registro predeterminado enviado con Android, ignora cualquier mensaje de registro con nivel más fino que INFO. No ves los mensajes DEBUG, etc.

La razón es la llamada a Log.isLoggable() en AndroidHandler.java:

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

Aquí es cómo solucionarlo:

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 >= 1000) { 
      return Log.ERROR; 
     } else if (value >= 900) { 
      return Log.WARN; 
     } else if (value >= 800) { 
      return Log.INFO; 
     } else { 
      return Log.DEBUG; 
     } 
    } 
} 

En el código de actividad principal/inicialización de su aplicación:

@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: Sí, podría usar algunas propiedades mágicas o el comando adb shell, o incluso aprender cómo el estúpido controlador de registro incorporado DalvikLogging.loggerNameToTag convierte los nombres de las categorías en etiquetas (que tendría que hacer para esas propiedades mágicas y el shell) comandos), pero ¿para qué molestarse? ¿El registro no es lo suficientemente doloroso?

+1

Por ciclo de vida de Android, el mejor lugar para invocar a este controlador es onCreate() desde una subclase de Aplicación y declara esta clase en el archivo de manifiesto. Porque si por algún motivo no aparece la actividad principal (de un recurso compartido, servicio, etc.) el código aún se ejecuta. – Renascienza

1

Al menos en Android 4.3, con Handler sin cambios, si se utiliza

adb shell setprop log.tag.YOURTAG DEBUG 

Se puede ver los mensajes registrados con hasta Level.FINE en Logcat. No he encontrado una forma de registrar niveles más altos, pero eso es suficiente para mí.

1

En caso de que uno de ustedes solo quiera enrutar la salida de java.util.logging desde bibliotecas de terceros, esto puede lograrse fácilmente con SLF4J y su jul-to-slf4j bridge. Esto también funciona para las declaraciones de registro FINE y FINEST, por cierto.

Aquí está la dependencia Maven

<dependency> 
    <groupId>org.slf4j</groupId> 
    <artifactId>jul-to-slf4j</artifactId> 
    <version>${slf4j.version}</version> 
</dependency> 

Para arrancar, pon lo siguiente en su clase Application, Roboguice módulo o en otro lugar en el que se ejecuta antes de su primera declaración de registro. (La configuración de esto en assets/logging.properties parece no funcionar, por desgracia).

/* 
* add SLF4JBridgeHandler to j.u.l's root logger, should be done once 
* during the initialization phase of your application 
*/ 
SLF4JBridgeHandler.install(); 

A continuación, puede

  • configurar todas sus declaraciones de registro de assets/logback.xml (usando logback-android). Ver here para un mapeo de niveles de registro.

  • o simplemente use SLF4J-android para reenviar las instrucciones de registro a logcat. Para ello, sólo hay que poner la siguiente dependencia de la ruta de clases, no más lejos de configuración requerido:

    <dependency> 
        <groupId>org.slf4j</groupId> 
        <artifactId>slf4j-android</artifactId> 
        <version>${slf4j.version}</version> 
    </dependency> 
    

He implementado esto utilizando con éxito

<properties> 
    <slf4j.version>1.7.6</slf4j.version> 
</properties> 

Nota:

  • Lea la parte del documento jul-to-slf4j que se relaciona con rendimiento cuidadosamente!
  • Si usa LogcatAppender, asegúrese de tener en cuenta que los mensajes de registro JUL (excepto los que tienen un nivel más fino que INFO) se enrutan a logcat por android. Así que asegúrese de aplicar los filtros apropiados para evitar duplicados.
+0

Funciona, pero para mí los mensajes de registro con niveles más finos que INFO no se han mostrado con adb logcat (slf4j 1.7.21). – user905686

Cuestiones relacionadas