ExceptionHelper.java

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