在写Android程序时,经常碰到在模拟器和调试器中无法捕捉的exception。有时自己运行好好的程序到了其他机器上就出现了问题。虽然Google Play有错误堆栈上传功能,但是没有办法把整个运行的过程记录下来。为此我写了一个LogDog类来试图解决这个问题。
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.Thread.UncaughtExceptionHandler;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.HashSet;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.os.Environment;
import android.os.Looper;
//import android.util.Log;
import android.util.Log;
public class LogDog implements UncaughtExceptionHandler {
public static String TAG = "LogDog";
private static HashSet _tags = new HashSet();
private static boolean _debug = false;
static {
// add tags to be captured
_tags.add(PDFMaster.TAG);
_tags.add(RecentlyUsedActivity.TAG);
_tags.add(DB.TAG);
}
public static LogDog instance() {
return _instance;
}
public static void i(String tag, String message) {
if(_debug) {
Log.i(tag, message);
return;
}
PrintWriter writer = _instance.getWriter();
if(writer != null && _tags.contains(tag)) {
_instance._writer.println("i:" + tag + ":" + message);
}
}
public static void e(String tag, String message) {
if(_debug) {
Log.i(tag, message);
return;
}
PrintWriter writer = _instance.getWriter();
if(writer != null && _tags.contains(tag)) {
_instance._writer.println("e" + tag + ":" + message);
}
}
public static void w(String tag, String message) {
if(_debug) {
Log.i(tag, message);
return;
}
PrintWriter writer = _instance.getWriter();
if(writer != null && _tags.contains(tag)) {
_instance._writer.println("w" + tag + ":" + message);
}
}
public void init(Context context) {
_context = context;
_fileName = _context.getString(R.string.app_name) + ".log";
_defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this);
}
public void close() {
if(_writer != null) {
_writer.close();
_writer = null;
}
}
// private
private static LogDog _instance = new LogDog();
private static final String PATH =
Environment.getExternalStorageDirectory().getPath() + "/log";
private Context _context;
private String _fileName;
private Thread.UncaughtExceptionHandler _defaultHandler;
private PrintWriter _writer = null;
private LogDog() {
}
private PrintWriter getWriter() {
if(_writer != null)
return _writer;
// check if we have SD card
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
//Log.w(TAG, "sdcard unmounted,skip dump exception");
return null;
}
File dir = new File(PATH);
if (!dir.exists()) {
dir.mkdirs();
}
File file = new File(PATH + "/" + _fileName);
try {
_writer = new PrintWriter(new BufferedWriter(new FileWriter(file)));
} catch (IOException e) {
//Log.e(TAG, "Failed to open " + PATH + "/" + FILE_NAME);
_writer = null;
}
return _writer;
}
@Override
public void uncaughtException(Thread thread, Throwable ex) {
// first display a toast message
new Thread() {
@Override
public void run() {
Looper.prepare();
PDFMarkerApp.instance().showToast("Sorry for the trouble, dumping uncaught exeption to SD card");
}
}.start();
try {
dump(ex);
} catch (Exception e) {
//Log.e(TAG, "Failed to dump because " + e.getMessage());
e.printStackTrace();
}
if (_defaultHandler != null) {
_defaultHandler.uncaughtException(thread, ex);
} else {
// sleep so the toast can have time to display
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
}
android.os.Process.killProcess(android.os.Process.myPid());
}
}
private void dump(Throwable ex) throws IOException, NameNotFoundException {
PrintWriter writer = _instance.getWriter();
if(writer == null)
return;
long current = System.currentTimeMillis();
String time = new SimpleDateFormat("yyyyMMdd.HHmmss").format(new Date(current));
_writer.println(time);
PackageManager pm = _context.getPackageManager();
PackageInfo pi = pm.getPackageInfo(_context.getPackageName(), PackageManager.GET_ACTIVITIES);
_writer.print("App Version: ");
_writer.print(pi.versionName);
_writer.print('_');
_writer.println(pi.versionCode);
_writer.print("OS Version: ");
_writer.print(Build.VERSION.RELEASE);
_writer.print("_");
_writer.println(Build.VERSION.SDK_INT);
_writer.print("Vendor: ");
_writer.println(Build.MANUFACTURER);
_writer.print("Model: ");
_writer.println(Build.MODEL);
_writer.print("CPU ABI: ");
_writer.println(Build.CPU_ABI);
_writer.println();
ex.printStackTrace(_writer);
close();
File file = new File(PATH + "/" + _fileName);
File file2 = new File(PATH + "/" + _fileName + "." + time + ".txt");
file.renameTo(file2);
}
}
在使用时所有的日志就全记录在一个文件中,直到最后的异常。每次异常都会单独被记录在一个文件中,连带所有需要知道的信息。要是正常运行,这个文件下次就被覆盖,不会造成空间问题。要是调试,只要把_debug改一下,所有日志就在LogCat中显示出来,非常方便。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。