/******************************************************************************* * This file is part of RedReader. * * RedReader is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * RedReader is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with RedReader. If not, see <http://www.gnu.org/licenses/>. ******************************************************************************/ package org.quantumbadger.redreader.activities; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.LinearLayout; import android.widget.ScrollView; import android.widget.TextView; import org.quantumbadger.redreader.R; import org.quantumbadger.redreader.common.AndroidApi; import org.quantumbadger.redreader.common.Constants; import org.quantumbadger.redreader.common.General; import org.quantumbadger.redreader.common.RRError; import java.util.LinkedList; public class BugReportActivity extends BaseActivity { private static final LinkedList<RRError> errors = new LinkedList<>(); public static synchronized void addGlobalError(RRError error) { errors.add(error); } public static synchronized void handleGlobalError(Context context, String text) { handleGlobalError(context, new RRError(text, null, new RuntimeException())); } public static synchronized void handleGlobalError(Context context, Throwable t) { if(t != null) { Log.e("BugReportActivity", "Handling exception", t); } handleGlobalError(context, new RRError(null, null, t)); } public static synchronized void handleGlobalError(final Context context, final RRError error) { addGlobalError(error); AndroidApi.UI_THREAD_HANDLER.post(new Runnable() { @Override public void run() { final Intent intent = new Intent(context, BugReportActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); } }); } private static synchronized LinkedList<RRError> getErrors() { final LinkedList<RRError> result = new LinkedList<>(errors); errors.clear(); return result; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); final LinearLayout layout = new LinearLayout(this); layout.setOrientation(LinearLayout.VERTICAL); final TextView title = new TextView(this); title.setText(R.string.bug_title); layout.addView(title); title.setTextSize(20.0f); final TextView text = new TextView(this); text.setText(R.string.bug_message); layout.addView(text); text.setTextSize(15.0f); final int paddingPx = General.dpToPixels(this, 20); title.setPadding(paddingPx, paddingPx, paddingPx, paddingPx); text.setPadding(paddingPx, paddingPx, paddingPx, paddingPx); final Button send = new Button(this); send.setText(R.string.bug_button_send); send.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { final LinkedList<RRError> errors = BugReportActivity.getErrors(); StringBuilder sb = new StringBuilder(1024); sb.append("Error report -- RedReader v").append(Constants.version(BugReportActivity.this)).append("\r\n\r\n"); for(RRError error : errors) { sb.append("-------------------------------"); if(error.title != null) sb.append("Title: ").append(error.title).append("\r\n"); if(error.message != null) sb.append("Message: ").append(error.message).append("\r\n"); if(error.httpStatus != null) sb.append("HTTP Status: ").append(error.httpStatus).append("\r\n"); appendException(sb, error.t, 25); } final Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("message/rfc822"); intent.putExtra(Intent.EXTRA_EMAIL, new String[] {"bug" + "reports" + '@' + "redreader" + '.' + "org"}); // no spam, thanks intent.putExtra(Intent.EXTRA_SUBJECT, "Bug Report"); intent.putExtra(Intent.EXTRA_TEXT, sb.toString()); try { startActivity(Intent.createChooser(intent, "Email bug report")); } catch (android.content.ActivityNotFoundException ex) { General.quickToast(BugReportActivity.this, "No email apps installed!"); } finish(); } }); final Button ignore = new Button(this); ignore.setText(R.string.bug_button_ignore); ignore.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { finish(); } }); layout.addView(send); layout.addView(ignore); final ScrollView sv = new ScrollView(this); sv.addView(layout); setBaseActivityContentView(sv); } public static void appendException(StringBuilder sb, Throwable t, int recurseLimit) { if(t != null) { sb.append("Exception: "); sb.append(t.getClass().getCanonicalName()).append("\r\n"); sb.append(t.getMessage()).append("\r\n"); for(StackTraceElement elem : t.getStackTrace()) { sb.append(" ").append(elem.toString()).append("\r\n"); } if(recurseLimit > 0 && t.getCause() != null) { sb.append("Caused by: "); appendException(sb, t.getCause(), recurseLimit - 1); } } } }