#Android的log使用技巧
1. android Log.isLoggable
DebugUtils.java
package com.XXX.XXX;
import android.content.Context;
import android.util.Log;
import android.widget.Toast;
public class DebugUtils {
private static final String TAG = "AABBCC";
private static final boolean BETA_ENABLED = false;
public static boolean DEBUG = true;
public static void i(String tag, String msg){
if(debugEnabled()) {
Log.i(TAG, tag + " " + msg);
}
}
public static void v(String tag, String msg){
if(debugEnabled()) {
Log.v(TAG, tag + " " + msg);
}
}
public static void d(String tag, String msg){
if(debugEnabled()) {
Log.d(TAG, tag + " " + msg);
}
}
public static void w(String tag, String msg){
if(debugEnabled()) {
Log.w(TAG, tag + " " + msg);
}
}
public static void e(String tag, String msg){
Log.e(TAG, tag + " " + msg);
}
public static void toastMsg(Context context, int resId){
Toast.makeText(context, context.getString(resId), Toast.LENGTH_SHORT).show();
}
public static void toastMsg(Context context, String msg){
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
}
public static boolean debugEnabled(){
return (Log.isLoggable(TAG, Log.DEBUG) || BETA_ENABLED);
}
}
在应用中加入如上的log类,然后需要调试Log的时候可通过 下列adb 命令打开Log
#当然VERBOSE 可以换成其他标签DEBUG,INFO,WARN,ERROR,ASSERT以打开不同等级的log
adb shell setprop log.tag.AABBCC VERBOSE
2. Java层打印callstack
va层打印callstack方法
Vic方法:
方法一:RuntimeException here = new RuntimeException("here");
here.fillInStackTrace();
Log.w(TAG, "Called: " + this, here);
方法二:Exception e = new Exception("this is a log");
e.printStackTrace();
方法三:Thread.dumpStack();
方法四:Log.d(TAG,Log.getStackTraceString(new Throwable()));
方法五类似于bob的方法:
StackTraceElement[] stackframes = Thread.currentThread().getStackTrace();
Log.e("Stacktrace ***","**********BEGIN********");
for(int i=0;i<stackframes.length;i++){
Log.e("Stacktrace ***",stackframes[i].toString());
}
Log.e("Stacktrace ***","**********END********");
在Java exception中打印callstack
try {
...
} catch (RemoteException e) {
e.printStackTrace();
}
Bob方法:
//---------------------------------------------------------
android.util.Log.d("bob_log_tag", " _ " +
"[setTypeface] " +
" typeface: " + typeface +
" typeface.native_instance: " + typeface.native_instance +
" this: " + Integer.toHexString(System.identityHashCode(this)) +
"");
for (StackTraceElement element : new Throwable().getStackTrace())
{
android.util.Log.d("bob_log_tag", " |-- " + element.toString());
}
android.util.Log.d("bob_log_tag", " @");
//---------------------------------------------------------
3.Native code中打印callstack
在C++中打印call stack
1.添加如下头文件
#include<utils/CallStack.h>
2.在使用的地方直接使用,注意加上android命名空间,否则会报错或者可以使用using namespace andoid;
android:CallStack stack(LOG_TAG);//LOG_TAG是自定义的String
3.在该模块的Android.mk中需要加上,已有其他的库在其他库后面空格再加入该库
LOCAL_SHARED_LIBRARIES+= libutils
编译该模块验证
值得注意的是,在CallStack中有toString方法,意味着我们可以通过返回值得到callstack的子串,对该子串进行搜索筛选等操作;
String8 CallStack::toString(const char* prefix) const {
String8 str;
String8Printer printer(&str, prefix);
print(printer);
return str;
}
在C中打印callStack
- Wrapper Android C++ Method into a C function in your C++ code ‘dump_stack.cpp’
#include<utils/CallStack.h>
using namespace android;
extern “C” void dump_stack(const char* logtag)
{
CallStack stack(logtag)
}
- 在C代码里调用这个’dump_stack’函数
extern void dump_stack(const char* logtag);
...
dump_stack(LOG_TAG);
...
3.在该模块的Android.mk中需要加上,已有其他的库在其他库后面空格再加入该库
LOCAL_SHARED_LIBRARIES+= libutils
打印调用父进程
在nativecode中查/proc/%d/status中的Name值可以得到进程名称,甚至可以通过ppid得到调用的父进程的名称
int split(char dst[120][80], char* str, const char* spl)
{
int n = 0;
char *result = NULL;
result = strtok(str, spl);
while( result != NULL )
{
strcpy(dst[n++], result);
result = strtok(NULL, spl);
}
return n;
}
static void dump_additional_info(log_t* log, pid_t pid) {
char proc_pid_path[255];
sprintf(proc_pid_path, "/proc/%d/status", pid);
FILE *pFile=fopen(proc_pid_path,"r");
char *pBuf;
int len=1024;
pBuf=new char[len+1];
rewind(pFile);
fread(pBuf,1,len,pFile);
pBuf[len]=0;
fclose(pFile);
char dst[120][80];
int cnt = split(dst,pBuf,"\n");
for (int i = 0; i< cnt; i++){
size_t l = strlen(dst[i]);
char ppid_str[50];
char name_str[50];
if(strstr(dst[i],"PPid:")!=NULL){
strncpy(ppid_str , dst[i] + 5, l-5);
ppid_str[l-5]=0;
int ppid = atoi(ppid_str);
if(ppid > 0){
dump_additional_info(log, ppid);
}
_LOG(log, logtype::HEADER, "(PPid/Name): %s %s\n", ppid_str, name_str);
}else if(strstr(dst[i],"Name:")!=NULL){
strncpy(name_str , dst[i] + 5, l-5);
name_str[l-5]=0;
}
}
}