Log.isLoggable的使用

本文将介绍怎么打印出framework源码中的log。


在Android源码中,经常可以看到如下的log代码:

//AudioService.java

private static final String TAG = "AudioService";
protected static final boolean DEBUG_VOL = Log.isLoggable(TAG + ".VOL", Log.DEBUG);

private void adjustStreamVolume(int streamType, int direction, int flags,
        String callingPackage, String caller, int uid) {
......
    if (DEBUG_VOL) Log.d(TAG, "adjustStreamVolume() stream=" + streamType + ", dir=" + direction
                + ", flags=" + flags + ", caller=" + caller);
......
}

只有在Log.isLoggable返回值为true的时候,adjustStreamVolume()的log才能正常输出。那怎样才能让isLoggable才会返回true呢?


#定义
isLoggable()在源码中定义如下

/** 
* Checks to see whether or not a log for the specified tag is loggable at the specified level. 
* 
*  The default level of any tag is set to INFO. This means that any level above and including 
*  INFO will be logged. Before you make any calls to a logging method you should check to see 
*  if your tag should be logged. You can change the default level by setting a system property: 
*      'setprop log.tag.<YOUR_LOG_TAG> <LEVEL>' 
*  Where level is either VERBOSE, DEBUG, INFO, WARN, ERROR, ASSERT, or SUPPRESS. SUPPRESS will 
*  turn off all logging for your tag. You can also create a local.prop file that with the 
*  following in it: 
*      'log.tag.<YOUR_LOG_TAG>=<LEVEL>' 
*  and place that in /data/local.prop. 
* 
* @param tag The tag to check. 
* @param level The level to check. 
* @return Whether or not that this is allowed to be logged. 
* @throws IllegalArgumentException is thrown if the tag.length() > 23. 
*/  
public static native boolean isLoggable(String tag, int level);  

从定义可知:

  1. isLoggable默认level为Log.INFO;
  2. 只有 level >= INFO才能输出,即level >= INFO时isLoggable返回true,反之则返回false;
  3. 可以通过setprop log.tag.<YOUR_LOG_TAG> 来改变log的默认level,如adb shell setprop log.tag.AudioService.VOL D。也可以将这些属性按照log.tag.AudioService.VOL = D的形式,写入/data/local.prop中;
  4. tag的长度如果超过23个字符则会抛出IllegalArgumentException异常;

#使用方法

protected static final boolean DEBUG_VOL = Log.isLoggable(TAG + ".VOL", Log.DEBUG);

因为DEBUG是static的变量,所以当Log类被加载时,其值就已经设置好了。如果要使得isLoggable返回为true,那么setprop需要在Log类被加载前设置好,因此使用setprop之后需要重启对应的进程,framework属于每一个进程,那如何重启framework呢?可以使用:

adb shell stop  
adb shell start 

所以
方法一(机器重启后失效):
在串口中输入

setprop log.tag.AudioService.VOL D
stop
start

方法二(机器重启仍生效):
将log.tag.AudioService.VOL = D加入到/data/local.prop文件中。


后续发现加个persist关键字,重启也能生效

setprop persist.log.tag.AudioService.VOL D
您可以使用以下代码来临时修改 `log.isLoggable` 方法的返回值: ```java import java.lang.reflect.Field; import java.util.logging.Level; import java.util.logging.Logger; public class LogModifier { public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { Logger logger = Logger.getLogger("your_logger_name"); // 替换成您的日志记录器名称 Field field = Logger.class.getDeclaredField("handlers"); field.setAccessible(true); Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); modifiersField.setInt(field, field.getModifiers() & ~java.lang.reflect.Modifier.FINAL); field.set(logger, null); logger.setLevel(Level.ALL); // 设置日志记录器级别为全部记录 // 替换成您希望的日志记录级别 int logLevel = Level.INFO.intValue(); // 这里设置为 INFO 级别 Field logLevelField = Logger.class.getDeclaredField("level"); logLevelField.setAccessible(true); logLevelField.set(logger, Level.parse(Integer.toString(logLevel))); // 执行您希望的操作,例如: logger.info("临时修改日志记录级别为 INFO"); // 恢复默认的日志处理器 logger.addHandler(new java.util.logging.ConsoleHandler()); } } ``` 请替换代码中的 `your_logger_name` 为您实际使用的日志记录器名称,并设置 `logLevel` 为您希望的日志记录级别(例如:Level.INFO)。 这段代码通过反射将 `handlers` 字段置为 null,然后设置日志记录器的级别为全部记录,并执行您希望的操作。请注意,这只是一种临时修改日志记录级别的方法,不会永久更改配置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值