1 /* 2 * libjingle 3 * Copyright 2013, Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 package org.appspot.apprtc; 29 30 import android.app.Activity; 31 import android.app.AlertDialog; 32 import android.content.DialogInterface; 33 import android.util.Log; 34 import android.util.TypedValue; 35 import android.widget.ScrollView; 36 import android.widget.TextView; 37 38 import java.io.PrintWriter; 39 import java.io.StringWriter; 40 41 /** 42 * Singleton helper: install a default unhandled exception handler which shows 43 * an informative dialog and kills the app. Useful for apps whose 44 * error-handling consists of throwing RuntimeExceptions. 45 * NOTE: almost always more useful to 46 * Thread.setDefaultUncaughtExceptionHandler() rather than 47 * Thread.setUncaughtExceptionHandler(), to apply to background threads as well. 48 */ 49 public class UnhandledExceptionHandler 50 implements Thread.UncaughtExceptionHandler { 51 private static final String TAG = "AppRTCDemoActivity"; 52 private final Activity activity; 53 54 public UnhandledExceptionHandler(final Activity activity) { 55 this.activity = activity; 56 } 57 58 public void uncaughtException(Thread unusedThread, final Throwable e) { 59 activity.runOnUiThread(new Runnable() { 60 @Override public void run() { 61 String title = "Fatal error: " + getTopLevelCauseMessage(e); 62 String msg = getRecursiveStackTrace(e); 63 TextView errorView = new TextView(activity); 64 errorView.setText(msg); 65 errorView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 8); 66 ScrollView scrollingContainer = new ScrollView(activity); 67 scrollingContainer.addView(errorView); 68 Log.e(TAG, title + "\n\n" + msg); 69 DialogInterface.OnClickListener listener = 70 new DialogInterface.OnClickListener() { 71 @Override public void onClick( 72 DialogInterface dialog, int which) { 73 dialog.dismiss(); 74 System.exit(1); 75 } 76 }; 77 AlertDialog.Builder builder = 78 new AlertDialog.Builder(activity); 79 builder 80 .setTitle(title) 81 .setView(scrollingContainer) 82 .setPositiveButton("Exit", listener).show(); 83 } 84 }); 85 } 86 87 // Returns the Message attached to the original Cause of |t|. 88 private static String getTopLevelCauseMessage(Throwable t) { 89 Throwable topLevelCause = t; 90 while (topLevelCause.getCause() != null) { 91 topLevelCause = topLevelCause.getCause(); 92 } 93 return topLevelCause.getMessage(); 94 } 95 96 // Returns a human-readable String of the stacktrace in |t|, recursively 97 // through all Causes that led to |t|. 98 private static String getRecursiveStackTrace(Throwable t) { 99 StringWriter writer = new StringWriter(); 100 t.printStackTrace(new PrintWriter(writer)); 101 return writer.toString(); 102 } 103 } 104