Permalink
Browse files

Added crash reports and user feedback via email.

This is done by the usage of the library ACRA.
Crash reports will now be send to a php script that will send the report via email to me.
I also added a dialog for sending feedback (about wrong exercises).
  • Loading branch information...
1 parent aec89e3 commit 19e52b76b8370e78b9d67e4110d04463d1cd2ad6 @chaosbastler committed Jun 1, 2014
View
@@ -5,5 +5,6 @@
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
+ <classpathentry kind="lib" path="libs/acra-4.5.0.jar"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>
@@ -18,7 +18,7 @@
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:largeHeap="true"
- android:theme="@style/Theme.AppCompat.Light.DarkActionBar" >
+ android:theme="@style/Theme.AppCompat.Light.DarkActionBar" android:name="de.skubware.opentraining.activity.acra.OpenTrainingApplication">
<activity
android:name="de.skubware.opentraining.activity.MainActivity"
android:label="@string/app_name">
@@ -94,7 +94,12 @@
android:label="@string/create_exercise_activity_title"
android:icon="@drawable/icon_dumbbell" >
</activity>
-
+ <activity android:name="org.acra.CrashReportDialog"
+ android:theme="@android:style/Theme.Dialog"
+ android:launchMode="singleInstance"
+ android:excludeFromRecents="true"
+ android:finishOnTaskLaunch="true" />
+
<service android:enabled="true" android:name="de.skubware.opentraining.activity.settings.sync.OpenTrainingSyncService" />
</application>
Binary file not shown.
@@ -0,0 +1,51 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/my_frame"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" >
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <TextView
+ android:id="@+id/textView1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:text="Issue:"
+ android:textAppearance="?android:attr/textAppearanceLarge" />
+
+ <Spinner
+ android:id="@+id/exercise_update_reason_spinner"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_toRightOf="@+id/textView1" />
+
+ </RelativeLayout>
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <TextView
+ android:id="@+id/textView2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Your suggestion:"
+ android:textAppearance="?android:attr/textAppearanceLarge" />
+
+ </RelativeLayout>
+
+ <EditText
+ android:id="@+id/edittext_user_suggestion"
+ android:layout_width="match_parent"
+ android:layout_height="163dp"
+ android:ems="10"
+ android:inputType="textMultiLine" >
+
+ <requestFocus />
+ </EditText>
+
+</LinearLayout>
@@ -22,4 +22,10 @@
android:visible="false"
android:title="@string/delete_exercise"
yourapp:showAsAction="never"/>
+
+ <item
+ android:id="@+id/menu_item_send_exercise_feedback"
+ android:visible="false"
+ android:title="@string/send_exercise_feedback"
+ yourapp:showAsAction="never"/>
</menu>
@@ -0,0 +1,16 @@
+<resources>
+
+ <!-- exercise detail menu -->
+ <string name="send_exercise_feedback">Fehler melden</string>
+
+
+ <!-- SendExerciseFeedbackDialog -->
+ <string name="send_feedback_for_exercise">Feedback zu: %1$s</string>
+
+ <!-- ACRA crash report dialog -->
+ <string name="crash_dialog_text">Ein unerwarteter Fehler brachte die Anwendung leider zum Absturz. Bitte hilf bei der Fehlerbehebung indem du uns die Fehlerdaten mit \'OK\' zusendest.</string>
+ <string name="crash_dialog_comment_prompt">Du kannst zusätzlich noch einen Kommentar zu dem Fehler hinzufügen:</string>
+ <string name="crash_dialog_ok_toast">Der Fehlerbericht wurde gesendet. Vielen Dank für die Mithilfe.</string>
+
+
+</resources>
@@ -0,0 +1,16 @@
+<resources>
+
+ <!-- exercise detail menu -->
+ <string name="send_exercise_feedback">Report error</string>
+
+
+ <!-- SendExerciseFeedbackDialog -->
+ <string name="send_feedback_for_exercise">Feedback for: %1$s</string>
+
+ <!-- ACRA crash report dialog -->
+ <string name="crash_dialog_text">An unexpected error occurred forcing the application to stop. Please help by sending us error date by clicking \'OK\'.</string>
+ <string name="crash_dialog_comment_prompt">You might add your comments abouth the problem below:</string>
+ <string name="crash_dialog_ok_toast">Report has been sent. Thank you for helping.</string>
+
+
+</resources>
@@ -0,0 +1,129 @@
+package de.skubware.opentraining.activity.acra;
+
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import org.acra.collector.CrashReportData;
+import org.acra.ReportField;
+import org.acra.sender.ReportSender;
+import org.acra.sender.ReportSenderException;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.protocol.HTTP;
+
+import android.util.Log;
+
+/**
+ * Based on acra-mailer(https://github.com/d-a-n/acra-mailer) of d-a-n.
+ */
+public class ACRACrashReportMailer implements ReportSender {
+ private final static String BASE_URL = "http://skubware.de/opentraining/acra_crash.php";
+ private final static String SHARED_SECRET = "my_on_github_with_everyone_shared_secret";
+ private Map<String, String> custom_data = null;
+
+ public ACRACrashReportMailer() {
+ }
+
+ public ACRACrashReportMailer(HashMap<String, String> custom_data) {
+ this.custom_data = custom_data;
+ }
+
+ @Override
+ public void send(CrashReportData report) throws ReportSenderException {
+
+ String url = getUrl();
+ Log.e("xenim", url);
+
+ try {
+ DefaultHttpClient httpClient = new DefaultHttpClient();
+ HttpPost httpPost = new HttpPost(url);
+
+ List<NameValuePair> parameters = new ArrayList<NameValuePair>();
+
+ if (custom_data != null) {
+ for (Map.Entry<String, String> entry : custom_data.entrySet()) {
+ parameters.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
+ }
+ }
+ parameters.add(new BasicNameValuePair("DATE", new Date().toString()));
+ parameters.add(new BasicNameValuePair("REPORT_ID", report.get(ReportField.REPORT_ID)));
+ parameters.add(new BasicNameValuePair("APP_VERSION_CODE", report.get(ReportField.APP_VERSION_CODE)));
+ parameters.add(new BasicNameValuePair("APP_VERSION_NAME", report.get(ReportField.APP_VERSION_NAME)));
+ parameters.add(new BasicNameValuePair("PACKAGE_NAME", report.get(ReportField.PACKAGE_NAME)));
+ parameters.add(new BasicNameValuePair("FILE_PATH", report.get(ReportField.FILE_PATH)));
+ parameters.add(new BasicNameValuePair("PHONE_MODEL", report.get(ReportField.PHONE_MODEL)));
+ parameters.add(new BasicNameValuePair("ANDROID_VERSION", report.get(ReportField.ANDROID_VERSION)));
+ parameters.add(new BasicNameValuePair("BUILD", report.get(ReportField.BUILD)));
+ parameters.add(new BasicNameValuePair("BRAND", report.get(ReportField.BRAND)));
+ parameters.add(new BasicNameValuePair("PRODUCT", report.get(ReportField.PRODUCT)));
+ parameters.add(new BasicNameValuePair("TOTAL_MEM_SIZE", report.get(ReportField.TOTAL_MEM_SIZE)));
+ parameters.add(new BasicNameValuePair("AVAILABLE_MEM_SIZE", report.get(ReportField.AVAILABLE_MEM_SIZE)));
+ parameters.add(new BasicNameValuePair("CUSTOM_DATA", report.get(ReportField.CUSTOM_DATA)));
+ parameters.add(new BasicNameValuePair("STACK_TRACE", report.get(ReportField.STACK_TRACE)));
+ parameters.add(new BasicNameValuePair("INITIAL_CONFIGURATION", report.get(ReportField.INITIAL_CONFIGURATION)));
+ parameters.add(new BasicNameValuePair("CRASH_CONFIGURATION", report.get(ReportField.CRASH_CONFIGURATION)));
+ parameters.add(new BasicNameValuePair("DISPLAY", report.get(ReportField.DISPLAY)));
+ parameters.add(new BasicNameValuePair("USER_COMMENT", report.get(ReportField.USER_COMMENT)));
+ parameters.add(new BasicNameValuePair("USER_APP_START_DATE", report.get(ReportField.USER_APP_START_DATE)));
+ parameters.add(new BasicNameValuePair("USER_CRASH_DATE", report.get(ReportField.USER_CRASH_DATE)));
+ parameters.add(new BasicNameValuePair("DUMPSYS_MEMINFO", report.get(ReportField.DUMPSYS_MEMINFO)));
+ parameters.add(new BasicNameValuePair("DROPBOX", report.get(ReportField.DROPBOX)));
+ parameters.add(new BasicNameValuePair("LOGCAT", report.get(ReportField.LOGCAT)));
+ parameters.add(new BasicNameValuePair("EVENTSLOG", report.get(ReportField.EVENTSLOG)));
+ parameters.add(new BasicNameValuePair("RADIOLOG", report.get(ReportField.RADIOLOG)));
+ parameters.add(new BasicNameValuePair("IS_SILENT", report.get(ReportField.IS_SILENT)));
+ parameters.add(new BasicNameValuePair("DEVICE_ID", report.get(ReportField.DEVICE_ID)));
+ parameters.add(new BasicNameValuePair("INSTALLATION_ID", report.get(ReportField.INSTALLATION_ID)));
+ parameters.add(new BasicNameValuePair("USER_EMAIL", report.get(ReportField.USER_EMAIL)));
+ parameters.add(new BasicNameValuePair("DEVICE_FEATURES", report.get(ReportField.DEVICE_FEATURES)));
+ parameters.add(new BasicNameValuePair("ENVIRONMENT", report.get(ReportField.ENVIRONMENT)));
+ parameters.add(new BasicNameValuePair("SETTINGS_SYSTEM", report.get(ReportField.SETTINGS_SYSTEM)));
+ parameters.add(new BasicNameValuePair("SETTINGS_SECURE", report.get(ReportField.SETTINGS_SECURE)));
+ parameters.add(new BasicNameValuePair("SHARED_PREFERENCES", report.get(ReportField.SHARED_PREFERENCES)));
+ parameters.add(new BasicNameValuePair("APPLICATION_LOG", report.get(ReportField.APPLICATION_LOG)));
+ parameters.add(new BasicNameValuePair("MEDIA_CODEC_LIST", report.get(ReportField.MEDIA_CODEC_LIST)));
+ parameters.add(new BasicNameValuePair("THREAD_DETAILS", report.get(ReportField.THREAD_DETAILS)));
+
+ httpPost.setEntity(new UrlEncodedFormEntity(parameters, HTTP.UTF_8));
+ httpClient.execute(httpPost);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private String getUrl() {
+ String token = getToken();
+ String key = getKey(token);
+ return String.format("%s?token=%s&key=%s&", BASE_URL, token, key);
+ }
+
+ private String getKey(String token) {
+ return md5(String.format("%s+%s", SHARED_SECRET, token));
+ }
+
+ private String getToken() {
+ return md5(UUID.randomUUID().toString());
+ }
+
+ public static String md5(String s) {
+ MessageDigest m = null;
+ try {
+ m = MessageDigest.getInstance("MD5");
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ }
+ m.update(s.getBytes(), 0, s.length());
+ String hash = new BigInteger(1, m.digest()).toString(16);
+ return hash;
+ }
+}
@@ -0,0 +1,102 @@
+package de.skubware.opentraining.activity.acra;
+
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import org.acra.collector.CrashReportData;
+import org.acra.ACRA;
+import org.acra.ReportField;
+import org.acra.sender.ReportSender;
+import org.acra.sender.ReportSenderException;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.protocol.HTTP;
+
+import android.util.Log;
+
+/**
+ * Based on acra-mailer(https://github.com/d-a-n/acra-mailer) of d-a-n.
+ */
+public class ACRAFeedbackMailer implements ReportSender {
+ private final static String BASE_URL = "http://skubware.de/opentraining/acra_feedback.php";
+ private final static String SHARED_SECRET = "my_on_github_with_everyone_shared_secret";
+ private Map<String, String> custom_data = null;
+
+ public ACRAFeedbackMailer() {
+ }
+
+ public ACRAFeedbackMailer(HashMap<String, String> custom_data) {
+ this.custom_data = custom_data;
+ }
+
+ @Override
+ public void send(CrashReportData report) throws ReportSenderException {
+
+ String url = getUrl();
+ Log.e("xenim", url);
+
+ try {
+ DefaultHttpClient httpClient = new DefaultHttpClient();
+ HttpPost httpPost = new HttpPost(url);
+
+ List<NameValuePair> parameters = new ArrayList<NameValuePair>();
+
+ if (custom_data != null) {
+ for (Map.Entry<String, String> entry : custom_data.entrySet()) {
+ parameters.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
+ }
+ }
+ parameters.add(new BasicNameValuePair("DATE", new Date().toString()));
+ parameters.add(new BasicNameValuePair("APP_VERSION_NAME", report.get(ReportField.APP_VERSION_NAME)));
+ parameters.add(new BasicNameValuePair("CUSTOM_DATA", report.get(ReportField.CUSTOM_DATA)));
+
+ httpPost.setEntity(new UrlEncodedFormEntity(parameters, HTTP.UTF_8));
+ httpClient.execute(httpPost);
+
+
+ // set the crash report sender again after sending the feedback
+ ACRA.getErrorReporter().removeAllReportSenders();
+ ACRA.getErrorReporter().setReportSender(new ACRACrashReportMailer());
+
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private String getUrl() {
+ String token = getToken();
+ String key = getKey(token);
+ return String.format("%s?token=%s&key=%s&", BASE_URL, token, key);
+ }
+
+ private String getKey(String token) {
+ return md5(String.format("%s+%s", SHARED_SECRET, token));
+ }
+
+ private String getToken() {
+ return md5(UUID.randomUUID().toString());
+ }
+
+ public static String md5(String s) {
+ MessageDigest m = null;
+ try {
+ m = MessageDigest.getInstance("MD5");
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ }
+ m.update(s.getBytes(), 0, s.length());
+ String hash = new BigInteger(1, m.digest()).toString(16);
+ return hash;
+ }
+}
Oops, something went wrong.

0 comments on commit 19e52b7

Please sign in to comment.