Skip to content

Commit

Permalink
Added crash reports and user feedback via email.
Browse files Browse the repository at this point in the history
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
chaosbastler committed Jun 1, 2014
1 parent aec89e3 commit 19e52b7
Show file tree
Hide file tree
Showing 14 changed files with 568 additions and 2 deletions.
1 change: 1 addition & 0 deletions app/.classpath
Expand Up @@ -5,5 +5,6 @@
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/> <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.LIBRARIES"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/> <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"/> <classpathentry kind="output" path="bin/classes"/>
</classpath> </classpath>
9 changes: 7 additions & 2 deletions app/AndroidManifest.xml
Expand Up @@ -18,7 +18,7 @@
android:icon="@drawable/ic_launcher" android:icon="@drawable/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:largeHeap="true" 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 <activity
android:name="de.skubware.opentraining.activity.MainActivity" android:name="de.skubware.opentraining.activity.MainActivity"
android:label="@string/app_name"> android:label="@string/app_name">
Expand Down Expand Up @@ -94,7 +94,12 @@
android:label="@string/create_exercise_activity_title" android:label="@string/create_exercise_activity_title"
android:icon="@drawable/icon_dumbbell" > android:icon="@drawable/icon_dumbbell" >
</activity> </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" /> <service android:enabled="true" android:name="de.skubware.opentraining.activity.settings.sync.OpenTrainingSyncService" />


</application> </application>
Expand Down
Binary file added app/libs/acra-4.5.0.jar
Binary file not shown.
51 changes: 51 additions & 0 deletions app/res/layout/dialog_send_exercise_feedback.xml
@@ -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>
6 changes: 6 additions & 0 deletions app/res/menu/exercise_detail_menu.xml
Expand Up @@ -22,4 +22,10 @@
android:visible="false" android:visible="false"
android:title="@string/delete_exercise" android:title="@string/delete_exercise"
yourapp:showAsAction="never"/> 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> </menu>
16 changes: 16 additions & 0 deletions app/res/values-de/strings_send_feedback.xml
@@ -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>
16 changes: 16 additions & 0 deletions app/res/values/strings_send_feedback.xml
@@ -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;
}
}
102 changes: 102 additions & 0 deletions app/src/de/skubware/opentraining/activity/acra/ACRAFeedbackMailer.java
@@ -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;
}
}

0 comments on commit 19e52b7

Please sign in to comment.