Android的log使用技巧(Java層,Native層)
阿新 • • 發佈:2018-12-22
#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;
}
}
}