package com.jecelyin.util; import java.util.HashMap; import android.app.ActivityManager; import android.app.Application; import android.app.ActivityManager.MemoryInfo; import android.content.Context; import android.content.Intent; import android.graphics.Point; import android.util.Log; import android.view.Display; import android.view.WindowManager; import android.widget.Toast; import com.jecelyin.editor.JecEditor; public class JecLog { private static Application mApp; public static void init(Application editor) { mApp = editor; } public static void e(String msg) { e(msg, null); } public static void e(final String msg, final Throwable th) { Log.e("JecEditor_ERROR", msg, th); new Thread(){ public void run() { String trace = createCrashDataString(th); Intent dialogIntent = new Intent(mApp, CrashReportDialog.class); dialogIntent.putExtra("msg", msg); dialogIntent.putExtra("trace", trace); dialogIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mApp.startActivity(dialogIntent); android.os.Process.killProcess(android.os.Process.myPid()); System.exit(10); } }.start(); //android.os.Process.killProcess(android.os.Process.myPid()); //System.exit(10); } public static void d(String msg) { d(msg, null); } public static void d(String msg, Throwable th) { Log.d("JecEditor_DEBUG", msg, th); } public static void msg(String msg) { msg(msg, null); } public static void msg(String msg, Throwable th) { if(th != null) th.printStackTrace(); Toast.makeText(mApp, msg, Toast.LENGTH_LONG).show(); } /** * Collects crash data. * * @param th * Throwable that caused the crash. * @return CrashReportData representing the current state of the application * at the instant of the Exception. */ public static HashMap<String, String> createCrashData(Throwable th) { final HashMap<String, String> crashReportData = new HashMap<String, String>(); crashReportData.put("APP_VERSION_NAME", JecEditor.version); // Device model crashReportData.put("PHONE_MODEL", android.os.Build.BRAND+" "+android.os.Build.MODEL); // Android version crashReportData.put("ANDROID_VERSION", android.os.Build.VERSION.RELEASE); WindowManager wm = (WindowManager) mApp.getSystemService(Context.WINDOW_SERVICE); Display display = wm.getDefaultDisplay(); crashReportData.put("SCREEN", display.getWidth()+"x"+display.getHeight()); // Device Memory ActivityManager activityManager = (ActivityManager) mApp.getSystemService(Context.ACTIVITY_SERVICE); MemoryInfo memoryInfo = new ActivityManager.MemoryInfo(); activityManager.getMemoryInfo(memoryInfo); crashReportData.put("FREE_MEM", Long.toString(memoryInfo.availMem/1024/1024)+"M"); crashReportData.put("STACK_TRACE", getStackTrace(th)); return crashReportData; } /** * Generates the string which is posted in the single custom data field in * the GoogleDocs Form. * * @return A string with a 'key = value' pair on each line. */ public static String createCrashDataString(Throwable th) { HashMap<String, String> crashReportData = createCrashData(th); final StringBuilder customInfo = new StringBuilder(); for (final String currentKey : crashReportData.keySet()) { String currentVal = crashReportData.get(currentKey); customInfo.append(currentKey); customInfo.append(": "); customInfo.append(currentVal); customInfo.append("\n"); } return customInfo.toString(); } private static String getStackTrace(Throwable th) { if(th == null) return ""; StringBuilder sb = new StringBuilder(); for (StackTraceElement element : th.getStackTrace()) { if(element.toString().indexOf("jecelyin") > -1) sb.append("\tat ").append(element).append("\n"); } // If the exception was thrown in a background thread inside // AsyncTask, then the actual exception can be found with getCause Throwable cause = th.getCause(); while (cause != null) { sb.append("Caused by: ").append(cause.toString()).append("\n"); for (StackTraceElement element : cause.getStackTrace()) { if(element.toString().indexOf("jecelyin") > -1) sb.append("\tat ").append(element).append("\n"); } cause = cause.getCause(); } return sb.toString(); } }