zoukankan      html  css  js  c++  java
  • Android 5.0 如何正确启用isLoggable(一)__使用详解

    转自:http://blog.csdn.net/yihongyuelan/article/details/46409389

    isLoggable是什么

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

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. //packages/apps/InCallUI/src/com/android/incallui/Log.java  
    2.   
    3. public static final String TAG = "InCall";  
    4. public static final boolean DEBUG = android.util.Log.isLoggable(TAG, android.util.Log.DEBUG);  
    5. public static void d(String tag, String msg) {  
    6.     if (DEBUG) {  
    7.         android.util.Log.d(TAG, delimit(tag) + msg);  
    8.     }  
    9. }  
    10.   
    11. //packages/apps/InCallUI/src/com/android/incallui/InCallPresenter.java  
    12. private InCallState startOrFinishUi(InCallState newState) {  
    13.     Log.d(this, "startOrFinishUi: " + mInCallState + " -> " + newState);  
    14.     //... ...  
    15. }  

            只有在android.util.Log.isLoggable返回值为true的时候,startOrFinishUi的log才能正常输出。那什么时候isLoggable才会返回true呢?如何简单快捷的开启isLoggable并使log正常输出呢?

    本文来自http://blog.csdn.NET/yihongyuelan 转载请务必注明出处

    isLoggable定义

            什么是isLoggable?isLoggable是android.util.Log提供的方法,用于检查指定TAG的level,是否满足输出条件,如满足则返回true反之则返回false。isLoggable在源码中的定义如下:

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. /** 
    2.  * Checks to see whether or not a log for the specified tag is loggable at the specified level. 
    3.  * 
    4.  *  The default level of any tag is set to INFO. This means that any level above and including 
    5.  *  INFO will be logged. Before you make any calls to a logging method you should check to see 
    6.  *  if your tag should be logged. You can change the default level by setting a system property: 
    7.  *      'setprop log.tag.<YOUR_LOG_TAG> <LEVEL>' 
    8.  *  Where level is either VERBOSE, DEBUG, INFO, WARN, ERROR, ASSERT, or SUPPRESS. SUPPRESS will 
    9.  *  turn off all logging for your tag. You can also create a local.prop file that with the 
    10.  *  following in it: 
    11.  *      'log.tag.<YOUR_LOG_TAG>=<LEVEL>' 
    12.  *  and place that in /data/local.prop. 
    13.  * 
    14.  * @param tag The tag to check. 
    15.  * @param level The level to check. 
    16.  * @return Whether or not that this is allowed to be logged. 
    17.  * @throws IllegalArgumentException is thrown if the tag.length() > 23. 
    18.  */  
    19. public static native boolean isLoggable(String tag, int level);  
    从以上定义中可以知道:

    1. isLoggable默认level为android.util.Log.INFO;

    2. 只有 level >= INFO才能输出,即level >= INFO时isLoggable返回true,反之则返回false;

    3. 可以通过setprop log.tag.<YOUR_LOG_TAG> <LEVEL>来改变log的默认level,如adb shell setprop log.tag.InCall D。也可以将这些属性按照log.tag.InCall=D的形式,写入/data/local.prop中;

    4. tag的长度如果超过23个字符则会抛出IllegalArgumentException异常;

            在android.util.Log类中定义了Log的6种Level,如下:

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. /** 
    2.  * Priority constant for the println method; use Log.v. 
    3.  */  
    4. public static final int VERBOSE = 2;  
    5.   
    6. /** 
    7.  * Priority constant for the println method; use Log.d. 
    8.  */  
    9. public static final int DEBUG = 3;  
    10.   
    11. /** 
    12.  * Priority constant for the println method; use Log.i. 
    13.  */  
    14. public static final int INFO = 4;  
    15.   
    16. /** 
    17.  * Priority constant for the println method; use Log.w. 
    18.  */  
    19. public static final int WARN = 5;  
    20.   
    21. /** 
    22.  * Priority constant for the println method; use Log.e. 
    23.  */  
    24. public static final int ERROR = 6;  
    25.   
    26. /** 
    27.  * Priority constant for the println method. 
    28.  */  
    29. public static final int ASSERT = 7;  
            6种level对应不同等级的log,level值的大小随着log权重的升高而增大。

    isLoggable使能方法

            前文提到,在自定义的Log类中通常使用isLoggable来判断是否输出log,如代码:

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. //packages/apps/InCallUI/src/com/android/incallui/Log.java  
    2.   
    3. public static final String TAG = "InCall";  
    4. public static final boolean DEBUG = android.util.Log.isLoggable(TAG, android.util.Log.DEBUG);  
    5. public static void d(String tag, String msg) {  
    6.     if (DEBUG) {  
    7.         android.util.Log.d(TAG, delimit(tag) + msg);  
    8.     }  
    9. }  
    10.   
    11. //packages/apps/InCallUI/src/com/android/incallui/InCallPresenter.java  
    12. private InCallState startOrFinishUi(InCallState newState) {  
    13.     Log.d(this, "startOrFinishUi: " + mInCallState + " -> " + newState);  
    14.     //... ...  
    15. }  
    如果想要输出startOrFinishUi()方法中的log,可以采用以下方式:

    ①. 将Log.d修改为android.util.Log.d;使用android.util.Log类取代InCallUI自定义的Log类,重新编译系统APP并push到手机中即可;

    ②. 修改com.android.incallui.Log中的DEBUG限制;将DEBUG的值直接置为true,或者注释掉if(DEBUG)。也可以将isLoggable(TAG, android.util.Log.DEBUG)中的android.util.Log.DEBUG修改为android.util.Log.INFO,即将log的level增大,从而使isLoggable()返回true并使得DEBUG的值为true;

    ③. 设置log.tag.InCall的属性值;通过adb shell setprop log.tag.InCall D,或者将"log.tag.InCall=D"写入/data/local.prop中(不包含引号,如local.prop不存在则需自行创建,权限设为644)。根据定义中的描述,设置属性值需要在方法被调用之前,因此需要重启InCallUI进程。通过修改属性值的方法,从而使得isLoggable()的返回值为true,从而使得DEBUG的值为true。

            第一种方式直接修改,简单粗暴,但若修改点较多则比较麻烦,且需要重新编译代码。

            第二种方式修改点统一,但和第一种一样,也需要重新编译。

            第三种使用属性的方式使得isLoggable返回true,这种方式比较方便,同时适用于user/userdebug/eng各个版本的设备。这种方式需要在方法被调用前设置log.tag.InCall,通过代码:

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. public static final boolean DEBUG = android.util.Log.isLoggable(TAG, android.util.Log.DEBUG);  
    可以知道,因为DEBUG是static的变量,所以当Log类被加载时,其值就已经设置好了。如果要使得isLoggable返回为true,那么setprop需要在Log类被加载前设置好,因此使用setprop之后需要重启对应的进程,如这里的com.android.incallui。但在framework中有些代码也使用isLoggable,framework属于每一个进程,如何重启framework呢?可以使用:
    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. adb shell stop  
    2. adb shell start  
    adb shell stop会杀掉zygote进程以及所有由zygote孵化而来的子进程。adb shell start则会重启zygote进程,再由zygote进程启动其它Android核心进程。当zygote重新启动时,会重新加载framework相关资源,而此时属性已经设置。这种方法虽然简单,但当设备重启后,所有设置的log.tag.<TAG>都会失效,若想再次启用则需重新设置。

            也可以通过将log.tag.InCall=D加入到/data/local.prop文件中,这种方式与setprop类似,都是设置属性值,但这种方式的好处是,设置之后重启设备该log.tag.InCall依然有效。不过因为/data目录的权限控制,只有userdebug/eng版本才可以修改/data/local.prop文件。[/system/core/init/property_service.c] load_override_properties()函数中有/data/local.prop的使能方法。

    小结

            isLoggable的使能方法如下图所示:

    图 1 isLoggable使能方案对比

            如果只是想启用某个进程的isLoggable方法,通过setprop设置属性是不错的选择,同事,想要重启设备后依然有效则需要设置/data/local.prop,不过/data目录只有在userdebug/eng版本中才可以写入。那如果想在user版中设置log.tag属性并在重启后依然有效,可以采取以下方法:

    1. 获取user版系统的root权限;

    2. 将log.tag.InCall=D追加到/system/build.prop文件中;

    3. adb reboot重启设备;

            以上方案大家可能会疑惑,既然user版获取到了root权限,为什么不直接修改/data/local.prop呢?这是因为如果是user版,则ro.debuggable=0,所以系统启动时不会读取/data/local.prop文件,并最终导致设置log.tag属性不会生效。详细原理将在下一篇文章《Android 5.0 如何正确启用isLoggable(一)__原理分析》中探讨。

     
  • 相关阅读:
    63. Unique Paths II(中等, 能独立做出来的DP类第二个题^^)
    3.2 2-dim Vector Initialization
    62. Unique Paths(中等,我自己解出的第一道 DP 题^^)
    漫画:什么是动态规划?
    120. Triangle(中等)
    128. Longest Consecutive Sequence
    80. Remove Duplicates from Sorted Array II
    81. Search in Rotated Sorted Array II (中等)
    59. Spiral Matrix II(中等,同54题)
    spring cloud
  • 原文地址:https://www.cnblogs.com/dirt2/p/6044129.html
Copyright © 2011-2022 走看看