求教怎么在android log.d 不输出的Logcat中输出日志

1984人阅读
Android学习(3)
Android中LogCat输出日志的自定义
没有耐心的客官可以直接看这里,里面有源码和使用方法。
一个好的log工具,必然得尽可能的打印出详细的信息,所以必须秉承着不管有的没的,一切都要为客户准备好的原则。而通常来说我们是使用Thread.currentThread().getStackTrace()这个方法来获取我们所需要的信息。
Thread.currentThread().getStackTrace()是什么鬼?来让我们运行一下。
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace()
for (StackTraceElement stackTraceElement:stackTraceElements){
System.out.println("stack " + stackTraceElement)
I/System.out: stack dalvik.system.VMStack.getThreadStackTrace(Native Method)
I/System.out: stack java.lang.Thread.getStackTrace(Thread.java:579)
I/System.out: stack com.sky.yunlv.yunlv_android.MainActivity.onCreate(MainActivity.java:120)
I/System.out: stack android.app.Activity.performCreate(Activity.java:5133)
I/System.out: stack android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
I/System.out: stack android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2175)
I/System.out: stack android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261)
I/System.out: stack android.app.ActivityThread.access$600(ActivityThread.java:141)
I/System.out: stack android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
I/System.out: stack android.os.Handler.dispatchMessage(Handler.java:99)
I/System.out: stack android.os.Looper.loop(Looper.java:137)
I/System.out: stack android.app.ActivityThread.main(ActivityThread.java:5103)
I/System.out: stack java.lang.reflect.Method.invokeNative(Native Method)
I/System.out: stack java.lang.reflect.Method.invoke(Method.java:525)
I/System.out: stack com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
I/System.out: stack com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
I/System.out: stack dalvik.system.NativeStart.main(Native Method)
Thread.currentThread().getStackTrace()可以看到我们调用这个方法可以获得StackTraceElement的数组,把数组打印出来就是上面的这些信息。
这时候你可能心里想的是,这又是什么鬼的什么鬼?别急,现在我们想一个问题,在一堆StackTraceElement数组中,我们有没有发现什么可以利用的东西呢?这时根据上图我们可以发现,这第三个StackTraceElement东东貌似打印出了一些不得了的东西,它追踪到了我们调用该方法的类中的具体方法里面,而里面的详细信息正是我们所需要的。哈哈哈,皇天不负有心人,打印了那么多终于找到了。
现在又有一个问题,是不是在任何情况下我们都选择第三个?抱着这个想法,我写了一个类,方法如下:
public class CommUtil {
public static StackTraceElement[] getStack(){
return Thread.currentThread().getStackTrace();
然后再调用它:
StackTraceElement[] stackTraceElements = CommUtil.get();
for (StackTraceElement stackTraceElement:stackTraceElements){
System.out.println("stack " + stackTraceElement);
再看看打印数据。
I/System.out: stack dalvik.system.VMStack.getThreadStackTrace(Native Method)
I/System.out: stack java.lang.Thread.getStackTrace(Thread.java:579)
I/System.out: stack com.sky.yunlv.yunlv_android.util.CommUtil.getStack(CommUtil.java:10)
I/System.out: stack com.sky.yunlv.yunlv_android.MainActivity.onCreate(MainActivity.java:121)
I/System.out: stack android.app.Activity.performCreate(Activity.java:5133)
噢买噶,显然可以发现打印的StackTraceElement信息又变了,看来不是一直在第三个的。靠,但是生活得继续,我们得找规律。
如果你慢慢,再慢慢的看,可以看到它把我们所调用Thread.currentThread().getStackTrace()所经过的类以及方法全都打印出来了,而我们实际所需的又往下被挤了一位。从这里我们可以得出,如果想要获得我们需要的那个StackTraceElement,那么就得找出准确的位置,确切的说要在合适的位置调用获取StackTraceElement的方法。
就是直接返回的Thread.currentThread().getStackTrace()[4],由此可以知道期间一定经过两次调用。
总之,简单的说就像是快递查询可以知道你的包裹经过了哪些地方,待了多久一样,Thread.currentThread().getStackTrace()是对你的方法进行追踪的,这样所有调用它的地方都能查询到。
现在我们再来看看当获得到了需要的StackTraceElement后,我们能从中获得什么信息。
* A representation of a single stack frame. Arrays of {@code StackTraceElement}
* are stored in {@link Throwable} objects to represent the whole state of the
* call stack at the time a {@code Throwable} gets thrown.
* Throwable#getStackTrace()
public final class StackTraceElement implements Serializable {
private static final long serialVersionUID = 6171013L;
private static final int NATIVE_LINE_NUMBER = -2;
String declaringC
String methodN
String fileN
* Returns the fully qualified name of the class belonging to this
* {@code StackTraceElement}.
* the fully qualified type name of the class
public String getClassName() {
return (declaringClass == null) ? "&unknown class&" : declaringC
* Returns the name of the Java source file containing class belonging to
* this {@code StackTraceElement}.
* the name of the file, or {@code null} if this information is not
available.
public String getFileName() {
return fileN
* Returns the line number in the source for the class belonging to this
* {@code StackTraceElement}.
* the line number, or a negative number if this information is not
available.
public int getLineNumber() {
return lineN
* Returns the name of the method belonging to this {@code
* StackTraceElement}.
* the name of the method, or "&unknown method&" if this information
is not available.
public String getMethodName() {
return (methodName == null) ? "&unknown method&" : methodN
由源码可以得知每个StackTraceElement里面有declaringClass、methodName、fileName、lineNumber这四个变量以及相应的get方法,我们现在输出这几个值看看。
//由于是在主函数里面获取StackTraceElement,所以只用取第二个就可以了
StackTraceElement element = Thread.currentThread().getStackTrace()[2]
System.out.println(element)
System.out.println("className: " + element.getClassName())
System.out.println("filesName: " + element.getFileName())
System.out.println("methodName: " + element.getMethodName())
System.out.println("lineNumber: " + element.getLineNumber())
I/System.out: className: com.sky.yunlv.yunlv_android.MainActivity
I/System.out: filesName: MainActivity.java
I/System.out: methodName: onCreate
I/System.out: lineNumber: 127
这时再想想我们打印log需要的信息,类名,方法名,打印的位置,年薪百万,升职,人生巅峰….这正是我们需要的啊!到此我们差不多就是万事具备只欠东风了,接着只需要拿起我们得到的StackTraceElement,就能投身与创建自己的log工具的革命中。
Log工具实践
众所周知,最普通的系统打印方法为Log.d(tag,message),然而由于懒是程序员第一生产力,一个参数能搞定的,为啥要用两个,那么自然而然的tag就得自动生成,这时聪明如你应该发现什么了吧,那就是StackTraceElement正是我们生成tag的关键。
String message = "hello,world"
StackTraceElement traceElement = element
StringBuilder sb = new StringBuilder()
String className = traceElement.getClassName()
String fileName = traceElement.getFileName()
sb.append(className.substring(className.lastIndexOf(".") + 1)).append(".")
.append(traceElement.getMethodName())
.append(" (").append(fileName).append(":")
.append(traceElement.getLineNumber())
.append(") ")
String tag = sb.toString()
Log.d(tag,message)
01-06 02:58:31.097 /? D/MainActivity.onCreate (MainActivity.java:20): hello,word
可以看到我们打印出来了很多干货,有类名,方法名,甚至还有调用的行数。有了这些妈妈再也不用担心我们信息不够了。
很显然,如果我们仅仅是扩展了系统Log的话,那毫无什么逼格可言,至少也得加几个神奇的功能嘛。
json是我们经常打交道的,但每次查看服务器端返回的json数据时,一大坨,还得复制到专门的解析工具中去解析,好麻烦啊。这时聪明的你是不是可以想办法把返回的json数据按格式打印出来呢。
为了打印出来的东西美观漂亮,我们还得思考思考格式,毕竟长得漂亮看得舒心嘛,这里参考了。
private static final char TOP_LEFT_CORNER = '╔';
private static final char BOTTOM_LEFT_CORNER = '╚';
private static final char MIDDLE_CORNER = '╟';
private static final char HORIZONTAL_DOUBLE_LINE = '║';
private static final String DOUBLE_DIVIDER = "════════════════════════════════════════════";
private static final String SINGLE_DIVIDER = "────────────────────────────────────────────";
private static final String TOP_BORDER = TOP_LEFT_CORNER + DOUBLE_DIVIDER + DOUBLE_DIVIDER;
private static final String BOTTOM_BORDER = BOTTOM_LEFT_CORNER + DOUBLE_DIVIDER + DOUBLE_DIVIDER;
private static final String MIDDLE_BORDER = MIDDLE_CORNER + SINGLE_DIVIDER + SINGLE_DIVIDER;
具体代码如下:
//打印json
private void printJson(StackTraceElement element,String json){
if (!KyLog.configAllowLog){
String[] values = generateValues(element)
String tag = values[0]
String fileName = values[1]
if (TextUtils.isEmpty(json)){
Log.d(tag,"JSON{json is null}")
if (json.startsWith("{")){
JSONObject jsonObject = new JSONObject(json)
json = jsonObject.toString(4)
}else if (json.startsWith("[")){
JSONArray array = new JSONArray(json)
json = array.toString(4)
String[] lines = json.split(LINE_SEPARATOR)
StringBuilder stringBuilder = new StringBuilder()
for (String line: lines){
stringBuilder.append("║ ").append(line).append(LINE_SEPARATOR)
Log.d(fileName,TOP_BORDER)
Log.d(fileName,HORIZONTAL_DOUBLE_LINE + " " + tag)
Log.d(fileName,MIDDLE_BORDER)
Log.d(fileName,stringBuilder.toString())
Log.d(fileName,BOTTOM_BORDER)
}catch (JSONException e){
Log.e(tag,e.getMessage() )
//获取具体信息的封装
private String[] generateValues(StackTraceElement element){
String[] values = new String[2]
StackTraceElement traceElement = element
StringBuilder sb = new StringBuilder()
String className = traceElement.getClassName()
String fileName = traceElement.getFileName()
sb.append(className.substring(className.lastIndexOf(".") + 1)).append(".")
.append(traceElement.getMethodName())
.append(" (").append(fileName).append(":")
.append(traceElement.getLineNumber())
.append(") ")
String tag = sb.toString()
values[0] = tag
values[1] = fileName
return values
效果如下:
其实原理很简单,就把json获取到,按照我们自己想要的格式输出。其中json按标准格式打印需要用到的方法是json = jsonObject.toString(4),按层次换行,并且间隔距离为4。
既然json打印得了,对象也能打印这样才有意思嘛。在打印对象上的实现方法很好。其原理就是通过反射将类的属性以及值反射出来。
* 将对象转化为String
public static &T& String objectToString(T object) {
if (object == null) {
return "Object{object is null}";
if (object.toString().startsWith(object.getClass().getName() + "@")) {
StringBuilder builder = new StringBuilder(object.getClass().getSimpleName() + " { ");
Field[] fields = object.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
boolean flag = false;
for (String type : types) {
if (field.getType().getName().equalsIgnoreCase(type)) {
flag = true;
Object value = null;
value = field.get(object);
} catch (IllegalAccessException e) {
}finally {
builder.append(String.format("%s=%s, ", field.getName(),
value == null ? "null" : value.toString()));
if(!flag){
builder.append(String.format("%s=%s, ", field.getName(), "Object"));
return builder.replace(builder.length() - 2, builder.length() - 1, " }").toString();
return object.toString();
private final static String[] types = {"int", "java.lang.String", "boolean", "char",
"float", "double", "long", "short", "byte"};
接下来就是制作log的样式
String message = SystemUtil.objectToString(object);
Log.d(fileName,TOP_BORDER);
Log.d(fileName,HORIZONTAL_DOUBLE_LINE + " " + tag);
Log.d(fileName,MIDDLE_BORDER);
Log.d(fileName, HORIZONTAL_DOUBLE_LINE + " " + message);
Log.d(fileName,BOTTOM_BORDER);
效果图如下:
打印Collection和Map
做的很不错,能打印很多东西,就是log样式稍微有点不好看,为了让它像那样,我决定改造改造。
if (object instanceof Collection){
Collection collection = (Collection) object
String msg = " %s size = %d [\n"
msg = String.format(msg,simpleName,collection.size())
if (!collection.isEmpty()) {
StringBuilder stringBuilder = new StringBuilder()
stringBuilder.append(TOP_BORDER).append(LINE_SEPARATOR)
.append(HORIZONTAL_DOUBLE_LINE).append(" ").append(tag).append(LINE_SEPARATOR)
.append(MIDDLE_BORDER).append(LINE_SEPARATOR)
.append(HORIZONTAL_DOUBLE_LINE).append(msg)
Iterator&Object& iterator = collection.iterator()
int index = 0
while (iterator.hasNext()){
String itemString = HORIZONTAL_DOUBLE_LINE + " [%d]:%s%s"
Object item = iterator.next()
stringBuilder.append(String.format(itemString,index,
SystemUtil.objectToString(item),index++ & collection.size()-1?",\n":"\n"))
stringBuilder.append(HORIZONTAL_DOUBLE_LINE + " ]\n").append(BOTTOM_BORDER)
Log.d(fileName,stringBuilder.toString())
printLog(element,ERROR,msg + " and is empty ]")
}else if (object instanceof Map){
Map&Object,Object& map = (Map&Object, Object&) object
Set&Object& keys = map.keySet()
if (keys.size() & 0) {
StringBuilder stringBuilder = new StringBuilder()
stringBuilder.append(TOP_BORDER).append(LINE_SEPARATOR)
.append(HORIZONTAL_DOUBLE_LINE).append(" ").append(tag).append(LINE_SEPARATOR)
.append(MIDDLE_BORDER).append(LINE_SEPARATOR)
.append(HORIZONTAL_DOUBLE_LINE).append(" ").append(simpleName).append(" {\n")
for (Object key : keys){
stringBuilder.append(HORIZONTAL_DOUBLE_LINE).append(" ")
.append(String.format("[%s -& %s]\n",SystemUtil.objectToString(key),SystemUtil.objectToString(map.get(key))))
stringBuilder.append(HORIZONTAL_DOUBLE_LINE).append(" ").append("}\n")
.append(BOTTOM_BORDER)
Log.d(fileName,stringBuilder.toString())
printLog(element,ERROR,simpleName + " is Empty")
效果图为下:
其实Log的制作是很简单的,我们只需要获得StackTraceElement里面的信息,更多的是考虑你自己想要的格式,只要发挥自己的想象力,就能做出各种漂亮的Log输出,另外本文的源码在这儿。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:15680次
排名:千里之外
评论:11条
(2)(1)(1)(1)(1)(1)(1)
(window.slotbydup = window.slotbydup || []).push({
id: '4740881',
container: s,
size: '200,200',
display: 'inlay-fix'问:安卓码运行出现问题,如何解决[--::-myContacts]设施错误:INSTALL_FAILED_CONFLICTING_...答:如是实在不行,就将游戏卸载了然后再次安装试试。在不行估计就是你的或者平板对游戏支持不够
问:如何过滤adblogcat输出答:本文介绍如何在 shell命令行中过滤 adblogcat输出的几个小技巧。开发当中经常看到别人的 log如洪水般瞬间满了屏幕,对自己有用的都被淹没了,影响心情...
问:高分求(A)的MIUI ROM要没有删除系统日志输出的.做开发用...答:嗨!很抱歉,第三方机型的问题,我们没有办法,给您详细的解答。建议您去MIUI搜索下相关帖子,或者发帖和们交流一下,里有很多玩机高手,应该会帮您...
问:安卓码运行时出错,怎么解决?[--::-myContacts]设施错误:INSTALL_FAILED_CONFLICTING_...答:是不是游戏?提示说你的硬件支持出现了问题。估计时你的对游戏的支持不足造成的。没有办法处理
问:求助,logcat无法显示日志:三星Neclipse:indigoADT:系统:_这个连接到电脑上logcat...答:已经选中了。他会打印一些乱糟的东西。但是不打印任何应用输出的log到eoeAndroid查看回答详情
问:安卓码运行出现问题,如何解决[--::-myContacts]设施错误:INSTALL_FAILED_CONFLICTING_...答:如是实在不行,就将游戏卸载了然后再次安装试试。在不行估计就是你的或者平板对游戏支持不够
问:androidlogcat输出日志时,怎么通过来过滤日志,只...答:控制台,还是在Eclipse上的Logcat视图?、如果是控制台,可以在控制台输入:adblogcat-s"*:I"、如果是在Eclipse上的Logcat视图,可以选择filter的为...
问:安卓码运行时出错,怎么解决?[--::-myContacts]设施错误:INSTALL_FAILED_CONFLICTING_...答:是不是游戏?提示说你的硬件支持出现了问题。估计时你的对游戏的支持不足造成的。没有办法处理
问:android不同品logcat日志的格式一样吗?例如不同的两部...答:格式一般是一样,内容大多不一样,厂商为了开发方便可能会多打些log,由于硬件不同也会打印不同的log
问:安卓码运行出现问题,如何解决[--::-myContacts]设施错误:INSTALL_FAILED_CONFLICTING_...答:如是实在不行,就将游戏卸载了然后再次安装试试。在不行估计就是你的或者平板对游戏支持不够
问:如何完全屏蔽某个tag的logcat日志输出呢?在调试蓝牙的时候,发现android系统里输出某个logcat日志,输出的很快,导致...答:可以添加log过滤哦,add a newlogcat filter,点那个绿的加号
07-2109-1508-0709-01
03-2601-2504-2204-07
◇本站云标签后使用快捷导航没有帐号?
平板/笔记本
云服务专区
荣耀8 android调试无法输出logCat日志
&略有小成&
来自:浏览器
本帖最后由 巴渝人 于
12:18 编辑
如题,请华为工程师帮忙讲解一下,如何输出日志,没有日志程序太难调试了!
log.e 和 System.out.println都看不到日志,晕了!
(118.79 KB, 下载次数: 0)
12:16 上传
(110.37 KB, 下载次数: 2)
12:16 上传
width:100%">
&初窥门径&
来自:浏览器
问题解决了么?
width:100%">
&略有小成&
来自:浏览器
问题解决了么?
width:100%">
&新学乍练&
来自:浏览器
问题解决了么?!
width:100%">
&新学乍练&
来自:浏览器
我也遇到了同样的问题,等解决 荣耀8 EMUI5.0
width:100%">
&略有小成&
来自:荣耀8 FRD-AL00
没人管吗?
width:100%">
&新学乍练&
来自:浏览器
顶起,也想知道这要怎么处理
width:100%">
&新学乍练&
来自:荣耀8 FRD-AL00
怒求答案,打开log设置还是不行,重启手机后log又回到关闭状态
width:100%">
&新学乍练&
来自:浏览器
求答案,手机坏了买了个荣耀8,结果悲剧看不了日志,打开了各种日志重启都会还原关闭,华为的工程师们看看吧!!!!!!!!!!!!!!!!!!!
width:100%">
&新学乍练&
来自:荣耀8 FRD-AL10
同重启后还原,求个解决方法
width:100%">
把【秋】做成标本随拍:生活的‘远方’夕照上阳宫秋色白桦林再次邂逅坝上公主湖,依然惊艳!
花粉客户端
Make it Possible
Make your device special
华为云服务
Huawei cloud services
音乐播放器
Huawei Music
Huawei Vmall
没有最新动态
关注花粉俱乐部
联系我们:
|关注花粉俱乐部:
Copyright (C)
华为软件技术有限公司 版权所有 保留一切权利下次自动登录
现在的位置:
& 综合 & 正文
Android SDK下, 如何在程序中输出日志 以及如何查看日志.
Android SDK下, 如何在程序中输出日志 以及如何查看日志. 闲话少说,直接进入正题 在程序中输出日志, 使用 android.util.Log 类. 该类提供了若干静态方法 Log.v(String tag, String msg); Log.d(String tag, String msg); Log.i(String tag, String msg); Log.w(String tag, String msg); Log.e(String tag, String msg); 分别对应 Verbose, Debug, Info, Warning,Error. tag是一个标识,可以是任意字符串,通常可以使用类名+方法名, 主要是用来在查看日志时提供一个筛选条件. 程序运行后 并不会在 ide的控制台内输出任何信息. 如果要后查看日志 请使用 adb logcat 关于adb的更多信息请查看官方网站. 当执行 adb logcat 后会以tail方式实时显示出所有的日志信息. 这时候我们通常需要对信息进行过滤,来显示我们需要的信息, 这时候我们指定的 tag就派上了用场. adb logcat -s MyAndroid:I 这时将只显示tag为MyAndroid,级别为I或级别高于I(Warning,Error)的日志信息. 示例代码如下:
package com.
import android.app.A
import android.content.C
import android.graphics.C
import android.os.B
import android.util.L
import android.view.MotionE
import android.view.V
public class MyAndroid extends Activity {
protected static final String ACTIVITY_TAG="MyAndroid";
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(new MyView(this));
public class MyView extends View {
public MyView(Context c) {
protected void onDraw(Canvas canvas) {
public boolean onMotionEvent(MotionEvent event) {
Log.i(MyAndroid.ACTIVITY_TAG, "=============================");
Log.d(MyAndroid.ACTIVITY_TAG, "Haha , this is a DEBUG of MyAndroid. ");
Log.i(MyAndroid.ACTIVITY_TAG, "Haha , this is a INFO of MyAndroid. ");
Log.w(MyAndroid.ACTIVITY_TAG, "Haha , this is a WARNING of MyAndroid. ");
return true;
以上程序运行后, 在命令行执行
adb logcat -s MyAndroid:I
然后在手机模拟器的屏幕上 点击 拖动鼠标 就能看到相应的日志信息.
logcat的参数说明,这个说明比较难找 我是无意间发现的 adb logcat .....
Usage: logcat [options] [filterspecs]
options include:
Set default filter to silent.
Like specifying filterspec '*:s'
-f &filename&
Log to file. Default to stdout
-r [&kbytes&]
Rotate log every kbytes. (16 if unspecified). Requires -f
-n &count&
Sets max number of rotated logs to &count&, default 4
-v &format&
Sets the log print format, where &format& is one of:
brief process tag thread raw time long
clear (flush) the entire log and exit
dump the log and then exit (don't block)
get the size of the log's ring buffer and exit
-b &buffer&
request alternate ring buffer, defaults to 'main'
filterspecs are a series of
&tag&[:priority]
where &tag& is a log component tag (or * for all) and priority is:
Silent (supress all output)
'*' means '*:d' and &tag& by itself means &tag&:v
If not specified on the commandline, filterspec is set from ANDROID_LOG_TAG
If no filterspec is found, filter defaults to '*:I'
If not specified with -v, format is set from ANDROID_PRINTF_LOG
or defaults to "brief"
在eclipse 里选择 show view 然后选择 LogCat 可以更方便的查看, 而不用一定非要到控制台
转载地址:
作者:fins(来自iteye的资深会员)
&&&&推荐文章:
【上篇】【下篇】}

我要回帖

更多关于 android 输出日志 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信