add crash handling dialog with optional sending of the crash to the author
authorDamyan Ivanov <dam+mobileledger@ktnx.net>
Mon, 11 Feb 2019 21:30:28 +0000 (23:30 +0200)
committerDamyan Ivanov <dam+mobileledger@ktnx.net>
Mon, 11 Feb 2019 21:30:28 +0000 (23:30 +0200)
app/src/main/java/net/ktnx/mobileledger/ui/CrashReportDialogFragment.java [new file with mode: 0644]
app/src/main/java/net/ktnx/mobileledger/ui/activity/CrashReportingActivity.java [new file with mode: 0644]
app/src/main/java/net/ktnx/mobileledger/ui/activity/MainActivity.java
app/src/main/java/net/ktnx/mobileledger/ui/activity/NewTransactionActivity.java
app/src/main/java/net/ktnx/mobileledger/ui/activity/ProfileListActivity.java
app/src/main/java/net/ktnx/mobileledger/utils/Globals.java
app/src/main/res/layout/crash_dialog.xml [new file with mode: 0644]
app/src/main/res/values-bg/strings.xml
app/src/main/res/values/strings.xml

diff --git a/app/src/main/java/net/ktnx/mobileledger/ui/CrashReportDialogFragment.java b/app/src/main/java/net/ktnx/mobileledger/ui/CrashReportDialogFragment.java
new file mode 100644 (file)
index 0000000..0875626
--- /dev/null
@@ -0,0 +1,88 @@
+package net.ktnx.mobileledger.ui;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.app.DialogFragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ScrollView;
+import android.widget.TextView;
+
+import net.ktnx.mobileledger.R;
+import net.ktnx.mobileledger.utils.Globals;
+
+public class CrashReportDialogFragment extends DialogFragment {
+    private String mCrashReportText;
+    private ScrollView repScroll = null;
+    @NonNull
+    @Override
+    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+        LayoutInflater inflater = getActivity().getLayoutInflater();
+
+        if (savedInstanceState != null)
+            mCrashReportText = savedInstanceState.getString("crash_text");
+
+        View view = inflater.inflate(R.layout.crash_dialog, null);
+        ((TextView) view.findViewById(R.id.textCrashReport)).setText(mCrashReportText);
+        repScroll = view.findViewById(R.id.scrollText);
+        builder.setTitle(R.string.crash_dialog_title).setView(view)
+                .setPositiveButton(R.string.btn_send_crash_report,
+                        new DialogInterface.OnClickListener() {
+                            @Override
+                            public void onClick(DialogInterface dialog, int which) {
+                                // still nothing
+                                Intent email = new Intent(Intent.ACTION_SEND);
+                                email.putExtra(Intent.EXTRA_EMAIL,
+                                        new String[]{Globals.developerEmail});
+                                email.putExtra(Intent.EXTRA_SUBJECT, "MoLe crash report");
+                                email.putExtra(Intent.EXTRA_TEXT, mCrashReportText);
+                                email.setType("message/rfc822");
+                                startActivity(Intent.createChooser(email,
+                                        getResources().getString(R.string.send_crash_via)));
+                            }
+                        })
+                .setNegativeButton(R.string.btn_not_now, new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        CrashReportDialogFragment.this.getDialog().cancel();
+                    }
+                })
+                .setNeutralButton(R.string.btn_show_report, new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                    }
+                });
+
+        AlertDialog dialog = builder.create();
+        dialog.setOnShowListener(new DialogInterface.OnShowListener() {
+            @Override
+            public void onShow(DialogInterface dialogIinterface) {
+                dialog.getButton(AlertDialog.BUTTON_NEUTRAL)
+                        .setOnClickListener(new View.OnClickListener() {
+                            @Override
+                            public void onClick(View v) {
+                                if (repScroll != null) {
+                                    repScroll.setVisibility(View.VISIBLE);
+                                    v.setVisibility(View.GONE);
+                                }
+                            }
+                        });
+            }
+        });
+        return dialog;
+    }
+    @Override
+    public void onSaveInstanceState(@NonNull Bundle outState) {
+        super.onSaveInstanceState(outState);
+        outState.putString("crash_text", mCrashReportText);
+    }
+    public void setCrashReportText(String text) {
+        mCrashReportText = text;
+    }
+}
diff --git a/app/src/main/java/net/ktnx/mobileledger/ui/activity/CrashReportingActivity.java b/app/src/main/java/net/ktnx/mobileledger/ui/activity/CrashReportingActivity.java
new file mode 100644 (file)
index 0000000..0d72499
--- /dev/null
@@ -0,0 +1,34 @@
+package net.ktnx.mobileledger.ui.activity;
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v7.app.AppCompatActivity;
+import android.util.Log;
+
+import net.ktnx.mobileledger.ui.CrashReportDialogFragment;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+public class CrashReportingActivity extends AppCompatActivity {
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
+            @Override
+            public void uncaughtException(Thread t, Throwable e) {
+                StringWriter sw = new StringWriter();
+                PrintWriter pw = new PrintWriter(sw);
+                e.printStackTrace(pw);
+
+                Log.e(null, sw.toString());
+
+                CrashReportDialogFragment df = new CrashReportDialogFragment();
+                df.setCrashReportText(sw.toString());
+                df.show(getSupportFragmentManager(), "crash_report");
+            }
+        });
+        Log.d("crash", "Uncaught exception handler set");
+    }
+}
index 0fe1402..02eb809 100644 (file)
@@ -30,7 +30,6 @@ import android.support.v4.view.GravityCompat;
 import android.support.v4.view.ViewPager;
 import android.support.v4.widget.DrawerLayout;
 import android.support.v7.app.ActionBarDrawerToggle;
