package org.acra.dialog; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.SharedPreferences; import android.os.Bundle; import android.support.annotation.CallSuper; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.text.InputType; import android.view.View; import android.view.ViewGroup.LayoutParams; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.ScrollView; import android.widget.TextView; import org.acra.ACRA; import org.acra.ACRAConstants; import org.acra.prefs.PrefUtils; import org.acra.prefs.SharedPreferencesFactory; /** * This is the dialog Activity used by ACRA to get authorization from the user * to send reports. Requires android:launchMode="singleInstance" in your * AndroidManifest to work properly. **/ @SuppressWarnings({"WeakerAccess", "unused"}) public class CrashReportDialog extends BaseCrashReportDialog implements DialogInterface.OnClickListener { private static final String STATE_EMAIL = "email"; private static final String STATE_COMMENT = "comment"; private static final int PADDING = 10; private LinearLayout scrollable; private EditText userCommentView; private EditText userEmailView; private SharedPreferencesFactory sharedPreferencesFactory; private AlertDialog mDialog; @CallSuper @Override protected void init(@Nullable Bundle savedInstanceState) { scrollable = new LinearLayout(this); scrollable.setOrientation(LinearLayout.VERTICAL); sharedPreferencesFactory = new SharedPreferencesFactory(getApplicationContext(), getConfig()); final int themeResourceId = getConfig().resDialogTheme(); if(themeResourceId != ACRAConstants.DEFAULT_RES_VALUE) setTheme(themeResourceId); buildAndShowDialog(savedInstanceState); } /** * Build the dialog from the values in config * * @param savedInstanceState old state to restore */ protected void buildAndShowDialog(@Nullable Bundle savedInstanceState) { final AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this); final int titleResourceId = getConfig().resDialogTitle(); if (titleResourceId != ACRAConstants.DEFAULT_RES_VALUE) { dialogBuilder.setTitle(titleResourceId); } final int iconResourceId = getConfig().resDialogIcon(); if (iconResourceId != ACRAConstants.DEFAULT_RES_VALUE) { dialogBuilder.setIcon(iconResourceId); } dialogBuilder.setView(buildCustomView(savedInstanceState)) .setPositiveButton(getText(getConfig().resDialogPositiveButtonText()), this) .setNegativeButton(getText(getConfig().resDialogNegativeButtonText()), this); mDialog = dialogBuilder.create(); mDialog.setCanceledOnTouchOutside(false); mDialog.show(); } @NonNull protected View buildCustomView(@Nullable Bundle savedInstanceState) { final ScrollView root = new ScrollView(this); root.setPadding(PADDING, PADDING, PADDING, PADDING); root.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); root.setFocusable(true); root.setFocusableInTouchMode(true); root.addView(scrollable); addViewToDialog(getMainView()); // Add an optional prompt for user comments final View comment = getCommentLabel(); if (comment != null) { comment.setPadding(comment.getPaddingLeft(), PADDING, comment.getPaddingRight(), comment.getPaddingBottom()); addViewToDialog(comment); String savedComment = null; if (savedInstanceState != null) { savedComment = savedInstanceState.getString(STATE_COMMENT); } userCommentView = getCommentPrompt(savedComment); addViewToDialog(userCommentView); } // Add an optional user email field final View email = getEmailLabel(); if (email != null) { email.setPadding(email.getPaddingLeft(), PADDING, email.getPaddingRight(), email.getPaddingBottom()); addViewToDialog(email); String savedEmail = null; if (savedInstanceState != null) { savedEmail = savedInstanceState.getString(STATE_EMAIL); } userEmailView = getEmailPrompt(savedEmail); addViewToDialog(userEmailView); } return root; } /** * adds a view to the end of the dialog * * @param v the view to add */ protected final void addViewToDialog(@NonNull View v) { scrollable.addView(v); } /** * Creates a main view containing text of resDialogText, or nothing if not found * * @return the main view */ @NonNull protected View getMainView() { final TextView text = new TextView(this); final int dialogTextId = getConfig().resDialogText(); if (dialogTextId != ACRAConstants.DEFAULT_RES_VALUE) { text.setText(getText(dialogTextId)); } return text; } /** * creates a comment label view with resDialogCommentPrompt as text * * @return the label or null if there is no resource */ @Nullable protected View getCommentLabel() { final int commentPromptId = getConfig().resDialogCommentPrompt(); if (commentPromptId != ACRAConstants.DEFAULT_RES_VALUE) { final TextView labelView = new TextView(this); labelView.setText(getText(commentPromptId)); return labelView; } return null; } /** * creates a comment prompt * * @param savedComment the content of the prompt (usually from a saved state) * @return the comment prompt */ @NonNull protected EditText getCommentPrompt(@Nullable CharSequence savedComment) { final EditText userCommentView = new EditText(this); userCommentView.setLines(2); if (savedComment != null) { userCommentView.setText(savedComment); } return userCommentView; } /** * creates a email label view with resDialogEmailPrompt as text * * @return the label or null if there is no resource */ @Nullable protected View getEmailLabel() { final int emailPromptId = getConfig().resDialogEmailPrompt(); if (emailPromptId != ACRAConstants.DEFAULT_RES_VALUE) { final TextView labelView = new TextView(this); labelView.setText(getText(emailPromptId)); return labelView; } return null; } /** * creates an email prompt * * @param savedEmail the content of the prompt (usually from a saved state or settings) * @return the email prompt */ @NonNull protected EditText getEmailPrompt(@Nullable CharSequence savedEmail) { final EditText userEmailView = new EditText(this); userEmailView.setSingleLine(); userEmailView.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS); if (savedEmail != null) { userEmailView.setText(savedEmail); } else { final SharedPreferences prefs = sharedPreferencesFactory.create(); userEmailView.setText(prefs.getString(ACRA.PREF_USER_EMAIL_ADDRESS, "")); } return userEmailView; } @Override public void onClick(DialogInterface dialog, int which) { if (which == DialogInterface.BUTTON_POSITIVE) { // Retrieve user comment final String comment = userCommentView != null ? userCommentView.getText().toString() : ""; // Store the user email final String userEmail; final SharedPreferences prefs = sharedPreferencesFactory.create(); if (userEmailView != null) { userEmail = userEmailView.getText().toString(); final SharedPreferences.Editor prefEditor = prefs.edit(); prefEditor.putString(ACRA.PREF_USER_EMAIL_ADDRESS, userEmail); PrefUtils.save(prefEditor); } else { userEmail = prefs.getString(ACRA.PREF_USER_EMAIL_ADDRESS, ""); } sendCrash(comment, userEmail); } else { cancelReports(); } finish(); } /* * (non-Javadoc) * * @see android.app.Activity#onSaveInstanceState(android.os.Bundle) */ @CallSuper @Override protected void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); if (userCommentView != null && userCommentView.getText() != null) { outState.putString(STATE_COMMENT, userCommentView.getText().toString()); } if (userEmailView != null && userEmailView.getText() != null) { outState.putString(STATE_EMAIL, userEmailView.getText().toString()); } } /** * @return the AlertDialog displayed by this Activity */ protected AlertDialog getDialog() { return mDialog; } }