Added own crash handler for debugging
authorpk910 <philipp@pk910.de>
Fri, 11 Mar 2016 02:10:45 +0000 (03:10 +0100)
committerpk910 <philipp@pk910.de>
Fri, 11 Mar 2016 02:10:45 +0000 (03:10 +0100)
app/src/main/AndroidManifest.xml
app/src/main/java/de/dhbwloe/campusapp/CampusApp.java
app/src/main/java/de/dhbwloe/campusapp/CampusAppContext.java
app/src/main/java/de/dhbwloe/campusapp/CampusAppCrashHandler.java [new file with mode: 0644]
app/src/main/java/de/dhbwloe/campusapp/CampusAppExceptionHandler.java [new file with mode: 0644]
app/src/main/res/layout/crash_log.xml [new file with mode: 0644]
app/src/main/res/values/strings.xml

index 54385a9476b9c96af0008528bd2052ad21ab7e5f..d8fce1d6f387453453fbf8389c7b42905bf55685 100644 (file)
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
+        <activity
+            android:name=".CampusAppCrashHandler"
+            android:theme="@android:style/Theme.Dialog"
+            android:textAppearance="@android:style/TextAppearance.Large"
+            android:windowSoftInputMode="stateHidden">
+            <intent-filter>
+                <action android:name="de.dhbw.campusapp.CRASH_LOG" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
     </application>
 
 </manifest>
index 499a665e9bcc78b7ceb8dbb935729419a2c61cd8..403c7401b748e12feeb2d2ca8f935f60b7eb6596 100644 (file)
@@ -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();
index 99a1d17f94bb7d019604e162ccd655b7f06bda68..807add9d1f1f62c8097c2bb7789c0e220af16e91 100644 (file)
@@ -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 (file)
index 0000000..7f66e1c
--- /dev/null
@@ -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 (file)
index 0000000..9d5a974
--- /dev/null
@@ -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 (file)
index 0000000..176d49d
--- /dev/null
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical" android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <RelativeLayout
+        android:layout_width="250dp"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal">
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceLarge"
+            android:text="Irgendwas Doofes ist passiert. :/"
+            android:id="@+id/textView38"
+            android:layout_gravity="center_horizontal" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:text="Crash Stacktrace wird an Entwickler gesendet..."
+            android:id="@+id/textView39"
+            android:layout_gravity="center_horizontal"
+            android:layout_below="@+id/textView38" />
+    </RelativeLayout>
+
+</LinearLayout>
\ No newline at end of file
index f2fe27d4132298f746c1f9835961d4279f2abece..dadfd82b49661460f5ddc3fcc25d797114a95e55 100644 (file)
@@ -31,8 +31,8 @@
     <string name="timeformat_vorlesungsplan_fulldate">dd.MM.yyyy HH:mm</string>
     <string name="timeformat_vorlesungsplan_time">HH:mm</string>
     <string name="timeformat_vorlesungsplan_date">dd.MM.</string>
-    <string name="timeformat_news_event">dd.MM.yyy HH:mm</string>
-    <string name="timeformat_news_news">dd.MM.yyy</string>
+    <string name="timeformat_news_event">dd.MM.yyyy HH:mm</string>
+    <string name="timeformat_news_news">dd.MM.yyyy</string>
     <string name="mensaformat_price">#,##0.00 €</string>
 
     <string name="appsearch_title">Search: %s</string>