Back to project page Common-Library.
The source code is released under:
Apache License
If you think the Android project Common-Library listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
package com.morgan.library.snippet; /* w w w . j av a 2 s .c om*/ import java.io.File; import java.io.FileOutputStream; import java.io.FilenameFilter; import java.io.PrintWriter; import java.io.StringWriter; import java.io.Writer; import java.lang.Thread.UncaughtExceptionHandler; import java.lang.reflect.Field; import java.util.Arrays; import java.util.Properties; import java.util.TreeSet; 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.Looper; import android.text.format.Time; import android.util.Log; import android.view.Gravity; import android.widget.Toast; public class ExceptionCatcher implements UncaughtExceptionHandler { /** Debug Log tag */ public static final String TAG = "CrashHandler"; /** * ????????????,?Debug????????, ?Release???????????????? * */ public static final boolean DEBUG = false; /** ?????UncaughtException????? */ private Thread.UncaughtExceptionHandler mDefaultHandler; /** CrashHandler?? */ private static ExceptionCatcher INSTANCE; /** ????Context?? */ private Context mContext; /** ??Properties?????????????????????? */ private Properties mDeviceCrashInfo = new Properties(); private static final String VERSION_NAME = "versionName"; private static final String VERSION_CODE = "versionCode"; private static final String STACK_TRACE = "STACK_TRACE"; /** ???????????? */ private static final String CRASH_REPORTER_EXTENSION = ".cr"; /** ??????????CrashHandler?? */ private ExceptionCatcher() { } /** ????CrashHandler?? ,??????? */ public static ExceptionCatcher getInstance() { if (INSTANCE == null) { INSTANCE = new ExceptionCatcher(); } return INSTANCE; } /** * ????,??Context??, ?????????UncaughtException?????, ???CrashHandler???????????? * * @param ctx */ public void init(Context ctx) { mContext = ctx; mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); Thread.setDefaultUncaughtExceptionHandler(this); } /** * ?UncaughtException?????????????????? */ @Override public void uncaughtException(Thread thread, Throwable ex) { if (!handleException(ex) && mDefaultHandler != null) { // ??????????????????????????????? mDefaultHandler.uncaughtException(thread, ex); } else { // Sleep???????????? try { Thread.sleep(5000); } catch (InterruptedException e) { Log.e(TAG, "Error : ", e); } android.os.Process.killProcess(android.os.Process.myPid()); System.exit(10); } } /** * ?????????,???????? ?????????????????????. ???????????????????????????????? * * @param ex * @return true:??????????????;??????false */ private boolean handleException(Throwable ex) { if (ex == null) { Log.w(TAG, "handleException --- ex==null"); return true; } final String msg = ex.getLocalizedMessage(); if (msg == null) { return false; } // ??Toast??????????? new Thread() { @Override public void run() { Looper.prepare(); Toast toast = Toast.makeText(mContext, "????????????:\r\n" + msg, Toast.LENGTH_LONG); toast.setGravity(Gravity.CENTER, 0, 0); toast.show(); // MsgPrompt.showMsg(mContext, "??????", msg+"\n?????"); Looper.loop(); } }.start(); // ???????? collectCrashDeviceInfo(mContext); // ????????? saveCrashInfoToFile(ex); // ?????????????? sendCrashReportsToServer(mContext); return true; } /** * ??????????, ?????????????????????????????? */ public void sendPreviousReportsToServer() { sendCrashReportsToServer(mContext); } /** * ???????????????,???????????????????. * * @param ctx */ private void sendCrashReportsToServer(Context ctx) { String[] crFiles = getCrashReportFiles(ctx); if (crFiles != null && crFiles.length > 0) { TreeSet<String> sortedFiles = new TreeSet<String>(); sortedFiles.addAll(Arrays.asList(crFiles)); for (String fileName : sortedFiles) { File cr = new File(ctx.getFilesDir(), fileName); postReport(cr); cr.delete();// ??????????? } } } private void postReport(File file) { // TODO ?????????????? } /** * ????????????? * * @param ctx * @return */ private String[] getCrashReportFiles(Context ctx) { File filesDir = ctx.getFilesDir(); FilenameFilter filter = new FilenameFilter() { public boolean accept(File dir, String name) { return name.endsWith(CRASH_REPORTER_EXTENSION); } }; return filesDir.list(filter); } /** * ????????????? * * @param ex * @return */ private String saveCrashInfoToFile(Throwable ex) { Writer info = new StringWriter(); PrintWriter printWriter = new PrintWriter(info); ex.printStackTrace(printWriter); Throwable cause = ex.getCause(); while (cause != null) { cause.printStackTrace(printWriter); cause = cause.getCause(); } String result = info.toString(); printWriter.close(); mDeviceCrashInfo.put("EXEPTION", ex.getLocalizedMessage()); mDeviceCrashInfo.put(STACK_TRACE, result); try { // long timestamp = System.currentTimeMillis(); Time t = new Time("GMT+8"); t.setToNow(); // ???????? int date = t.year * 10000 + t.month * 100 + t.monthDay; int time = t.hour * 10000 + t.minute * 100 + t.second; String fileName = "crash-" + date + "-" + time + CRASH_REPORTER_EXTENSION; FileOutputStream trace = mContext.openFileOutput(fileName, Context.MODE_PRIVATE); mDeviceCrashInfo.store(trace, ""); trace.flush(); trace.close(); return fileName; } catch (Exception e) { Log.e(TAG, "an error occured while writing report file...", e); } return null; } /** * ?????????????? * * @param ctx */ public void collectCrashDeviceInfo(Context ctx) { try { PackageManager pm = ctx.getPackageManager(); PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES); if (pi != null) { mDeviceCrashInfo.put(VERSION_NAME, pi.versionName == null ? "not set" : pi.versionName); mDeviceCrashInfo.put(VERSION_CODE, "" + pi.versionCode); } } catch (NameNotFoundException e) { Log.e(TAG, "Error while collect package info", e); } // ?????????????????.?Build?????????????????, // ??: ???????,????? ??????????????? // ???????????????????? Field[] fields = Build.class.getDeclaredFields(); for (Field field : fields) { try { field.setAccessible(true); mDeviceCrashInfo.put(field.getName(), "" + field.get(null)); if (DEBUG) { Log.d(TAG, field.getName() + " : " + field.get(null)); } } catch (Exception e) { Log.e(TAG, "Error while collect crash info", e); } } } }