From 12137edd8e00a50e1cb621193594f80e8a3591fc Mon Sep 17 00:00:00 2001 From: pk910 Date: Fri, 11 Mar 2016 03:10:45 +0100 Subject: [PATCH] Added own crash handler for debugging --- app/src/main/AndroidManifest.xml | 10 ++ .../java/de/dhbwloe/campusapp/CampusApp.java | 16 +- .../dhbwloe/campusapp/CampusAppContext.java | 4 + .../campusapp/CampusAppCrashHandler.java | 25 +++ .../campusapp/CampusAppExceptionHandler.java | 143 ++++++++++++++++++ app/src/main/res/layout/crash_log.xml | 29 ++++ app/src/main/res/values/strings.xml | 4 +- 7 files changed, 228 insertions(+), 3 deletions(-) create mode 100644 app/src/main/java/de/dhbwloe/campusapp/CampusAppCrashHandler.java create mode 100644 app/src/main/java/de/dhbwloe/campusapp/CampusAppExceptionHandler.java create mode 100644 app/src/main/res/layout/crash_log.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 54385a9..d8fce1d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -29,6 +29,16 @@ + + + + + + diff --git a/app/src/main/java/de/dhbwloe/campusapp/CampusApp.java b/app/src/main/java/de/dhbwloe/campusapp/CampusApp.java index 499a665..403c740 100644 --- a/app/src/main/java/de/dhbwloe/campusapp/CampusApp.java +++ b/app/src/main/java/de/dhbwloe/campusapp/CampusApp.java @@ -66,6 +66,20 @@ public class CampusApp extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { Log.i("CampusApp", "Event: onCreate"); + + if(CampusAppContext.DEBUG) { + final Thread.UncaughtExceptionHandler systemExceptionHandler = Thread.getDefaultUncaughtExceptionHandler(); + final CampusAppExceptionHandler oExceptionHandler = new CampusAppExceptionHandler(); + Thread.setDefaultUncaughtExceptionHandler (new Thread.UncaughtExceptionHandler() { + @Override + public void uncaughtException(Thread thread, Throwable e) { + oExceptionHandler.handleUncaughtException(thread, e); + //systemExceptionHandler.uncaughtException(thread, e); + System.exit(1); + } + }); + } + super.onCreate(savedInstanceState); setContentView(R.layout.activity_campus_app); @@ -294,7 +308,7 @@ public class CampusApp extends FragmentActivity { AppContext = new CampusAppContext(this, R.id.fragment_container, R.id.nav_view); else AppContext.setMainActivity(this); - + super.onResume(); Log.i("CampusApp", "onResume event"); AppContext.getNfcCardListener().resumeForefrontDispatcher(); diff --git a/app/src/main/java/de/dhbwloe/campusapp/CampusAppContext.java b/app/src/main/java/de/dhbwloe/campusapp/CampusAppContext.java index 99a1d17..807add9 100644 --- a/app/src/main/java/de/dhbwloe/campusapp/CampusAppContext.java +++ b/app/src/main/java/de/dhbwloe/campusapp/CampusAppContext.java @@ -16,6 +16,7 @@ package de.dhbwloe.campusapp; import android.app.Activity; +import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.widget.TextView; @@ -67,6 +68,7 @@ public class CampusAppContext { String navTarget; }; + public final static boolean DEBUG = true; public final NavigationItem[] NAVIGATION_TARGETS = new NavigationItem[] { new NavigationItem() {{ navItemId = R.id.nav_dashboard; @@ -131,10 +133,12 @@ public class CampusAppContext { private DatabaseManager oDatabaseManager; private NfcCardListener oNfcCardListener; private Bundle oContextVariables; + private CampusAppExceptionHandler oExceptionHandler; public CampusAppContext(CampusApp mainActivity, int fragmentContainerId, int navigationViewId) { final CampusAppContext AppContext = this; instance = this; + oMainActivity = mainActivity; oContextVariables = new Bundle(); oNavigationManager = new NavigationManager(this, fragmentContainerId, navigationViewId); diff --git a/app/src/main/java/de/dhbwloe/campusapp/CampusAppCrashHandler.java b/app/src/main/java/de/dhbwloe/campusapp/CampusAppCrashHandler.java new file mode 100644 index 0000000..7f66e1c --- /dev/null +++ b/app/src/main/java/de/dhbwloe/campusapp/CampusAppCrashHandler.java @@ -0,0 +1,25 @@ +package de.dhbwloe.campusapp; + +import android.app.Activity; +import android.os.Bundle; +import android.view.Window; + +/** + * Created by pk910 on 11.03.2016. + */ +public class CampusAppCrashHandler extends Activity { + + @Override + public void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + requestWindowFeature(Window.FEATURE_NO_TITLE); // make a dialog without a titlebar + setContentView(R.layout.crash_log); + + Bundle extras = this.getIntent().getExtras(); + String crashdate = (extras != null ? extras.getString("crashdate") : null); + + CampusAppExceptionHandler exceptionHandler = new CampusAppExceptionHandler(); + exceptionHandler.postprocessException(this, crashdate); + } +} diff --git a/app/src/main/java/de/dhbwloe/campusapp/CampusAppExceptionHandler.java b/app/src/main/java/de/dhbwloe/campusapp/CampusAppExceptionHandler.java new file mode 100644 index 0000000..9d5a974 --- /dev/null +++ b/app/src/main/java/de/dhbwloe/campusapp/CampusAppExceptionHandler.java @@ -0,0 +1,143 @@ +package de.dhbwloe.campusapp; + +import android.app.Activity; +import android.content.Intent; +import android.util.Log; + +import com.loopj.android.http.AsyncHttpClient; +import com.loopj.android.http.AsyncHttpResponseHandler; +import com.loopj.android.http.RequestParams; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.Writer; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import cz.msebera.android.httpclient.Header; +import cz.msebera.android.httpclient.NameValuePair; +import cz.msebera.android.httpclient.client.entity.UrlEncodedFormEntity; +import cz.msebera.android.httpclient.client.methods.HttpPost; +import cz.msebera.android.httpclient.impl.client.DefaultHttpClient; +import cz.msebera.android.httpclient.message.BasicNameValuePair; +import cz.msebera.android.httpclient.protocol.HTTP; + +/** + * Created by pk910 on 11.03.2016. + */ +public class CampusAppExceptionHandler { + private static String CRASHLOG_UPLOAD = "http://dev.pk910.de/DHBWCampusCourses"; + private String localPath; + + private static boolean crashLogWindowOpened = false; + + public void handleUncaughtException(Thread thread, Throwable e) { + // automatically send crash log to my server for debuggging. + // disable this for productive use! (CampusAppContext.DEBUG) + + final Writer result = new StringWriter(); + final PrintWriter printWriter = new PrintWriter(result); + e.printStackTrace(printWriter); + String stacktrace = result.toString(); + printWriter.close(); + + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd-HHmmss"); + String crashdate = dateFormat.format(new Date()); + String filename = crashdate + ".stacktrace"; + + CampusAppContext context; + Activity mainActivity = null; + try { + /*Wir greifen nun auf einen Code zurück, aus welchem die unbehandelte Exception stammt. + * Dies ist womöglich keine gute Idee, daher müssen wir sämmtliche Exceptions abfangen und verwerfen (Exception inception :D) + * und hoffen, dass die App noch so weit "funktioniert" ;) + */ + context = CampusAppContext.getInstance(); + + if(context != null) { + mainActivity = context.getMainActivity(); + } + if(mainActivity != null) { + localPath = mainActivity.getApplicationContext().getFilesDir().getAbsolutePath(); + } + } catch (Exception ex) {} + + if(localPath != null) + writeToFile(stacktrace, filename); + + // start crash screen + if(!crashLogWindowOpened) { + try { + Intent intent = new Intent(); + intent.setAction("de.dhbw.campusapp.CRASH_LOG"); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // required when starting from Application + intent.putExtra("crashdate", crashdate); + mainActivity.startActivity(intent); + crashLogWindowOpened = true; + } catch (Exception ex) { + } + } + } + + private void writeToFile(String stacktrace, String filename) { + try { + BufferedWriter bos = new BufferedWriter(new FileWriter( + localPath + "/" + filename)); + bos.write(stacktrace); + bos.flush(); + bos.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void postprocessException(Activity crashLogScreen, String crashdate) { + localPath = crashLogScreen.getApplicationContext().getFilesDir().getAbsolutePath(); + String fileName = localPath + "/" + crashdate + ".stacktrace"; + StringBuilder stackTrace = new StringBuilder(); + + try { + BufferedReader br = new BufferedReader(new FileReader(fileName)); + String line; + + while ((line = br.readLine()) != null) { + stackTrace.append(line); + stackTrace.append('\n'); + } + br.close(); + } + catch (IOException e) { + //You'll need to add proper error handling here + } + + sendToServer(CRASHLOG_UPLOAD, stackTrace.toString(), crashdate); + } + + private void sendToServer(String url, String stacktrace, String crashdate) { + AsyncHttpClient client = new AsyncHttpClient(); + RequestParams params = new RequestParams(); + params.add("stacktrace", stacktrace); + params.add("crashdate", crashdate); + + client.post(url, params, new AsyncHttpResponseHandler() { + + @Override + public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) { + Log.i("CrashLog", "OK: "+(responseBody != null ? new String(responseBody) : null)); + } + + @Override + public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) { + Log.i("CrashLog", "Failed: "+(responseBody != null ? new String(responseBody) : null)); + } + }); + } + +} diff --git a/app/src/main/res/layout/crash_log.xml b/app/src/main/res/layout/crash_log.xml new file mode 100644 index 0000000..176d49d --- /dev/null +++ b/app/src/main/res/layout/crash_log.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f2fe27d..dadfd82 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -31,8 +31,8 @@ dd.MM.yyyy HH:mm HH:mm dd.MM. - dd.MM.yyy HH:mm - dd.MM.yyy + dd.MM.yyyy HH:mm + dd.MM.yyyy #,##0.00 € Search: %s -- 2.20.1