Android的log使用技巧(Java层,Native层)

#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

  1. 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)

}

  1. 在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;
        }
    }
}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值