package system;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.Enumeration;
import java.util.Properties;
import util.Log;
import android.app.Activity;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import de.rwth.R;
/**
* use the {@link tools.ErrorHandler} instead </br></br></br></br></br></br>
*
* Register the {@link ErrorHandler} like this: </br>
* Thread.setDefaultUncaughtExceptionHandler(new ErrorHandler(currentActivity));
* </br></br>
*
* Or use the {@link ErrorHandler#registerNewErrorHandler(Activity)}
* method.</br></br>
*
* To add email support, call
* {@link ErrorHandler#enableEmailReports(String, String)} </br></br>
*
* And dont forget to add the ErrorReports.xml Layout file to your res/layout
* folder!</br></br>
*
* The ErrorHandler has to be registered in the AndroidManifest.xml like this:
*
* <p class=MsoNormal style='margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none'>
* <span style='font-size: 10.0pt;font-family:"Courier New";color:teal;mso-ansi
* -language:DE'><</span><span class=SpellE><span
* style='font-size:10.0pt;font-family:"Courier New";
* color:#3F7F7F;mso-ansi-language:DE'>activity</span></span><span
* style='font-size:10.0pt;font-family:"Courier New";mso-ansi-language:DE'>
* <span class=SpellE><span
* style='color:#7F007F'>android:name</span></span><span
* style='color:black'>=</span><i><span style='color:#2A00FF'>"<span
* class=SpellE>system.ErrorHandler</span>"</span></i> <span
* class=SpellE><span style='color:#7F007F'>android:process</span></span><span
* style='color:black'>=</span><i><span style='color:#2A00FF'>":<span
* class=SpellE>myexeptionprocess</span>"</span></i><o:p></o:p></span>
* </p>
*
* <p class=MsoNormal style='margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none'>
* <span style='font-size:
* 10.0pt;font-family:"Courier New";mso-ansi-language:DE'><span
* style='mso-tab-count: 1'>����� </span><span class=SpellE><span
* style='color:#7F007F'>android:taskAffinity</span></span><span
* style='color:black'>=</span><i><span style='color:#2A00FF'>"<span
* class=SpellE>system.ErrorHandler</span>"</span></i><span style='color:
* teal'>></span><o:p></o:p></span>
* </p>
*
* <p class=MsoNormal style='margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none'>
* <span style='font-size:
* 10.0pt;font-family:"Courier New";color:black;mso-ansi-language:DE'><span
* style='mso-tab-count:1'>����� </span></span><span style='font-size:10.0pt;
* font-family:"Courier New";color:teal;mso-ansi-language :DE'><</span><span
* class=SpellE><span style='font-size:10.0pt;font-family:"Courier New";
* color:#3F7F7F;mso-ansi-language:DE'>intent</span></span><span
* style='font-size: 10.0pt;font-family:"Courier New";color:#3F7F7F;mso-ansi-
* language:DE'>-filter</span><span style='font-size:10.0pt;font-family:"Courier
* New";color:teal;mso-ansi-language: DE'>></span><span
* style='font-size:10.0pt;font-family:"Courier New";
* mso-ansi-language:DE'><o:p></o:p></span>
* </p>
*
* <p class=MsoNormal style='margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none'>
* <span style='font-size:
* 10.0pt;font-family:"Courier New";color:black;mso-ansi-language:DE'><span
* style='mso-tab-count:2'>����������� </span></span><span
* style='font-size:10.0pt;
* font-family:"Courier New";color:teal;mso-ansi-language :DE'><</span><span
* class=SpellE><span style='font-size:10.0pt;font-family:"Courier New";
* color:#3F7F7F;mso-ansi-language:DE'>category</span></span><span
* style='font-size:10.0pt;font-family:"Courier New";mso-ansi-language:DE'>
* <span class=SpellE><span
* style='color:#7F007F'>android:name</span></span><span
* style='color:black'>=</span><i><span style='color:#2A00FF'>"<span
* class=SpellE>android.intent.category.DEFAULT</span>"</span></i> <span
* style='color:teal'>/></span><o:p></o:p></span>
* </p>
*
* <p class=MsoNormal style='margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none'>
* <span style='font-size:
* 10.0pt;font-family:"Courier New";color:black;mso-ansi-language:DE'><span
* style='mso-tab-count:1'>����� </span><span style='mso-tab-count:1'>�����
* </span></span><span style='font-size:10.0pt;font-family:"Courier
* New";color:teal;mso-ansi-language: DE'><</span><span class=SpellE><span
* style='font-size:10.0pt;font-family: "Courier New";color
* :#3F7F7F;mso-ansi-language:DE'>action</span></span><span
* style='font-size:10.0pt;font-family:"Courier New";mso-ansi-language:DE'>
* <span class=SpellE><span
* style='color:#7F007F'>android:name</span></span><span
* style='color:black'>=</span><i><span style='color:#2A00FF'>"<span
* class=SpellE>android.intent.action.VIEW</span>"</span></i> <span
* style='color:teal'>/></span><o:p></o:p></span>
* </p>
*
* <p class=MsoNormal style='margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none'>
* <span style='font-size:
* 10.0pt;font-family:"Courier New";color:black;mso-ansi-language:DE'><span
* style='mso-tab-count:1'>����� </span><span style='mso-tab-count:1'>�����
* </span></span><span style='font-size:10.0pt;font-family:"Courier
* New";color:teal;mso-ansi-language: DE'><</span><span class=SpellE><span
* style='font-size:10.0pt;font-family:
* "Courier New";color:#3F7F7F;mso-ansi-language:DE'>data</span></span><span
* style='font-size:10.0pt;font-family:"Courier New";mso-ansi-language:DE'>
* <span class=SpellE><span
* style='color:#7F007F'>android:mimeType</span></span><span
* style='color:black'>=</span><i><span style='color:#2A00FF'>"<span
* class=SpellE>errors</span>/<span
* class=SpellE>myUnhandleCatcher</span>"</span></i> <span
* style='color:teal'>/></span><o:p></o:p></span>
* </p>
*
* <p class=MsoNormal style='margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none'>
* <span style='font-size:
* 10.0pt;font-family:"Courier New";color:black;mso-ansi-language:DE'><span
* style='mso-tab-count:1'>����� </span></span><span style='font-size:10.0pt;
* font-family:"Courier New";color:teal;mso-ansi-language :DE'></</span><span
* class=SpellE><span style='font-size:10.0pt;font-family:"Courier New";
* color:#3F7F7F;mso-ansi-language:DE'>intent</span></span><span
* style='font-size: 10.0pt;font-family:"Courier New";color:#3F7F7F;mso-ansi-
* language:DE'>-filter</span><span style='font-size:10.0pt;font-family:"Courier
* New";color:teal;mso-ansi-language: DE'>></span><span
* style='font-size:10.0pt;font-family:"Courier New";
* mso-ansi-language:DE'><o:p></o:p></span>
* </p>
*
* <p class=MsoNormal>
* <span style='font-size:10.0pt;line-height:115%;font-family:
* "Courier New";color:teal;mso-ansi-language:DE'></</span><span
* class=SpellE><span
* style='font-size:10.0pt;line-height:115%;font-family:"Courier
* New";color:#3F7F7F; mso-ansi-language:DE'>activity</span></span><span
* style='font-size:10.0pt; line-height:115%;font-family:"Courier New";color:
* teal;mso-ansi-language:DE'>></span>
* </p>
*
* @author Spobo
*
*/
@Deprecated
public class ErrorHandler extends Activity implements UncaughtExceptionHandler {
/**
* must be the same "x/y" string as in the AndroidManifest. </br></br>
*
*
* see {@link ErrorHandler} to understand where this is defined in the
* manifest
*/
public static final String DEFINED_TYPE = "errors/myUnhandleCatcher";
private static Activity myCurrentActivity;
private static UncaughtExceptionHandler defaultHandler;
private static String myDeveloperMailAdress;
private static String myMailSubject = "Error in DroidAR";
private static final String PASSED_ERROR_TEXT_ID = "Error Text";
private static final CharSequence ERROR_ACTIVITY_TITLE = "Error :(";
private static final String DEV_MAIL = "dev mail";
private static final String TITLE_MAIL = "title mail";
private static final int ERROR_WINDOW_ID = R.layout.errorreports;
private static final int ERROR_TEXT_VIEW_ID = R.id.errorText;
private static final int ERROR_MAIL_BUTTON_ID = R.id.errorMailButton;
private static final String LOG_TAG = "ErrorHandler";
/**
* use the {@link ErrorHandler#ErrorHandler(Activity) constructor instead}.
* This constructor is required by the Android system and the
* {@link ErrorHandler} can only work properly if a activity is provided, so
* only use this constructor if you call
* {@link ErrorHandler#setCurrentActivity(Activity)} later!
*/
@Deprecated
public ErrorHandler() {
if (defaultHandler == null) {
defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
}
}
/**
* See {@link ErrorHandler} for details
*
* @param a
*/
public ErrorHandler(Activity a) {
setCurrentActivity(a);
if (defaultHandler == null) {
defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
}
}
public static void showErrorLog(Activity a, Exception errorToShow,
boolean keepBrokenProcessRunning) {
showErrorActivity(a, throwableToString(errorToShow),
keepBrokenProcessRunning);
}
public static String throwableToString(Throwable t) {
StringWriter sw = new StringWriter();
PrintWriter p = new PrintWriter(sw);
t.printStackTrace(p);
String s = sw.toString();
p.close();
return s;
}
private static void showErrorActivity(final Activity activity,
final String errorText, boolean keepBrokenProcessRunning) {
if (activity != null) {
myCurrentActivity = activity;
Intent i = new Intent(Intent.ACTION_VIEW);
i.putExtra(PASSED_ERROR_TEXT_ID, errorText);
i.putExtra(DEV_MAIL, myDeveloperMailAdress);
i.putExtra(TITLE_MAIL, myMailSubject);
i.setType(DEFINED_TYPE);
Log.e("ErrorHandler", "Starting from " + activity + " to "
+ ErrorHandler.class);
activity.startActivity(i);
if (!keepBrokenProcessRunning) {
/*
* After displaying the error in a new process the current
* process can be killed. This wont affect the
* ErrorHandler-activity because it is running in its own
* process (see AndroidManifest)
*/
activity.finish();
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(1);
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String myErrorText = getIntent().getExtras().getString(
PASSED_ERROR_TEXT_ID);
/*
* because this is a new process even the static fields will be reseted!
* the correct values can be restored by passing them in the intent
*/
myDeveloperMailAdress = getIntent().getExtras().getString(DEV_MAIL);
myMailSubject = getIntent().getExtras().getString(TITLE_MAIL);
loadErrorLayout(this, myErrorText);
}
private static void loadErrorLayout(Activity a, String myErrorText) {
a.setContentView(ERROR_WINDOW_ID);
a.setTitle(ERROR_ACTIVITY_TITLE);
EditText myTextView = (EditText) a.findViewById(ERROR_TEXT_VIEW_ID);
myErrorText = addDebugInfosToErrorMessage(a, myErrorText);
if (myTextView != null && myErrorText != null) {
myTextView.setText(myErrorText);
}
if (myDeveloperMailAdress != null) {
enableMailButton(a, myTextView);
}
}
private static void enableMailButton(final Activity a,
final EditText myTextView) {
Button b = (Button) a.findViewById(ERROR_MAIL_BUTTON_ID);
b.setVisibility(View.VISIBLE);
b.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
sendMail(a, myTextView);
}
});
}
private static void sendMail(Activity a, EditText myTextView) {
final Intent emailIntent = new Intent(
android.content.Intent.ACTION_SEND);
emailIntent.setType("plain/text");
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL,
new String[] { myDeveloperMailAdress });
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,
myMailSubject);
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT,
myTextView.getText());
a.startActivity(Intent.createChooser(emailIntent, "Send mail..."));
}
private static String addDebugInfosToErrorMessage(Activity a, String s) {
s += "\n \n <Debug Infos>";
s += "\n OS Version: " + System.getProperty("os.version") + " ("
+ android.os.Build.VERSION.INCREMENTAL + ")";
s += "\n OS API Level: " + android.os.Build.VERSION.SDK;
s += "\n Device: " + android.os.Build.DEVICE;
s += "\n Model (and Product): " + android.os.Build.MODEL + " ("
+ android.os.Build.PRODUCT + ")";
// TODO add application version!
// more from
// http://developer.android.com/reference/android/os/Build.html :
s += "\n Manufacturer: " + android.os.Build.MANUFACTURER;
s += "\n Other TAGS: " + android.os.Build.TAGS;
s += "\n screenWidth: "
+ a.getWindow().getWindowManager().getDefaultDisplay()
.getWidth();
s += "\n screenHeigth: "
+ a.getWindow().getWindowManager().getDefaultDisplay()
.getHeight();
s += "\n Keyboard available: "
+ (a.getResources().getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS);
s += "\n Trackball available: "
+ (a.getResources().getConfiguration().navigation == Configuration.NAVIGATION_TRACKBALL);
s += "\n SD Card state: " + Environment.getExternalStorageState();
s += " \n \n [More automatically received system infos]:";
Properties p = System.getProperties();
Enumeration keys = p.keys();
String key = "";
while (keys.hasMoreElements()) {
key = (String) keys.nextElement();
s += "\n > " + key + " = " + (String) p.get(key);
}
s += " \n \n [You can add a description of what you were doing here]:";
s += " \n ...";
return s;
}
@Override
public void uncaughtException(final Thread thread, final Throwable ex) {
Log.e(LOG_TAG, "A wild 'Uncaught exeption' appeares!");
// Log.e(LOG_TAG, "Error=" + ex.toString());
ex.printStackTrace();
if (myCurrentActivity != null) {
Log.e("ErrorHandler", "Starting error activity");
showErrorActivity(myCurrentActivity, throwableToString(ex), false);
} else {
Log.e("ErrorHandler",
"No current activity set -> error activity couldn't be started");
defaultHandler.uncaughtException(thread, ex);
}
}
public static void enableEmailReports(String developerEmailAdress,
String emailTitle) {
myDeveloperMailAdress = developerEmailAdress;
myMailSubject = emailTitle;
}
public static void setCurrentActivity(Activity a) {
myCurrentActivity = a;
}
public static void registerNewErrorHandler(Activity currentActivity) {
Thread.setDefaultUncaughtExceptionHandler(new ErrorHandler(
currentActivity));
}
}