isLoggable是什么

在Android源代码中,我们常常能够看到例如以下代码:

//packages/apps/InCallUI/src/com/android/incallui/Log.java

public static final String TAG = "InCall";
public static final boolean DEBUG = android.util.Log.isLoggable(TAG, android.util.Log.DEBUG);
public static void d(String tag, String msg) {
if (DEBUG) {
android.util.Log.d(TAG, delimit(tag) + msg);
}
} //packages/apps/InCallUI/src/com/android/incallui/InCallPresenter.java
private InCallState startOrFinishUi(InCallState newState) {
Log.d(this, "startOrFinishUi: " + mInCallState + " -> " + newState);
//... ...
}

仅仅有在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在源代码中的定义例如以下:

    /**
* 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为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。例如以下:

    /**
* Priority constant for the println method; use Log.v.
*/
public static final int VERBOSE = 2; /**
* Priority constant for the println method; use Log.d.
*/
public static final int DEBUG = 3; /**
* Priority constant for the println method; use Log.i.
*/
public static final int INFO = 4; /**
* Priority constant for the println method; use Log.w.
*/
public static final int WARN = 5; /**
* Priority constant for the println method; use Log.e.
*/
public static final int ERROR = 6; /**
* Priority constant for the println method.
*/
public static final int ASSERT = 7;

6种level相应不同等级的log。level值的大小随着log权重的升高而增大。

isLoggable使能方法

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

//packages/apps/InCallUI/src/com/android/incallui/Log.java

public static final String TAG = "InCall";
public static final boolean DEBUG = android.util.Log.isLoggable(TAG, android.util.Log.DEBUG);
public static void d(String tag, String msg) {
if (DEBUG) {
android.util.Log.d(TAG, delimit(tag) + msg);
}
} //packages/apps/InCallUI/src/com/android/incallui/InCallPresenter.java
private InCallState startOrFinishUi(InCallState newState) {
Log.d(this, "startOrFinishUi: " + mInCallState + " -> " + newState);
//... ...
}

假设想要输出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,通过代码:

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呢?能够使用:

adb shell stop
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文件。

小结

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(一)__原理分析》中探讨。

Android 5.0 怎样正确启用isLoggable(一)__使用具体解释的更多相关文章

  1. Android 5.0 怎样正确启用isLoggable(二)__原理分析

    前置文章 <Android 5.0 怎样正确启用isLoggable(一)__使用具体解释> 概要 在上文<Android 5.0 怎样正确启用isLoggable(一)__使用具体 ...

  2. Android 5.0 如何正确启用isLoggable(一)__使用详解

    转自:http://blog.csdn.net/yihongyuelan/article/details/46409389 isLoggable是什么 在Android源码中,我们经常可以看到如下代码 ...

  3. Android5.0如何正确启用isLoggable(二) 理分析

    转自:http://www.it165.net/pro/html/201506/43374.html 概要 在上文<Android 5.0 如何正确启用isLoggable(一)__使用详解&g ...

  4. Android 4.0以后正确的获取外部sd卡存储目录

    刚解决这个棘手的问题 找了很久,随笔记下. 网上搜索 android 获取外部sd卡存储目录 普遍都是: 1) Environment.getExternalStorageDirectory() 这个 ...

  5. 【译】Android 6.0 Changes (机翻加轻微人工校对)

    Android 6.0 Changes In this document Runtime Permissions Doze and App Standby Apache HTTP Client Rem ...

  6. Android 6.0 新功能及主要 API 变更

    运行时权限 这个版本中引入了新的权限模型,现在用户可以在运行时直接管理应用程序的权限.这个模型基于用户对权限控制的更多可见性,同时为应用程序的开发者提供更流畅的应用安装和自动升级.用户可以为已安装的每 ...

  7. Android 6.0 Changes

    原文链接:http://developer.android.com/about/versions/marshmallow/android-6.0-changes.html 伴随着新特性和功能,Andr ...

  8. 还在期待安卓9.0吗?Android 10.0要来了

    目前,美国 Google公司的 AndroidP (安卓9.0),已经正式全面推出有几个多月了.众多手机品牌厂商也都在积极的进行更新适配 Android 9.0 系统(修改UI界面也算是二次开发,嗯) ...

  9. Android 9.0更新

    北京时间2018年8月7日上午,Google 发布了 Android 9.0 操作系统.并宣布系统版本 Android P 被正式命名为代号"Pie". Android 9.0 利 ...

随机推荐

  1. 追忆似水流年sed

    sed是一种非交互式的流编辑器,默认情况下并不会修改源文件内容,只是把命令的结果输出处理单位:行功能:查找替换.添加.插入.删除适用场景:常规编辑器难以胜任的文本:大文件(几百兆):有规律的文本修改操 ...

  2. 关于xargs cp中,如何确定拷贝的源和目的

    来源: http://bbs.chinaunix.net/thread-1022095-1-1.html Seker: find . -name "*" |xargs cp ??? ...

  3. urllib2模块、cookielib模块

    urllib2模块 urllib模块和urllib模块类似,用来打开URL并从中获取数据.与urllib模块不同的是,urllib模块不仅可以使用urlopen() 函数还可以自定义Opener来访问 ...

  4. 文件包含漏洞检测工具fimap

    文件包含漏洞检测工具fimap   在Web应用中,文件包含漏洞(FI)是常见的漏洞.根据包含的文件不同,它分为本地文件包含漏洞(LFI)和远程文件包含漏洞(RFL).利用该漏洞,安全人员可以获取服务 ...

  5. Sass和Compass的安装

    Sass和Compass都是基于Ruby编程语言的命令行工具.要使用它们,你首先需要在电脑中安装Ruby,并对电脑的命令行操作有一个基本的理解.Sass和Compass可以安装在Windows.Mac ...

  6. [BZOJ 1058] 报表统计

    Link: BZOJ 1058 传送门 Solution: 为了这道题今天下午一直都在和常数大战…… 1.对于询问1,我们记录每个数末位置的数$T[i]$和初始位置$S[i]$ 用平衡树维护所有差值, ...

  7. 【枚举】XVII Open Cup named after E.V. Pankratiev Stage 4: Grand Prix of SPb, Sunday, Octorber 9, 2016 Problem D. Cutting Potatoes

    题意:有n个土豆,每个有体积V(i),你可以将每个土豆等分为不超过K份,问你最大块和最小块比值最小为多少. 直接枚举切法,只有n*K种,然后保证其为最大块,去算其他块的切法,即让其他块切得尽可能大即可 ...

  8. 【差分约束系统】【最短路】【spfa】CDOJ1646 穷且益坚, 不坠青云之志。

    求一个有n个元素的数列,满足任意连续p个数的和不小于s, 任意连续q个数的和不大于t. 令sum[i]表示前i项的和(0<=i<=n,sum[0]=0) 那么题目的条件可转化为: sum[ ...

  9. B 君的第二题 (hongkong)

    B 君的第二题 (hongkong) 题目大意: 一个长度为\(n(n\le2\times10^5)\)的数组,给定一个数\(k(k\le40)\).用\(a[i][j]\)表示该数组\(i\)次前缀 ...

  10. Problem H: 零起点学算法109——单数变复数

    #include <stdio.h> #include<string.h> int main(void) { int n; ]; scanf("%d",&a ...