解決Android啟動過程中Log丟失問題的方案
在Android開發中,遇到需要Debug啟動過程中的問題時,往往會因為在啟動過程中log丟失而異常麻煩,為此我們用了下面這個簡單的方案。
假設你的應用或者framework的某些服務需要在開機時越快啟動越好,那麼在啟動過程中某些log會丟失,但是程式的邏輯不會丟失,為此我們可以把需要分析的關鍵部位的log快取在記憶體中,等到問題出現後系統穩定後再通過某些方式把快取的log資訊讀出來,因為log是存在記憶體中的,所以不會有任何的丟失。
為了做到程式的靈活性,我們使用了檢測檔案是否存在來開啟和關閉快取功能,這樣我們可以快取功能的程式碼嵌入到程式本身,平時它都不會執行,只有當需要的時候,在特定的目錄下建立一個檔案後,它才會執行。同時為了不改變應用程式本身的程式碼就能讀取快取的資訊,我們使用接收廣播的形式來列印,下面是程式的原始碼,歡迎提供你的寶貴意見和建議:
package ;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.Message;
import android.os.Process;
import android.util.Log;
public class LogAssist {
private static final String TAG = "LogAssist";
//control command
private static final String ACTION_PRINT = "action.logassist.print";
private static final String ACTION_CONTROL_PAUSE = "action.logassist.control.pause";
private static final String ACTION_CONTROL_RESUME = "action.logassist.control.resume";
private static final String ACTION_CONTROL_CLEAR = "action.logassist.control.clear";
//delay time to print the buffered log (ms)
private static final String ACTION_EXTRA_DELAY2PRINT = "delay";
//msg to print the log
private static final int MSG_PRINT = 2008;
//switch the log assist on or off by adding/removing this file
private static final String SWITCHER_FILE = "/data/data/com./logassist_enabled";
//maxium buffer used to cache the log
private static final int MAX_BUFFER_SIZE = 10241000;
//buffer size to clear when it is full
private static final int BUFFER_SIZE_TO_CLEAR = 512;
//start line of the log
private static final String STR_LOG_START_LINE = "----------------LogAssist Print------------\n";
static StringBuffer mLogBuffer;
static SimpleDateFormat mDateFormat;
static boolean mStarted = false;
static int mPid;
static Handler mPrintHandler = null;
public static void init(Context context) {
if (!needStart()) {
Log.d(TAG, "LogAssist is not enabled.");
return;
}
mLogBuffer = new StringBuffer(STR_LOG_START_LINE);
mDateFormat = new SimpleDateFormat("dd-M-yyyy hh:mm:ss.SSS");
mStarted = true;
mPid = Process.myPid();
registerControlReceiver(context);
Log.d(TAG, "LogAssist is enabled.");
}
static class PrintHandlerCallBack implements Handler.Callback {
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case MSG_PRINT:
print();
break;
}
return false;
}
}
private static void registerControlReceiver(Context context) {
BroadcastReceiver controlReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "received intent :"+intent.getAction());
if (intent == null) {
return;
}
String action = intent.getAction();
if (ACTION_PRINT.equals(action)) {
int delay = intent.getIntExtra(ACTION_EXTRA_DELAY2PRINT, 0);
Log.d(TAG, " intent :delay="+delay);
if (delay <=0) {
print();
} else {
if (mPrintHandler == null) {
mPrintHandler = new Handler(new PrintHandlerCallBack());
}
mPrintHandler.sendEmptyMessageDelayed(MSG_PRINT, delay);
}
} else if (ACTION_CONTROL_PAUSE.equals(action)) {
mStarted = false;
}else if (ACTION_CONTROL_RESUME.equals(action)) {
mStarted = true;
}else if (ACTION_CONTROL_CLEAR.equals(action)) {
mLogBuffer = new StringBuffer(STR_LOG_START_LINE);
}
}
};
IntentFilter ctrlIntentFilter = new IntentFilter();
ctrlIntentFilter.addAction(ACTION_PRINT);
ctrlIntentFilter.addAction(ACTION_CONTROL_PAUSE);
ctrlIntentFilter.addAction(ACTION_CONTROL_RESUME);
ctrlIntentFilter.addAction(ACTION_CONTROL_CLEAR);
context.registerReceiver(controlReceiver, ctrlIntentFilter);
}
//check the switch file to see we need run log assist
private static boolean needStart() {
File switcher = new File(SWITCHER_FILE);
return switcher.exists();
}
public static void log(String info) {
if (!mStarted) {
return;
}
if (mLogBuffer.length() >= MAX_BUFFER_SIZE) {
//if buffer is full, remove first part defined by BUFFER_SIZE_TO_CLEAR
if (mLogBuffer.length() > BUFFER_SIZE_TO_CLEAR) {
//if the cached size is bigger than size to be cleared
mLogBuffer.delete(0, BUFFER_SIZE_TO_CLEAR);
} else {
//if the cached size is not bigger than size to be cleared, reset the buffer
mLogBuffer = new StringBuffer(STR_LOG_START_LINE);
}
}
String date = mDateFormat.format(new Date());
int tid = Process.myTid();
mLogBuffer.append(date + " " + mPid + " " + tid + " " + info + "\n");
}
private static void print() {
if (mLogBuffer != null) {
Log.i(TAG, mLogBuffer.toString());
}
}
}