diff --git a/app/src/main/java/net/kdt/pojavlaunch/FatalErrorActivity.java b/app/src/main/java/net/kdt/pojavlaunch/FatalErrorActivity.java index 1ed4e37f02..236221d11d 100644 --- a/app/src/main/java/net/kdt/pojavlaunch/FatalErrorActivity.java +++ b/app/src/main/java/net/kdt/pojavlaunch/FatalErrorActivity.java @@ -1,17 +1,25 @@ package net.kdt.pojavlaunch; +import android.app.*; import android.content.*; import android.os.*; import android.support.v7.app.*; +import android.util.*; +import java.awt.*; +import java.awt.datatransfer.*; + +import android.support.v7.app.AlertDialog; public class FatalErrorActivity extends AppCompatActivity { - public static void showError(Context ctx, boolean isFatalErr, Throwable th) { + public static void showError(Context ctx, String savePath, boolean storageAllow, /* boolean isFatalErr, */ Throwable th) { Intent ferrorIntent = new Intent(ctx, FatalErrorActivity.class); ferrorIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); ferrorIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); ferrorIntent.putExtra("throwable", th); - ferrorIntent.putExtra("isFatal", isFatalErr); + ferrorIntent.putExtra("savePath", savePath); + ferrorIntent.putExtra("storageAllow", storageAllow); + // ferrorIntent.putExtra("isFatal", isFatalErr); ctx.startActivity(ferrorIntent); } @@ -20,9 +28,46 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Bundle extras = getIntent().getExtras(); - Throwable th = (Throwable) extras.getSerializable("throwable"); - boolean isFatalError = extras.getBoolean("isFatal", false); + boolean storageAllow = extras.getBoolean("storageAllow"); + final String strStackTrace = Log.getStackTraceString((Throwable) extras.getSerializable("throwable")); + String strSavePath = extras.getString("savePath"); + String errHeader = storageAllow ? + "Crash stack trace saved to " + strSavePath + "." : + "Storage permission is required to save crash stack trace!"; + + // boolean isFatalError = extras.getBoolean("isFatal", false); + + new AlertDialog.Builder(this) + .setTitle(R.string.error_fatal) + .setMessage(errHeader + "\n\n" + strStackTrace) + .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener(){ + + @Override + public void onClick(DialogInterface p1, int p2) { + finish(); + } + }) + .setNegativeButton(R.string.global_restart, new DialogInterface.OnClickListener(){ + + @Override + public void onClick(DialogInterface p1, int p2) { + startActivity(new Intent(FatalErrorActivity.this, PojavLoginActivity.class)); + } + }) + .setNeutralButton(android.R.string.copy, new DialogInterface.OnClickListener(){ + + @Override + public void onClick(DialogInterface p1, int p2) { + StringSelection errData = new StringSelection(strStackTrace); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(errData, null); + + finish(); + } + }) + //.setNegativeButton("Report (not available)", null) + .setCancelable(false) + .show(); - Tools.showError(this, isFatalError ? R.string.error_fatal : R.string.global_error, th, true); + // Tools.showError(this, isFatalError ? R.string.error_fatal : R.string.global_error, th, true); } } diff --git a/app/src/main/java/net/kdt/pojavlaunch/PojavApplication.java b/app/src/main/java/net/kdt/pojavlaunch/PojavApplication.java index 84e46ff8b8..384ed1e22e 100644 --- a/app/src/main/java/net/kdt/pojavlaunch/PojavApplication.java +++ b/app/src/main/java/net/kdt/pojavlaunch/PojavApplication.java @@ -9,16 +9,44 @@ import android.support.v7.preference.*; import java.io.*; import android.content.*; +import android.support.v4.app.*; +import android.util.*; +import net.kdt.pojavlaunch.exit.*; +import java.time.*; +import java.text.*; +import java.util.*; public class PojavApplication extends Application { + public static String CRASH_REPORT_TAG = "PojavCrashReport"; + @Override public void onCreate() { Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler(){ @Override public void uncaughtException(Thread thread, Throwable th) { - FatalErrorActivity.showError(PojavApplication.this, true, th); - android.os.Process.killProcess(android.os.Process.myPid()); + boolean storagePermAllowed = Build.VERSION.SDK_INT < 23 || ActivityCompat.checkSelfPermission(PojavApplication.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED; + File crashFile = new File(storagePermAllowed ? Tools.MAIN_PATH : Tools.datapath, "latestcrash.txt"); + try { + // Write to file, since some devices may not able to show error + crashFile.createNewFile(); + PrintStream crashStream = new PrintStream(crashFile); + crashStream.append("PojavLauncher crash report\n"); + crashStream.append(" - Time: " + DateFormat.getDateTimeInstance().format(new Date())); + crashStream.append(" - Device: " + Build.PRODUCT + " " + Build.MODEL); + crashStream.append(" - Android version: " + Build.VERSION.RELEASE); + crashStream.append(" - Crash stack trace:"); + crashStream.append(Log.getStackTraceString(th)); + crashStream.close(); + } catch (Throwable th2) { + Log.e(CRASH_REPORT_TAG, " - Exception attempt saving crash stack trace:", th2); + Log.e(CRASH_REPORT_TAG, " - The crash stack trace was:", th); + } + + FatalErrorActivity.showError(PojavApplication.this, crashFile.getAbsolutePath(), storagePermAllowed, th); + // android.os.Process.killProcess(android.os.Process.myPid()); + + MainActivity.fullyExit(); } }); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2c8838fa7d..48f1390482 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -118,6 +118,7 @@ Load Name Remove + Restart Save This field can\'t be empty