A. 安卓如何將log保存到文件中
相信大家在做應用調試的時候,不可能時時通過USB線連著電腦去查看log信息,所以,將應用的log信息保存到手機本地就很有必要了,有助我們從這些log信息中提取有用的部分,以解決一些bug,下面我把網上分享的代碼中作了一些精簡,作為開發者使用,個人覺得沒必要通過用戶上傳給我們,用戶上傳的不需要這么龐大的log信息,僅僅那部分崩潰的log信息即可,可參考我的另外一篇blog:http://blog.csdn.net/weidi1989/article/details/7927273。
好了,廢話不多說,直接分享封裝好的log信息類:LogcatHelper
package com.way.util;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import android.content.Context;
import android.os.Environment;
/**
* log日誌統計保存
*
* @author way
*
*/
public class LogcatHelper {
private static LogcatHelper INSTANCE = null;
private static String PATH_LOGCAT;
private LogDumper mLogDumper = null;
private int mPId;
/**
*
* 初始化目錄
*
* */
public void init(Context context) {
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {// 優先保存到SD卡中
PATH_LOGCAT = Environment.getExternalStorageDirectory()
.getAbsolutePath() + File.separator + "miniGPS";
} else {// 如果SD卡不存在,就保存到本應用的目錄下
PATH_LOGCAT = context.getFilesDir().getAbsolutePath()
+ File.separator + "miniGPS";
}
File file = new File(PATH_LOGCAT);
if (!file.exists()) {
file.mkdirs();
}
}
public static LogcatHelper getInstance(Context context) {
if (INSTANCE == null) {
INSTANCE = new LogcatHelper(context);
}
return INSTANCE;
}
private LogcatHelper(Context context) {
init(context);
mPId = android.os.Process.myPid();
}
public void start() {
if (mLogDumper == null)
mLogDumper = new LogDumper(String.valueOf(mPId), PATH_LOGCAT);
mLogDumper.start();
}
public void stop() {
if (mLogDumper != null) {
mLogDumper.stopLogs();
mLogDumper = null;
}
}
private class LogDumper extends Thread {
private Process logcatProc;
private BufferedReader mReader = null;
private boolean mRunning = true;
String cmds = null;
private String mPID;
private FileOutputStream out = null;
public LogDumper(String pid, String dir) {
mPID = pid;
try {
out = new FileOutputStream(new File(dir, "GPS-"
+ MyDate.getFileName() + ".log"));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/**
*
* 日誌等級:*:v , *:d , *:w , *:e , *:f , *:s
*
* 顯示當前mPID程序的 E和W等級的日誌.
*
* */
// cmds = "logcat *:e *:w | grep \"(" + mPID + ")\"";
// cmds = "logcat | grep \"(" + mPID + ")\"";//列印所有日誌信息
// cmds = "logcat -s way";//列印標簽過濾信息
cmds = "logcat *:e *:i | grep \"(" + mPID + ")\"";
}
public void stopLogs() {
mRunning = false;
}
@Override
public void run() {
try {
logcatProc = Runtime.getRuntime().exec(cmds);
mReader = new BufferedReader(new InputStreamReader(
logcatProc.getInputStream()), 1024);
String line = null;
while (mRunning && (line = mReader.readLine()) != null) {
if (!mRunning) {
break;
}
if (line.length() == 0) {
continue;
}
if (out != null && line.contains(mPID)) {
out.write((MyDate.getDateEN() + " " + line + "\n")
.getBytes());
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (logcatProc != null) {
logcatProc.destroy();
logcatProc = null;
}
if (mReader != null) {
try {
mReader.close();
mReader = null;
} catch (IOException e) {
e.printStackTrace();
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
out = null;
}
}
}
}
}
記得加上許可權:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_LOGS" />
另外把那個時間的工具類也分享一下:
package com.way.util;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MyDate {
public static String getFileName() {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
String date = format.format(new Date(System.currentTimeMillis()));
return date;// 2012年10月03日 23:41:31
}
public static String getDateEN() {
SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date1 = format1.format(new Date(System.currentTimeMillis()));
return date1;// 2012-10-03 23:41:31
}
}
OK,所有事情做完之後,在我們的應用中start一下就OK了,使用完之後,記得調用一下stop:
public class GPSApplication extends Application {
@Override
public void onCreate() {
// TODO Auto-generated method stub
LogcatHelper.getInstance(this).start();
}
}
B. 在Android開發中,Logcat是什麼
最後介紹一下Android的Log工具LogCat。
首先在Eclipse中選擇Windows > Show View > Other... > Android > LogCat,確定後會出現LogCat顯示框,用戶添加的Log將會在這里顯示。使用時直接在代碼中插入「Log.i("info","this is a log");」,那麼在執行到該語句時,LogCat顯示框中將出現「this is a log」。
在Eclipse中安裝ADT和android sdk包之後,運行以開發的android程序時,在LogCat窗口中會顯示出一系列的信息,這些信息是每一個程序通過Dalvik虛擬機所傳出的實時信息,可以方便我們對程序的了解。
在log窗口中,每條信息都包含五個部分,Time,標題空白,pid,tag和Message。
1、Time
表示執行的時間,這個信息對於學習生命周期,分析程序運行的先後順序特別有用。
2、標題空白的列
表示的是信息的種類,分為V,D,I,W,E五種。
V:verbose,顯示全部信息
D:Debug,顯示調試信息
I:Info,顯示一般信息
W:Warming,顯示警告信息
E:Error,顯示錯誤信息
可以通過點擊LogCat上面的用圓圈括起來的V,D,I,W,E來改變顯示的范圍。比如選擇了W,那就只有警告信息和錯誤信息可以顯示出來了。
3、pid
表示程序運行時的進程號
4、tag
標簽,通常表示系統中的一些進程名,比如我們運行helloworld程序的話,就會看到activitymanager在運行。
5、Message
表示進程運行時的一些具體信息,比如我們運行helloworld程序的話,就會看到starting activity...helloWorld的字樣
可以輸出LogCat的信息到文本文件中,以方便分析。在下拉框中選擇輸出選擇的信息就可以了。
下面是輸出到文件中的啟動helloWorld程序時的一條信息的例子,分別用5個下劃線標出了上面介紹的內容:
05-20 15:46:10.129: INFO/ActivityManager(60): Starting activity: Intent { act=android.intent.action.MAIN cat=
[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.android.helloworld/.HelloWorld }
6、Filter的使用
可以在Filter中輸入篩選信息,使LogCat中只現實我們需要分析的信息。比如我們只想看和HelloWorld相關的信息,就可以在
Filter中輸入HelloWorld,這樣只有Message 中包含HelloWorld的內容才會顯示出來。
7、LogCat中信息不能顯示
上面說了這么多關於logCat的使用,可能LogCat中根本就什麼信息都沒有顯示!沒關系,只要在Eclipse中選擇window-
>show view->other->android->devices就可以 了。
8、在LogCat中輸出程序的運行信息
a、在程序中導入相應的包:import android.util.Log;
b、在需要輸出信息的函數中增加相關的調試代碼:Log.i("hi world","oncreate");
方法i是Log類的靜態方法,可以直接使用,我們看著各類的定義可以看到,它提供了多種輸出方法,分別對應我們上面提到的V,D,I,W,E。用哪個方法就決定了輸出的類型,這里用i,表示輸出的是information。
這個方法中的第一個參數就是要顯示在Tag那一欄的內容,把這條語句加到OnCreate方法中,執行時LogCat中就會顯示如下的信息: 05-22 21:58:22.894 I 3910 hi world onCreate
9、創建新的Filter
有時候只想看我們程序中用Log類的相關方法輸出的各種信息,這時就可以考慮新建一個過濾器。點擊LogCat的右上角的「+」號,可以創建一個新的過濾器。比如我們在by Log Tag的選項中填入上面程序輸出的"hi world"這個tag。這樣再運行時在我們新創建的Filter中就只顯示hi world這個tag標記出來的信息了。
Android開發中的logcat工具使用詳解--------
logcat是Android中一個命令行工具,可以用於得到程序的log信息。
logcat使用方法如下所示:
logcat [options] [filterspecs]
logcat的選項包括:
-s 設置過濾器,例如指定 '*:s'
-f <filename> 輸出到文件,默認情況是標准輸出。
-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> 設置log的列印格式, <format> 是下面的一種:
brief process tag thread raw time threadtime long
-c 清除所有log並退出
-d 得到所有log並退出 (不阻塞)
-g 得到環形緩沖區的大小並退出
-b <buffer> 請求不同的環形緩沖區 ('main' (默認), 'radio', 'events')
-B 輸出log到二進制中。
過濾器的格式是一個這樣的串:
<tag>[:priority]
其中 <tag> 表示log的component, tag (或者使用 * 表示所有) , priority 如下所示:
V Verbose
D Debug
I Info
W Warn
E Error
F Fatal
S Silent
事實上logcat的功能 是由Android的類android.util.Log決定的,在程序中log的使用方法如下所示:
Log.v() -------------------- VERBOSE
Log.d() -------------------- DEBUG
Log.i() -------------------- INFO
Log.w() -------------------- WARN
Log.e() -------------------- ERROR
以上log的級別依次升高,DEBUG信息應當只存在於開發中,INFO, WARN,ERROR這三種log將出現在發布版本中。
對於JAVA類,可以聲明一個字元串常量TAG,Logcat可以根據他來區分不同的log,例如在計算器(Calculator)的類中,定義如下所示:
public class Calculator extends Activity {
/* ...... */
private static final String LOG_TAG = "Calculator";
private static final boolean DEBUG = false;
private static final boolean LOG_ENABLED = DEBUG ? Config.LOGD : Config.LOGV;
/* ...... */
由此,所有在Calculator中使用的log,均以"Calculator"為開頭。
例如使用方法如下所示:
# logcat &
< 得到一個log片段 >
W/KeyCharacterMap( 130): No keyboard for id 0
W/KeyCharacterMap( 130): Using default keymap: /system/usr/keychars/qwerty.kcm.bin
I/ActivityManager( 52): Displayed activity com.android.contacts/.: 983 ms
I/ARMAsse mbler( 52): generated scanline__00000077:03545404_00000A04_00000000 [ 29 ipp] (51 ins) at [0x25c978:0x25ca44] in 1764174 ns
I/ARMAssembler( 52): generated scanline__00000077:03515104_00000001_00000000 [ 46 ipp] (65 ins) at [0x25d1c8:0x25d2cc] in 776789 ns
D / dalvikvm ( 130 ): GC freed 834 objects / 81760 bytes in 63ms
D/dalvikvm( 52): GC freed 10588 objects / 425776 bytes in 94ms
其中W/I/D 表示log的級別,「dalvikvm 」「ARMAssembler 」等是不同組件(component)的名稱,後面括弧裡面的數字 表示了發出log的進程號。
使用技巧:
1.使用logcat &在後台運行
2.使用-d得到所有log
3.使用-f或者重定向(>和>>)輸出到文件
4.使用-s設置過濾器,得到想要的log。
當然,最重要的還是在程序中加入恰當的log.
許多初次接觸Android開發的朋友會遇到調試的問題,如何能夠根據錯誤提示迅速的找到「出事地點呢」?在Eclipse+ADT的開發環境中沒有好的直接跟蹤對象內容的方法,通過使用android.util.Log類可以幫助你自己查找錯誤和列印系統日誌消息。它是一個進行日誌輸出的API,我們在Android 程序中可以隨時為某一個對象插入一個Log,然後在DDMS中觀察Logcat的輸出是否正常。
android.util.Log常用的方法有以下5個:Log.v() Log.d() Log.i() Log.w() 以及 Log.e() 。根據首字母對應VERBOSE,DEBUG,INFO, WARN,ERROR。當我們在DDMS進行調試時他們的區別並不大,只是顯示的顏色不同,但通過Logcat的過濾器我們可以過濾顯示某類的,一般對於執行錯誤的斷點,下在Log.e比較合適。但是Android開發網根據規范建議VERBOSE,DEBUG信息應當只存在於開發中,最終版本只可以包含 INFO, WARN,ERROR這三種日誌信息。在實際使用中,我們最好為每一個類聲明一個字元串常量TAG,這樣在Logcat中我們可以容易區分不同的類的日誌。例如:
private static final String TAG = "MyActivity";
接下來我們就可以用Log隨心所欲的觀察Android代碼中的每個細節:Log.e(TAG, "android123.com.cn"); 但是要記住這個Log類的參數都是String類型的。
C. Android中如何通過logcat追蹤生命周期事件
使用 logcat 命令 查看和跟蹤系統日誌緩沖區的命令logcat的一般用法是:[adb] logcat [] ... [] ... 下文介紹過濾器和命令選項,詳細內容可參見Listing of logcat Command Options。 可以在開發機中通過遠程shell的方式使用logcat命令查看日誌輸出: $ adb logcat如果是在遠程shell中可直接使用命令:# logcat過濾日誌輸出每一條日誌消息都有一個標記和優先順序與其關聯。 標記是一個簡短的字元串,用於標識原始消息的來源 (例如"View" 來源於顯示系統)。 優先順序是下面的字元,順序是從低到高: V — 明細 (最低優先順序) ,D — 調試I — 信息,W — 警告,E — 錯誤,F — 嚴重錯誤S — 無記載 (最高優先順序,沒有什麼會被記載) 通過運行logcat ,可以獲得一個系統中使用的標記和優先順序的列表,觀察列表的前兩列,給出的格式是/。 這里是一個日誌輸出的消息,優先順序是「I」,標記是「ActivityManager」: I/ActivityManager( 585): Starting activity: Intent { action=android.intent.action...} 如果想要減少輸出的內容,可以加上過濾器表達式進行限制,過濾器可以限制系統只輸出感興趣的標記-優先順序組合。 過濾器表達式的格式是tag:priority ... ,其中tag是標記, priority是最小的優先順序, 該標記標識的所有大於等於指定優先順序的消息被寫入日誌。也可以在一個過濾器表達式中提供多個這樣的過濾,它們之間用空格隔開。 下面給出的例子是僅輸出標記為「ActivityManager」並且優先順序大於等於「Info」和標記為「MyApp」並且優先順序大於等於「Debug」的日誌: adb logcat ActivityManager:I MyApp:D *:S 上述表達式最後的 *:S 用於設置所有標記的日誌優先順序為S,這樣可以確保僅有標記為「View」(譯者註:應該為ActivityManager,原文可能是筆誤)和「MyApp」的日誌被輸出,使用 *:S 是可以確保輸出符合指定的過濾器設置的一種推薦的方式,這樣過濾器就成為了日誌輸出的「白名單」。 下面的表達是顯示所有優先順序大於等於「warning」的日誌: adb logcat *:W如果在開發用電腦上運行 logcat (相對於運行運程shell而言),也可以通過ANDROID_LOG_TAGS環境變數設置默認的過濾器表達式: export ANDROID_LOG_TAGS="ActivityManager:I MyApp:D *:S" 需要注意的是,如果是在遠程shell或是使用adb shell logcat 命令運行logcat , ANDROID_LOG_TAGS不會導出到模擬器或手機設備上。 控制日誌格式 日誌消息在標記和優先順序之外還有很多元數據欄位,這些欄位可以通過修改輸出格式來控制輸出結果, -v 選項加上下面列出的內容可以控制輸出欄位: brief — 顯示優先順序/標記和原始進程的PID (默認格式) process — 僅顯示進程PID tag — 僅顯示優先順序/標記 thread — 僅顯示進程:線程和優先順序/標記 raw — 顯示原始的日誌信息,沒有其他的元數據欄位 time — 顯示日期,調用時間,優先順序/標記,PID long —顯示所有的元數據欄位並且用空行分隔消息內容 可以使用 -v啟動 logcat來控制日誌格式: [adb] logcat [-v ] 例如使用 thread 輸出格式: adb logcat -v thread注意只能在 -v 選項中指定一種格式。 Viewing Alternative Log Buffers Android日誌系統為日誌消息保持了多個循環緩沖區,而且不是所有的消息都被發送到默認緩沖區,要想查看這些附加的緩沖區,可以使用-b選項,以下是可以指定的緩沖區:radio — 查看包含在無線/電話相關的緩沖區消息events — 查看事件相關的消息main — 查看主緩沖區 (默認緩沖區)b 選項的用法:[adb] logcat [-b ] 例如查看radio緩沖區:adb logcat -b radio adb logcat簡單舉例:1、導入日誌到sd卡 $ adb shell monkey -p your.package.name -v 500 一些常用的參數信息:v命令行的每一個-v將增加反饋信息的級別。Level 0(預設值)除啟動提示、測試完成和最終結果之外,提供較少信息。Level1提供較為詳細的測試信息,如逐個發送到Activity的事件。Level 2提供更加詳細的設置信息,如測試中被選中的或未被選中的Activity。 事件s偽隨機數生成器的seed值。如果用相同的seed值再次運行Monkey,它將生成相同的事件序列。 throttle在事件之間插入固定延遲。通過這個選項可以減緩Monkey的執行速度。如果不指定該選項,Monkey將不會被延遲,事件將盡可能快地被產成。 pct-touch調整觸摸事件的百分比(觸摸事件是一個down-up事件,它發生在屏幕上的某單一位置)。 pct-motion調整動作事件的百分比(動作事件由屏幕上某處的一個down事件、一系列的偽隨機事件和一個up事件組成)。 pct-trackball調整軌跡事件的百分比(軌跡事件由一個或幾個隨機的移動組成,有時還伴隨有點擊)。 pct-nav調整「基本」導航事件的百分比(導航事件由來自方向輸入設備的up/down/left/right組成)。 pct-majornav調整「主要」導航事件的百分比(這些導航事件通常引發圖形界面中的動作,如:5-way鍵盤的中間按鍵、回退按鍵、菜單按鍵) pct-syskeys調整「系統」按鍵事件的百分比(這些按鍵通常被保留,由系統使用,如Home、Back、Start Call、End Call及音量控制鍵)。 pct-appswitch調整啟動Activity的百分比。在隨機間隔里,Monkey將執行一個startActivity()調用,作為最大程度覆蓋包中全部Activity的一種方法。 pct-anyevent調整其它類型事件的百分比。它包羅了所有其它類型的事件,如:按鍵、其它不常用的設備按鈕、等等。 約束限制p 如果用此參數指定了一個或幾個包,Monkey將只允許系統啟動這些包里的Activity。如果你的應用程序還需要訪問其它包里的Activity(如選擇取一個聯系人),那些包也需要在此同時指定。如果不指定任何包,Monkey將允許系統啟動全部包里的Activity。要指定多個包,需要使用多個p選項,每個-p選項只能用於一個包。 c如果用此參數指定了一個或幾個類別,Monkey將只允許系統啟動被這些類別中的某個類別列出的Activity。如果不指定任何類別,Monkey將選擇下列類別中列出的Activity:Intent.CATEGORY_LAUNCHER或Intent.CATEGORY_MONKEY。要指定多個類別,需要使用多個-c選項,每個-c選項只能用於一個類別。 調試dbg-no-events設置此選項,Monkey將執行初始啟動,進入到一個測試Activity,然後不會再進一步生成事件。為了得到最佳結果,把它與-v、一個或幾個包約束、以及一個保持Monkey運行30秒或更長時間的非零值聯合起來,從而提供一個環境,可以監視應用程序所調用的包之間的轉換。 hprof設置此選項,將在Monkey事件序列之前和之後立即生成profiling報告。這將會在data/misc中生成大文件(~5Mb),所以要小心使用它。 ignore-crashes通常,當應用程序崩潰或發生任何失控異常時,Monkey將停止運行。如果設置此選項,Monkey將繼續向系統發送事件,直到計數完成。 ignore-timeouts通常,當應用程序發生任何超時錯誤(如「Application NotResponding」對話框)時,Monkey將停止運行。如果設置此選項,Monkey將繼續向系統發送事件,直到計數完成。 ignore-security-exceptions通常,當應用程序發生許可錯誤(如啟動一個需要某些許可的Activity)時,Monkey將停止運行。如果設置了此選項,Monkey將繼續向系統發送事件,直到計數完成。 kill-process-after-error通常,當Monkey由於一個錯誤而停止時,出錯的應用程序將繼續處於運行狀態。當設置了此選項時,將會通知系統停止發生錯誤的進程。注意,正常的(成功的)結束,並沒有停止啟動的進程,設備只是在結束事件之後,簡單地保持在最後的狀態。 monitor-native-crashes監視並報告Android系統中本地代碼的崩潰事件。如果設置了--kill-process-after-error,系統將停止運行。
D. android 開發 activity 怎麼列印數據到控制台
java一般的列印辦法為System.out.println("");J2ME也是,在ide的控制台就可以看到效果。但是android平台,System.out.println("");你是看不到列印的消息的。因為android提供的列印方法為,Log.v,該對象需要導入 import android.util.Log;,然後就可以使用了。察看效果的地方,也不在ide的console面板中,而在android提供的log面板中,可以選擇ide右上角的debug模式,查看log面板。
下邊是為本教程,寫的測試代碼
package com.google.android.testlog;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
/*本教程版權為http://blog。csdn。net/wudifeng 博客主人所有,代碼隨意使用,如想轉載請表明出處,這是對寫教程人得起碼尊重,謝謝:)
*/
public class testlog extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
Log.v("debug", "message............");
}
}
E. android 錯誤日誌 哪裡
1、創建MyCrashHandler類
package com.example.yu.myapplication;
import android.content.Context;
import android.os.Environment;
import android.util.Log;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.Date;
/**
* 全局捕獲導常,保存到本地錯誤日誌。日誌
* 路徑位於sdcard/錯誤日誌Log/myErrorLog下。
*/
public class MyCrashHandler implements UncaughtExceptionHandler {
private static MyCrashHandler instance;
public static MyCrashHandler getInstance() {
if (instance == null) {
instance = new MyCrashHandler();
}
return instance;
}
public void init(Context ctx) {
Thread.(this);
}
/**
* 核心方法,當程序crash 會回調此方法, Throwable中存放這錯誤日誌
*/
@Override
public void uncaughtException(Thread arg0, Throwable arg1) {
String logPath;
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
logPath = Environment.getExternalStorageDirectory()
.getAbsolutePath()
+ File.separator
+ File.separator
+ "錯誤日誌Log";
File file = new File(logPath);
if (!file.exists()) {
file.mkdirs();
}
try {
FileWriter fw = new FileWriter(logPath + File.separator
+ "myErrorlog.log", true);
fw.write(new Date() + "錯誤原因:\n");
// 錯誤信息
// 這里還可以加上當前的系統版本,機型型號 等等信息
StackTraceElement[] stackTrace = arg1.getStackTrace();
fw.write(arg1.getMessage() + "\n");
for (int i = 0; i < stackTrace.length; i++) {
fw.write("file:" + stackTrace[i].getFileName() + " class:"
+ stackTrace[i].getClassName() + " method:"
+ stackTrace[i].getMethodName() + " line:"
+ stackTrace[i].getLineNumber() + "\n");
}
fw.write("\n");
fw.close();
// 上傳錯誤信息到伺服器
// uploadToServer();
} catch (IOException e) {
Log.e("crash handler", "load file failed...", e.getCause());
}
}
arg1.printStackTrace();
android.os.Process.killProcess(android.os.Process.myPid());
}
}
F. 如何獲取 android 的系統日誌 logcat
1. 只顯示需要的輸出,白名單
最方便的當然是通過管道使用 grep 過濾了,這樣可以使用 grep 強大的正則表達式匹配。簡單的匹配一行當中的某個字元串,例如 MyApp:
adb logcat | grep MyApp
adb logcat | grep -i myapp #忽略大小寫。
adb logcat | grep --color=auto -i myapp #設置匹配字元串顏色。更多設置請查看 grep 幫助。
進階一點可以使用 grep 的正則表達式匹配。例如上一個例子會匹配一行中任意位置的 MyApp,可以設置為僅匹配 tag。默認的 log 輸出如下,如果修改過輸出格式相應的表達式也要修改。
I/CacheService( 665): Preparing DiskCache for all thumbnails.
可以看出 tag 是一行開頭的第三個字元開始,根據這點寫出表達式:
adb logcat | grep "^..MyApp"
根據這個格式也可以設置只顯示某個優先順序的 log,再匹配行首第一個字元即可。例如僅顯示 Error 級別 tag 為 MyApp 的輸出:
adb logcat | grep "^E.MyApp"
當然也可以匹配多個,使用 | 分割多個匹配表達式,要加轉義符。例如要匹配 tag 為 MyApp 和 MyActivity 的輸出:
adb logcat | grep "^..MyApp\|^..MyActivity"
adb logcat | grep -E "^..MyApp|^..MyActivity" #使用 egrep 無須轉義符
2. 過濾不需要的輸出,黑名單
還是使用 grep,用法也跟上面的一樣,加一個 -v 即可。例如要過濾 tag 為 MyApp 和 MyActivity 的輸出:
adb logcat | grep -v "^..MyApp\|^..MyActivity"
adb logcat | grep -vE "^..MyApp|^..MyActivity" #使用 egrep 無須轉義符
3. 顯示同一個進程的所有輸出
有時一個程序裡面的 tag 有多個,需要輸出該程序(同一個 PID)的所有 tag;僅使用 tag 過濾有時也會漏掉一些錯誤信息,而一般錯誤信息也是和程序同一個 PID。還是通過 grep 實現,思路是先根據包名找到 pid 號,然後匹配 pid。寫成 shell 腳本如下,參數是程序的 java 包名(如 com.android.media)。
查看源代碼列印幫助\
#!/bin/bash
packageName=$1
pid=`adb shell ps | grep $packageName | awk '{print $2}'`
adb logcat | grep --color=auto $pid
4. 從當前開始顯示
logcat 有緩存,如果僅需要查看當前開始的 log,需要清空之前的。adb logcat -c && adb logcat
5. 過濾 log 文件
有時需要分析 log 文件,過濾 log 文件還是使用 grep。例如 log 文件為 myapp.log,要匹配 tag 為 MyApp 和 MyActivity 的輸出,然後輸出到 newmyapp.log:cat myapp.log | grep "^..MyApp\|^..MyActivity" > newmyapp.log
Windows 下推薦使用 Notepad++,一個免費強大的記事本,支持正則表達式查找替換。可以高亮顯示匹配內容,也可以刪除不需要的內容。
以上的技巧主要用到了 grep,其實 logcat 本身也有過濾功能,可以根據 tag、優先順序過濾 log,具體請參考 Android 官方文檔 Reading and Writing Logs。如果喜歡使用圖形界面,請參考 Using DDMS,DDMS 裡面的 logcat 也可以同樣過濾。