You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
294 lines
11 KiB
Java
294 lines
11 KiB
Java
package org.acra;
|
|
|
|
import java.io.BufferedReader;
|
|
import java.io.File;
|
|
import java.io.FileInputStream;
|
|
import java.io.InputStreamReader;
|
|
import java.io.PrintWriter;
|
|
import java.io.StringWriter;
|
|
import java.util.Map;
|
|
import java.util.TreeMap;
|
|
|
|
import org.acra.collector.CrashReportData;
|
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
import com.htc.widget.HtcAlertDialog;
|
|
import com.htc.widget.HtcEditText;
|
|
import com.sensetoolbox.six.R;
|
|
import com.sensetoolbox.six.utils.Helpers;
|
|
|
|
import android.annotation.SuppressLint;
|
|
import android.app.Activity;
|
|
import android.content.Context;
|
|
import android.content.DialogInterface;
|
|
import android.content.DialogInterface.OnCancelListener;
|
|
import android.content.SharedPreferences;
|
|
import android.net.ConnectivityManager;
|
|
import android.net.NetworkInfo;
|
|
import android.os.Bundle;
|
|
import android.os.Environment;
|
|
import android.util.Base64;
|
|
import android.util.Log;
|
|
import android.util.TypedValue;
|
|
import android.view.Gravity;
|
|
import android.view.MotionEvent;
|
|
import android.view.View;
|
|
import android.view.View.OnClickListener;
|
|
import android.view.View.OnTouchListener;
|
|
import android.view.WindowManager;
|
|
import android.view.inputmethod.EditorInfo;
|
|
import android.widget.LinearLayout;
|
|
import android.widget.TextView;
|
|
import android.widget.Toast;
|
|
import android.widget.FrameLayout.LayoutParams;
|
|
|
|
public class HCrashReportDialog extends Activity {
|
|
private String mReportFileName;
|
|
private String xposedLog;
|
|
private HtcEditText desc;
|
|
|
|
private boolean isNetworkAvailable() {
|
|
ConnectivityManager connectivityManager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
|
|
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
|
|
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
|
|
}
|
|
|
|
private String getXposedLog() {
|
|
StringBuilder sb = new StringBuilder();
|
|
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(new File("/data/data/de.robv.android.xposed.installer/log/error.log"))))) {
|
|
String line = null;
|
|
while ((line = reader.readLine()) != null) sb.append(line).append("\n");
|
|
return sb.toString();
|
|
} catch (Exception e) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
void showFinishDialog(boolean isOk, String details) {
|
|
HtcAlertDialog.Builder dlg = new HtcAlertDialog.Builder(this);
|
|
dlg.setTitle(Helpers.l10n(this, R.string.crash_result));
|
|
dlg.setCancelable(true);
|
|
if (isOk)
|
|
dlg.setView(Helpers.createCenteredText(this, R.string.crash_ok));
|
|
else {
|
|
TextView errorTxt = Helpers.createCenteredText(this, R.string.crash_error);
|
|
if (details != null) errorTxt.setText(errorTxt.getText() + ": " + details);
|
|
dlg.setView(errorTxt);
|
|
}
|
|
dlg.setOnCancelListener(new OnCancelListener() {
|
|
@Override
|
|
public void onCancel(DialogInterface dialog) {
|
|
finish();
|
|
}
|
|
});
|
|
dlg.setNeutralButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
|
public void onClick(DialogInterface dialog, int whichButton) {
|
|
finish();
|
|
}
|
|
});
|
|
dlg.show();
|
|
}
|
|
|
|
@SuppressLint("SdCardPath")
|
|
private void sendCrash(final String xposedLogStr) {
|
|
String exceptionsPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/SenseToolbox/";
|
|
try {
|
|
CrashReportPersister persister = new CrashReportPersister(getApplicationContext());
|
|
CrashReportData crashData = persister.load(mReportFileName);
|
|
|
|
String ROM = "";
|
|
Process ifc = null;
|
|
try {
|
|
ifc = Runtime.getRuntime().exec("getprop ro.product.version");
|
|
BufferedReader bis = new BufferedReader(new InputStreamReader(ifc.getInputStream()), 2048);
|
|
ROM = bis.readLine();
|
|
} catch (Exception e) {} finally {
|
|
if (ifc != null) ifc.destroy();
|
|
}
|
|
|
|
String kernel = System.getProperty("os.version");
|
|
if (kernel == null) kernel = "";
|
|
|
|
SharedPreferences prefs = getSharedPreferences("one_toolbox_prefs", 1);
|
|
TreeMap<String, Object> keys = new TreeMap<String, Object>();
|
|
keys.putAll(prefs.getAll());
|
|
String keysAsString = "";
|
|
for (Map.Entry<String, Object> entry: keys.entrySet())
|
|
keysAsString += entry.getKey() + "=" + entry.getValue().toString() + "\n";
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
try (FileInputStream in = new FileInputStream(new File(exceptionsPath + "uncaught_exceptions"))) {
|
|
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(in))) {
|
|
String line;
|
|
while ((line = bufferedReader.readLine()) != null) sb.append(line).append("\n");
|
|
} catch (Exception e) {}
|
|
} catch (Exception e) {}
|
|
|
|
String buildData = crashData.getProperty(ReportField.BUILD);
|
|
buildData += "ROM.VERSION=" + ROM + "\n";
|
|
buildData += "KERNEL.VERSION=" + kernel + "\n";
|
|
buildData += "SHARED.PREFS=" + Base64.encodeToString(keysAsString.getBytes(), Base64.NO_WRAP) + "\n";
|
|
if (!sb.toString().isEmpty())
|
|
buildData += "UNCAUGHT.EXCEPTIONS=" + Base64.encodeToString(sb.toString().getBytes(), Base64.NO_WRAP) + "\n";
|
|
|
|
crashData.put(ReportField.BUILD, buildData);
|
|
crashData.put(ReportField.USER_COMMENT, desc.getText().toString());
|
|
if (xposedLogStr == null || xposedLogStr.trim() == "")
|
|
crashData.put(ReportField.CUSTOM_DATA, "Xposed log is empty...");
|
|
else
|
|
crashData.put(ReportField.CUSTOM_DATA, xposedLogStr);
|
|
persister.store(crashData, mReportFileName);
|
|
} catch (Exception e) {
|
|
StringWriter sw = new StringWriter();
|
|
e.printStackTrace(new PrintWriter(sw));
|
|
ACRA.getErrorReporter().putCustomData("XPOSED_LOG", "Retrieval failed. Stack trace:\n" + sw.toString());
|
|
}
|
|
SendWorker worker = ACRA.getErrorReporter().startSendingReports(false, true);
|
|
try {
|
|
worker.join(60000);
|
|
} catch (InterruptedException e) {
|
|
showFinishDialog(false, "server timeout");
|
|
return;
|
|
}
|
|
Helpers.emptyFile(exceptionsPath + "uncaught_exceptions", true);
|
|
showFinishDialog(true, null);
|
|
}
|
|
|
|
private void cancelReports() {
|
|
ACRA.getErrorReporter().deletePendingNonApprovedReports(false);
|
|
finish();
|
|
}
|
|
|
|
int densify(int size) {
|
|
return Math.round(getResources().getDisplayMetrics().density * size);
|
|
}
|
|
|
|
@Override
|
|
public void onCreate(Bundle savedInstanceState) {
|
|
super.onCreate(savedInstanceState);
|
|
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
|
|
|
|
if (getIntent().getBooleanExtra("FORCE_CANCEL", false)) {
|
|
cancelReports();
|
|
return;
|
|
}
|
|
|
|
mReportFileName = getIntent().getStringExtra("REPORT_FILE_NAME");
|
|
if (mReportFileName == null) finish();
|
|
|
|
String title = Helpers.l10n(this, R.string.warning);
|
|
String neutralText = Helpers.l10n(this, R.string.crash_ignore);
|
|
TextView text = Helpers.createCenteredText(this, R.string.crash_dialog);
|
|
LinearLayout dialogView = new LinearLayout(this);
|
|
dialogView.setOrientation(LinearLayout.VERTICAL);
|
|
|
|
int tries = 5;
|
|
xposedLog = null;
|
|
while (xposedLog == null && tries > 0) try {
|
|
tries--;
|
|
xposedLog = getXposedLog();
|
|
if (xposedLog == null) Thread.sleep(500);
|
|
} catch (Exception e) {}
|
|
|
|
try {
|
|
CrashReportPersister persister = new CrashReportPersister(getApplicationContext());
|
|
CrashReportData crashData = persister.load(mReportFileName);
|
|
ObjectMapper mapper = new ObjectMapper();
|
|
String payload = mapper.writeValueAsString(Helpers.getParamsAsStringString(crashData));
|
|
int payloadSize = payload.getBytes("UTF-8").length;
|
|
boolean isManualReport = crashData.getProperty(ReportField.STACK_TRACE).contains("Report requested by developer");
|
|
Log.e("ACRA", crashData.getProperty(ReportField.STACK_TRACE));
|
|
|
|
TextView descText = new TextView(this);
|
|
descText.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
|
|
descText.setGravity(Gravity.START);
|
|
descText.setPadding(densify(10), 0, densify(10), 0);
|
|
descText.setTextColor(text.getCurrentTextColor());
|
|
descText.setTextSize(TypedValue.COMPLEX_UNIT_PX, text.getTextSize() - 10);
|
|
|
|
desc = new HtcEditText(this);
|
|
desc.setGravity(Gravity.TOP | Gravity.START);
|
|
desc.setInputType(EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE);
|
|
desc.setSingleLine(false);
|
|
desc.setPadding(densify(5), densify(5), densify(5), densify(5));
|
|
|
|
if (isManualReport) {
|
|
title = Helpers.l10n(this, R.string.popupnotify_blconfirm);
|
|
text = Helpers.createCenteredText(this, R.string.crash_dialog_manual);
|
|
neutralText = Helpers.l10n(this, R.string.sense_themes_cancel);
|
|
descText.setText(Helpers.l10n(this, R.string.crash_dialog_manual_desc));
|
|
|
|
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, densify(100));
|
|
lp.setMargins(densify(10), densify(5), densify(10), densify(10));
|
|
desc.setLayoutParams(lp);
|
|
} else {
|
|
descText.setText(Helpers.l10n(this, R.string.crash_dialog_manual_desc2));
|
|
|
|
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, densify(50));
|
|
lp.setMargins(densify(10), densify(5), densify(10), densify(10));
|
|
desc.setLayoutParams(lp);
|
|
desc.setFocusable(false);
|
|
desc.setFocusableInTouchMode(false);
|
|
desc.setOnTouchListener(new OnTouchListener() {
|
|
@Override
|
|
public boolean onTouch(View v, MotionEvent event) {
|
|
v.setFocusable(true);
|
|
v.setFocusableInTouchMode(true);
|
|
v.performClick();
|
|
return false;
|
|
}
|
|
});
|
|
}
|
|
|
|
TextView feedbackNote = new TextView(this);
|
|
feedbackNote.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
|
|
feedbackNote.setGravity(Gravity.START);
|
|
feedbackNote.setPadding(densify(10), 0, densify(10), densify(10));
|
|
feedbackNote.setTextColor(text.getCurrentTextColor());
|
|
feedbackNote.setTextSize(TypedValue.COMPLEX_UNIT_PX, text.getTextSize() - 10);
|
|
feedbackNote.setText(Helpers.l10n(this, R.string.crash_dialog_note));
|
|
|
|
dialogView.addView(text);
|
|
dialogView.addView(descText);
|
|
dialogView.addView(desc);
|
|
|
|
if (getSharedPreferences("one_toolbox_prefs", 1).getString("acra.user.email", "").isEmpty())
|
|
dialogView.addView(feedbackNote);
|
|
|
|
text.setText(text.getText() + "\n" + Helpers.l10n(this, R.string.crash_dialog_manual_size) + ": " + String.valueOf(Math.round(payloadSize / 1024)) + " KB");
|
|
} catch (Exception e) {}
|
|
|
|
HtcAlertDialog.Builder alert = new HtcAlertDialog.Builder(this);
|
|
alert.setTitle(title);
|
|
alert.setView(dialogView);
|
|
alert.setOnCancelListener(new OnCancelListener() {
|
|
@Override
|
|
public void onCancel(DialogInterface dialog) {
|
|
cancelReports();
|
|
}
|
|
});
|
|
alert.setNeutralButton(neutralText, new DialogInterface.OnClickListener() {
|
|
public void onClick(DialogInterface dialog, int whichButton) {
|
|
cancelReports();
|
|
}
|
|
});
|
|
alert.setPositiveButton(Helpers.l10n(this, R.string.crash_send), new DialogInterface.OnClickListener() {
|
|
public void onClick(DialogInterface dialog, int whichButton) {}
|
|
});
|
|
final HtcAlertDialog alertDlg = alert.show();
|
|
alertDlg.getButton(HtcAlertDialog.BUTTON_POSITIVE).setOnClickListener(new OnClickListener() {
|
|
@Override
|
|
public void onClick(View v) {
|
|
if (desc != null && desc.getText().toString().trim().equals("")) {
|
|
Toast.makeText(HCrashReportDialog.this, Helpers.l10n(HCrashReportDialog.this, R.string.crash_needs_desc), Toast.LENGTH_LONG).show();
|
|
} else if (!isNetworkAvailable()) {
|
|
Toast.makeText(HCrashReportDialog.this, Helpers.l10n(HCrashReportDialog.this, R.string.crash_needs_inet), Toast.LENGTH_LONG).show();
|
|
} else {
|
|
alertDlg.dismiss();
|
|
sendCrash(xposedLog);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|