[轉載請註明出處]
http://kezeodsnx.pixnet.net/blog
http://hatsukiakio.blogspot.com/2009/05/loglogcat.html


http://ithelp.ithome.com.tw/question/10012805


說明


先把emulator跑起來後,在console下adb logcat後,就會有一堆message跑出來了,如


I/SystemServer(  568): Starting Battery Service.
E/BatteryService(  568): Could not open '/sys/class/power_supply/usb/online'


在Android除錯最常用的方式就是開Logcat來觀看,他可以取代JRE的Console來幫忙偵錯
不然每次程式錯誤都要寫個AlertDialog也是個麻煩
LogCat叫出方法,Window -> Show View -> Other,找Android -> LogCat

而在Android有個Log類別可以跟Logcat配合,他可以幫忙除錯,有點像以前我們寫C/C++用土法煉鋼printf來看資訊一樣

Log基本用法

Log.類型(標籤名子,訊息)

Log的類型大概分以下幾類



  1. Log.v(TAG,Message) :Verbose 記錄詳細訊息
  2. Log.d(TAG,Message) :Debug 除錯
  3. Log.i(TAG,Message) :INFO 資訊
  4. Log.w(TAG,Message):Warning 警告
  5. Log.e(TAG,Message) : Error 錯誤


------------
其中TAG是可以幫助我們篩選訊息,因為一般logcat會擷取一大堆訊息,包括GC做了什麼
自定Tag可以幫我們下Filter

LogCat雜七雜八訊息

而我加入了自己的訊息,假設我想記錄開啟程式成功與否

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.main);
Log.i("Create Android", "Test");
findVuew();
setClick();


}

而我想過濾那些雜七雜八的訊息,可以從右上的綠色加號增加filter

之後會跳出設定視窗

裡面幾個必要參數



  1. Filter Name:過濾名稱 可以隨自己喜好取
  2. by Log Tag:想留下的Tag名稱,在此設我剛剛取的Create Android
  3. by Log level :這選項是可選的,可以過濾Log的類型,在此我選none



而接下來,就只會剩下我想看到的訊息


In JAVA


在JAVA中,logcat的class是在android.util.log裡,因此若要使用,需要在header加上import android.util.Log。程式的使用如下:


Log.v(): VERBOSE
Log.d(): DEBUG
Log.i() : INFO
Log.w(): WARN
Log.e(): ERROR


第一個欄位是tag,第二個欄位是訊息,因此可以這樣用:


Log.i("OnCreate", "#########Test in java");


在logcat可以看到:


I/OnCreate(  712): #########Test in java


In JNI


在JNI中,可以使用 所定義的macro:


int __android_log_print(int prio, const char *tag,  const char *fmt, ...)
#if defined(__GNUC__)
    __attribute__ ((format(printf, 3, 4)))
#endif
    ;


參考android討論區所提到的這篇文章,可定義如下的macro以方便使用:
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG  , "libnav",__VA_ARGS__)


就可以在.c檔裡輸出到logcat,方法如下:


jint
Java_com_latrell_libtest_libtest_add( JNIEnv* env, jobject thiz, jint x, jint y)
{
        LOGD("#############test log in JNI, x is %d, y is %d\n",x,y);
    return add(x,y);
}


從logcat就可看到,也是一種debug方式:


D/libnav  (  716): #############test log in JNI, x is 3, y is 5


在JNI裡使用logcat,要在Android.mk裡將liblog link進來,因此要加上:


LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog


將ndk裡的hello-jni改寫了一下,程式碼如下:


hello-jni.c


#include
#include
#include

#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, "libnav",__VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG  , "libnav",__VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO   , "libnav",__VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN   , "libnav",__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR  , "libnav",__VA_ARGS__)
int add(int x, int y)
{
        return x+y;
}
jint
Java_com_latrell_libtest_libtest_add( JNIEnv* env, jobject thiz, jint x, jint y)
{
        LOGD("#############test log in JNI, x is %d, y is %d\n",x,y);
    return add(x,y);
}



Android.mk:


LOCAL_PATH := $(call my-dir)
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog

include $(CLEAR_VARS)

LOCAL_MODULE    := latrell-libtest
LOCAL_SRC_FILES := hello-jni.c

include $(BUILD_SHARED_LIBRARY)


libtest.java:


package com.latrell.libtest;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
public class libtest extends Activity {
    /** Called when the activity is first created. */
    int ret=0;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TextView  tv = new TextView(this);
            int a=3;
            int b=5;
            ret=add(a,b);
            tv.setText(Integer.toString(ret));
            Log.i("Create Android", "################Test in java");
            setContentView(tv);
    }
 public native int  add(int x, int y);
    static {
        System.loadLibrary("latrell-libtest");
    }

}


issue:


1. 用eclipse時,在hello-jni.c裡改變log的內容,重新make APP後,用eclipse上傳到emulator後,沒辦法將改變apply?後來將整個project移除再import一次才解決,不知有沒有人知道該如何解決?


2. 試著調用如strcmp,strlen的function,但還無法將字串從java傳到c (傳integer沒問題),這可能是java寫錯了,還在研究中。


傳字串是要用特定方法的:


int stringlen(char* str)
{
        LOGD("#############test log in native c function, str is %s\n",str);
        return strlen(str);
}


Java_com_latrell_libtest_libtest_stringlen( JNIEnv* env, jobject thiz, jstring str)
{
        char* buf;
        buf = (*env)->GetStringUTFChars(env, str, 0);
        LOGD("#############test log in JNI, str is %s\n",buf);
        return stringlen(buf);
}

創作者介紹
創作者 立你斯 的頭像
立你斯

立你斯學習記錄

立你斯 發表在 痞客邦 留言(0) 人氣()