/* * Copyright (C) 2012-2016 The Android Money Manager Ex Project Team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 3 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.money.manager.ex.log; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Build; import android.os.Handler; import android.os.Looper; import android.util.Log; import android.widget.Toast; import com.crashlytics.android.Crashlytics; import com.money.manager.ex.Constants; import com.money.manager.ex.MoneyManagerApplication; import com.money.manager.ex.R; import java.io.PrintWriter; import java.io.StringWriter; /** * Deprecated. Replace with calls to Timber, which uses the new production logger. * Default exception handler. * Used for reporting uncaught exceptions before using Crashlytics. */ @Deprecated public class ExceptionHandler implements Thread.UncaughtExceptionHandler { // public static void log(String message) { // Log.i("manual", message); // Crashlytics.log(message); // } public static void warn(String message) { Log.w("manual", message); Crashlytics.log(message); } public ExceptionHandler(Context context) { mContext = context; mHost = context; } /** * Basic constructor * @param context Context / activity. * @param host The class where the exception originates. Used to get the class name * for Logcat. */ public ExceptionHandler(Context context, Object host) { mContext = context; mHost = host; // this.originalHandler = Thread.getDefaultUncaughtExceptionHandler(); } private final String LINE_SEPARATOR = "\n"; private Context mContext; private Object mHost; public Context getContext() { return mContext; } public void e(Exception ex, String errorMessage) { this.e((Throwable) ex, errorMessage); } public void e(Throwable t, String errorMessage) { errorMessage = String.format("Error %s:\n%s", errorMessage, t.getLocalizedMessage()); String version = getAppVersion() + "." + getAppBuildNumber(); Log.e(getLogcat(), "version: " + version + ": " + errorMessage + ": " + t.getLocalizedMessage()); t.printStackTrace(); showMessage(errorMessage); //Crashlytics.getInstance().crash(); Crashlytics.logException(t); } private String getLogcat() { if (mHost != null) { return mHost.getClass().getSimpleName(); } else { return "unknown"; } } public void showMessage(int resourceId) { showMessage(getContext().getString(resourceId)); } public void showMessage(final String message) { showMessage(message, Toast.LENGTH_SHORT); } /** * Display a toast message. * @param message Message text to display. * @param length Length of display. See Toast.Long and Toast.Short. * reference: http://stackoverflow.com/questions/18705945/android-cant-create-handler-inside-thread-that-has-not-called-looper-prepare */ public void showMessage(final String message, final int length) { if (this.mContext == null) return; Handler h = new Handler(Looper.getMainLooper()); h.post(new Runnable() { public void run() { try { Toast.makeText(mContext, message, length).show(); } catch (Exception e) { Log.e(getLogcat(), "Error showing toast: " + e.getMessage()); } } }); } @Override public void uncaughtException(Thread thread, Throwable throwable) { StringWriter stackTrace = new StringWriter(); throwable.printStackTrace(new PrintWriter(stackTrace)); StringBuilder errorReport = new StringBuilder(); errorReport.append("************ FEEDBACK ************\n"); errorReport.append("Please tell us what happened in the space below. Thank you!"); errorReport.append(LINE_SEPARATOR); errorReport.append(LINE_SEPARATOR); errorReport.append(LINE_SEPARATOR); errorReport.append("************ APP DETAILS ************\n"); String version = getAppVersionInformation(); errorReport.append(version); errorReport.append(LINE_SEPARATOR); errorReport.append("\n************ FIRMWARE ************\n"); errorReport.append("SDK: "); errorReport.append(Build.VERSION.SDK); errorReport.append(LINE_SEPARATOR); errorReport.append("Release: "); errorReport.append(Build.VERSION.RELEASE); errorReport.append(LINE_SEPARATOR); errorReport.append("Incremental: "); errorReport.append(Build.VERSION.INCREMENTAL); errorReport.append(LINE_SEPARATOR); errorReport.append(LINE_SEPARATOR); errorReport.append("************ CAUSE OF ERROR ************\n"); errorReport.append(stackTrace.toString()); errorReport.append("\n************ DEVICE INFORMATION ***********\n"); errorReport.append("Brand: "); errorReport.append(Build.BRAND); errorReport.append(LINE_SEPARATOR); errorReport.append("Device: "); errorReport.append(Build.DEVICE); errorReport.append(LINE_SEPARATOR); errorReport.append("Model: "); errorReport.append(Build.MODEL); errorReport.append(LINE_SEPARATOR); errorReport.append("Id: "); errorReport.append(Build.ID); errorReport.append(LINE_SEPARATOR); errorReport.append("Product: "); errorReport.append(Build.PRODUCT); errorReport.append(LINE_SEPARATOR); // Log.e(getLogcat(), errorReport.toString()); // showMessage(errorReport.toString()); // Intent intent = new Intent (); // intent.setAction ("com.mydomain.SEND_LOG"); // see step 5. // intent.setFlags (Intent.FLAG_ACTIVITY_NEW_TASK); // required when starting from Application // context.startActivity(intent); sendEmail(errorReport.toString()); // this.originalHandler.uncaughtException(thread, throwable); // android.os.Process.killProcess(android.os.Process.myPid()); // System.exit(10); System.exit(1); } // private private void sendEmail(String text) { Intent intent = new Intent (Intent.ACTION_SEND); intent.setType("plain/text"); intent.putExtra(Intent.EXTRA_EMAIL, new String[] { Constants.EMAIL }); intent.putExtra(Intent.EXTRA_SUBJECT, "Unexpected Exception Log"); // intent.putExtra (Intent.EXTRA_STREAM, Uri.parse("file://" + fullName)); intent.putExtra(Intent.EXTRA_TEXT, text); // do this so some email clients don't complain about empty body. // Title for the app selector // intent.putExtra(Intent.EXTRA_TITLE, "The app has crashed"); // context.startActivity(intent); Intent chooser = Intent.createChooser(intent, mContext.getString(R.string.unhandled_crash)); mContext.startActivity(chooser); } private String getAppVersionInformation() { if (getContext() == null) return ""; String result = ""; try { String version = getAppVersion(); result += "Version: " + version; result += LINE_SEPARATOR; String build = getAppBuildNumber(); result += "Build: " + build; } catch (Exception ex) { result = "Could not retrieve version information."; } return result; } private String getAppVersion() { String version; try { version = getContext().getPackageManager().getPackageInfo(mContext.getPackageName(), 0).versionName; } catch (Exception e) { version = "can't fetch"; } return version; } private String getAppBuildNumber() { try { return Integer.toString(getContext().getPackageManager().getPackageInfo(getContext().getPackageName(), 0).versionCode); } catch (PackageManager.NameNotFoundException e) { String message = "could not retrieve build number"; Crashlytics.log(message); return message; } } }