ExceptionHelper.java

  1package eu.siacs.conversations.utils;
  2
  3import android.support.v7.app.AlertDialog;
  4import android.content.Context;
  5import android.content.DialogInterface;
  6import android.content.DialogInterface.OnClickListener;
  7import android.content.SharedPreferences;
  8import android.content.pm.PackageInfo;
  9import android.content.pm.PackageManager;
 10import android.content.pm.Signature;
 11import android.preference.PreferenceManager;
 12import android.util.Log;
 13
 14import java.io.BufferedReader;
 15import java.io.FileInputStream;
 16import java.io.IOException;
 17import java.io.InputStreamReader;
 18import java.io.OutputStream;
 19import java.text.SimpleDateFormat;
 20import java.util.Date;
 21import java.util.List;
 22import java.util.Locale;
 23
 24import eu.siacs.conversations.Config;
 25import eu.siacs.conversations.R;
 26import eu.siacs.conversations.entities.Account;
 27import eu.siacs.conversations.entities.Conversation;
 28import eu.siacs.conversations.entities.Message;
 29import eu.siacs.conversations.services.XmppConnectionService;
 30import eu.siacs.conversations.ui.XmppActivity;
 31import rocks.xmpp.addr.Jid;
 32
 33public class ExceptionHelper {
 34
 35	private static final String FILENAME = "stacktrace.txt";
 36	private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
 37
 38	public static void init(Context context) {
 39		if (!(Thread.getDefaultUncaughtExceptionHandler() instanceof ExceptionHandler)) {
 40			Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler(
 41					context));
 42		}
 43	}
 44
 45	public static boolean checkForCrash(XmppActivity activity) {
 46		try {
 47			final XmppConnectionService service = activity == null ? null : activity.xmppConnectionService;
 48			if (service == null) {
 49				return false;
 50			}
 51			final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
 52			boolean neverSend = preferences.getBoolean("never_send", false);
 53			if (neverSend || Config.BUG_REPORTS == null) {
 54				return false;
 55			}
 56			List<Account> accounts = service.getAccounts();
 57			Account account = null;
 58			for (int i = 0; i < accounts.size(); ++i) {
 59				if (accounts.get(i).isEnabled()) {
 60					account = accounts.get(i);
 61					break;
 62				}
 63			}
 64			if (account == null) {
 65				return false;
 66			}
 67			final Account finalAccount = account;
 68			FileInputStream file = activity.openFileInput(FILENAME);
 69			InputStreamReader inputStreamReader = new InputStreamReader(file);
 70			BufferedReader stacktrace = new BufferedReader(inputStreamReader);
 71			final StringBuilder report = new StringBuilder();
 72			PackageManager pm = activity.getPackageManager();
 73			PackageInfo packageInfo;
 74			try {
 75				packageInfo = pm.getPackageInfo(activity.getPackageName(), PackageManager.GET_SIGNATURES);
 76				report.append("Version: ").append(packageInfo.versionName).append('\n');
 77				report.append("Last Update: ").append(DATE_FORMAT.format(new Date(packageInfo.lastUpdateTime))).append('\n');
 78				Signature[] signatures = packageInfo.signatures;
 79				if (signatures != null && signatures.length >= 1) {
 80					report.append("SHA-1: ").append(CryptoHelper.getFingerprintCert(packageInfo.signatures[0].toByteArray())).append('\n');
 81				}
 82				report.append('\n');
 83			} catch (Exception e) {
 84				e.printStackTrace();
 85				return false;
 86			}
 87			String line;
 88			while ((line = stacktrace.readLine()) != null) {
 89				report.append(line);
 90				report.append('\n');
 91			}
 92			file.close();
 93			activity.deleteFile(FILENAME);
 94			AlertDialog.Builder builder = new AlertDialog.Builder(activity);
 95			builder.setTitle(activity.getString(R.string.crash_report_title));
 96			builder.setMessage(activity.getText(R.string.crash_report_message));
 97			builder.setPositiveButton(activity.getText(R.string.send_now),
 98					new OnClickListener() {
 99
100						@Override
101						public void onClick(DialogInterface dialog, int which) {
102
103							Log.d(Config.LOGTAG, "using account="
104									+ finalAccount.getJid().asBareJid()
105									+ " to send in stack trace");
106							Conversation conversation = null;
107							try {
108								conversation = service.findOrCreateConversation(finalAccount,
109										Jid.of(Config.BUG_REPORTS), false, true);
110							} catch (final IllegalArgumentException ignored) {
111							}
112							Message message = new Message(conversation, report
113									.toString(), Message.ENCRYPTION_NONE);
114							service.sendMessage(message);
115						}
116					});
117			builder.setNegativeButton(activity.getText(R.string.send_never),
118					new OnClickListener() {
119
120						@Override
121						public void onClick(DialogInterface dialog, int which) {
122							preferences.edit().putBoolean("never_send", true)
123									.apply();
124						}
125					});
126			builder.create().show();
127			return true;
128		} catch (final IOException ignored) {
129			return false;
130		}
131	}
132
133	public static void writeToStacktraceFile(Context context, String msg) {
134		try {
135			OutputStream os = context.openFileOutput(FILENAME, Context.MODE_PRIVATE);
136			os.write(msg.getBytes());
137			os.flush();
138			os.close();
139		} catch (IOException ignored) {
140		}
141	}
142}