-import android.support.v7.app.AppCompatActivity;
 import android.support.v7.widget.Toolbar;
 import android.util.Log;
 import android.view.View;
@@ -53,7 +52,7 @@ import java.lang.ref.WeakReference;
 import java.text.DateFormat;
 import java.util.Date;
 
-public class MainActivity extends AppCompatActivity {
+public class MainActivity extends CrashReportingActivity {
     DrawerLayout drawer;
     private FragmentManager fragmentManager;
     private TextView tvLastUpdate;
index c907b89..04cabd6 100644 (file)
@@ -24,7 +24,6 @@ import android.support.design.widget.BaseTransientBottomBar;
 import android.support.design.widget.FloatingActionButton;
 import android.support.design.widget.Snackbar;
 import android.support.v4.app.DialogFragment;
-import android.support.v7.app.AppCompatActivity;
 import android.support.v7.widget.Toolbar;
 import android.text.Editable;
 import android.text.InputType;
@@ -73,7 +72,7 @@ import java.util.Objects;
  * TODO: nicer swiping removal with visual feedback
  *  */
 
-public class NewTransactionActivity extends AppCompatActivity
+public class NewTransactionActivity extends CrashReportingActivity
         implements TaskCallback, DescriptionSelectedCallback {
     private static SaveTransactionTask saver;
     private TableLayout table;
index dc36fc7..3a4a515 100644 (file)
@@ -22,7 +22,6 @@ import android.content.Intent;
 import android.os.Bundle;
 import android.support.annotation.NonNull;
 import android.support.v7.app.ActionBar;
-import android.support.v7.app.AppCompatActivity;
 import android.support.v7.widget.DividerItemDecoration;
 import android.support.v7.widget.RecyclerView;
 import android.support.v7.widget.Toolbar;
@@ -51,7 +50,7 @@ import java.util.Collections;
  * item details. On tablets, the activity presents the list of items and
  * item details side-by-side using two vertical panes.
  */
-public class ProfileListActivity extends AppCompatActivity {
+public class ProfileListActivity extends CrashReportingActivity {
 
     public static final String ARG_ACTION = "action";
     public static final String ARG_PROFILE_INDEX = "profile_index";
index ecbffda..8a2c836 100644 (file)
@@ -39,6 +39,7 @@ public final class Globals {
     @ColorInt
     public static int primaryDark, defaultTextColor;
     public static String[] monthNames;
+    public static String developerEmail = "dam+mole-crash@ktnx.net";
     private static SimpleDateFormat ledgerDateFormatter =
             new SimpleDateFormat("yyyy/MM/dd", Locale.US);
     private static Pattern reLedgerDate =
diff --git a/app/src/main/res/layout/crash_dialog.xml b/app/src/main/res/layout/crash_dialog.xml
new file mode 100644 (file)
index 0000000..2d4bb84
--- /dev/null
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:paddingStart="8dp"
+    android:paddingTop="8dp"
+    android:paddingEnd="8dp">
+
+    <ScrollView
+        android:id="@+id/scrollText"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="9"
+        android:background="@color/table_row_light_bg"
+        android:scrollbars="horizontal|vertical"
+        android:visibility="gone">
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical"
+            android:padding="8dp">
+
+            <TextView
+                android:id="@+id/textCrashReport"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="Example crash report text goes here"
+                tools:ignore="HardcodedText" />
+        </LinearLayout>
+    </ScrollView>
+
+    <TextView
+        android:id="@+id/textView7"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="16dp"
+        android:text="@string/crash_send_question" />
+
+</LinearLayout>
\ No newline at end of file
index e735aed..7a18b4d 100644 (file)
     <string name="err_profile_user_name_empty">Въвеждането на потребителско име е задължително когато се използва удостоверяване</string>
     <string name="err_profile_password_empty">Паролата е задължителна</string>
     <string name="posting_permitted">Позволяване на добавянето на нови трансакции</string>
+    <string name="send_crash_via">Изпращане на доклада чрез:</string>
+    <string name="crash_send_question">Желаете ли да изпратите доклад за грешката на автора? Това ще помогне за диагностициране и отстраняване на проблема.</string>
+    <string name="crash_app_condensed_label">Срив</string>
+    <string name="btn_not_now">Не сега</string>
+    <string name="btn_send_crash_report">Изпращане...</string>
+    <string name="crash_dialog_title">MoLe се срина</string>
+    <string name="crash_report_contents_label">Съдържание на доклада:</string>
+    <string name="profile_subitlte_read_only">(Само за преглед)</string>
+    <string name="menu_acc_summary_confirm_selection_title">Потвърждаване на избора</string>
+    <string name="menu_acc_summary_hide_selected_title">Скриване на маркираните сметки</string>
 
 </resources>
index fa60329..54db4cc 100644 (file)
     </string-array>
     <string name="posting_permitted">Posting of new transactions enabled</string>
     <string name="profile_subitlte_read_only">(Read only)</string>
+    <string name="crash_report_contents_label">Crash report contents:</string>
+    <string name="crash_dialog_title">MoLe chashed</string>
+    <string name="btn_send_crash_report">Send...</string>
+    <string name="btn_not_now">Not now</string>
+    <string name="crash_app_condensed_label">Crash</string>
+    <string name="crash_send_question">Would you like to send the crash report to the developer? This would help diagnosing and fixing the problem.</string>
+    <string name="send_crash_via">Send crash report via:</string>
+    <string name="btn_show_report">Show report</string>
 </resources>