/** * This file is part of CrashCatcher library. * Copyright (c) 2014, Sibext Ltd. (http://www.sibext.com), * All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. * * This library 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 Lesser General Public License * for more details (http://www.gnu.org/licenses/lgpl-3.0.txt). * * You should have received a copy of the GNU Lesser General Public * License along with this library. */ package com.sibext.android.manager; import android.app.Activity; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.util.Log; import com.sibext.android.activity.EmailReportActivity; import com.sibext.android.tools.CatchActivity; import com.sibext.android.tools.StackTraceHelper; import com.sibext.crashcatcher.R; public class CrashCatcherManager { private static final String TAG = "[CCL] CrashCatcherManager"; public static final String MANUAL_FLAG_KEY = "MANUAL_FLAG_KEY"; private Context context; private Class<?> catchClass = null; private void init() { catchClass = getCatchClass(); Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { private volatile boolean alreadyCrashed = false; @Override public void uncaughtException(Thread paramThread, final Throwable e) { if ( alreadyCrashed ) { return; } alreadyCrashed = true; final String stackTrace = StackTraceHelper.getStackTrace(e); Log.e(TAG, "Error: " + stackTrace); try { sendReport(stackTrace, false); } catch (Throwable e1) { Log.e(TAG, "Can't handle the crash", e1); } } }); } public void manualSendReport() { sendReport("Manual", true); } private void sendReport(String stackTrace, final boolean manual) { final Class reporterClass = ( null == catchClass ? getDefaultReporterClass() : catchClass ); final Intent crashedIntent = new Intent(context.getApplicationContext(), reporterClass); crashedIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); crashedIntent.putExtra(CatchActivity.TRACE_INFO, stackTrace); crashedIntent.putExtra(MANUAL_FLAG_KEY, manual); final PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, crashedIntent, 0); ( (Activity)context ).runOnUiThread(new Runnable() { public void run() { try { pendingIntent.send(context.getApplicationContext(), 0, null); if ( manual ) { Log.d(TAG, "sent manual report"); } else { Log.d(TAG, "sent new crash"); android.os.Process.killProcess(android.os.Process.myPid()); System.exit(10); } } catch (PendingIntent.CanceledException e) { Log.d(TAG, "Can't start activity", e); } } }); } public void register(Context c) { this.context = c; init(); } public void unRegister() { context = null; } protected Class<?> getDefaultReporterClass() { return EmailReportActivity.class; } private Class<?> getCatchClass() { Class<?> catchClass = null; try { Log.d(TAG, "get catch class: " + context.getPackageName()); final ApplicationInfo ai = context.getPackageManager() .getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA); if ( ai != null ) { final String reporterKey = context.getString(R.string.metadata_reporter_key); final String className = ai.metaData.getString(reporterKey); if ( null != className ) { catchClass = Class.forName(className); } } } catch (NameNotFoundException e) { Log.e(TAG, "Can't get init params", e); } catch (ClassNotFoundException e1) { Log.w(TAG, "Using default reporter..."); } return catchClass; } }