Buckets:
NaTo1000/termux-app-bucket / termux-shared /src /main /java /com /termux /shared /crash /CrashHandler.java
| package com.termux.shared.crash; | |
| import android.content.Context; | |
| import androidx.annotation.NonNull; | |
| import com.termux.shared.file.FileUtils; | |
| import com.termux.shared.logger.Logger; | |
| import com.termux.shared.markdown.MarkdownUtils; | |
| import com.termux.shared.errors.Error; | |
| import com.termux.shared.android.AndroidUtils; | |
| import java.nio.charset.Charset; | |
| /** | |
| * Catches uncaught exceptions and logs them. | |
| */ | |
| public class CrashHandler implements Thread.UncaughtExceptionHandler { | |
| private final Context mContext; | |
| private final CrashHandlerClient mCrashHandlerClient; | |
| private final Thread.UncaughtExceptionHandler mDefaultUEH; | |
| private final boolean mIsDefaultHandler; | |
| private static final String LOG_TAG = "CrashUtils"; | |
| private CrashHandler( final Context context, final CrashHandlerClient crashHandlerClient, | |
| boolean isDefaultHandler) { | |
| mContext = context; | |
| mCrashHandlerClient = crashHandlerClient; | |
| mDefaultUEH = Thread.getDefaultUncaughtExceptionHandler(); | |
| mIsDefaultHandler = isDefaultHandler; | |
| } | |
| public void uncaughtException( Thread thread, Throwable throwable) { | |
| Logger.logInfo(LOG_TAG, "uncaughtException() for " + thread + ": " + throwable.getMessage()); | |
| logCrash(thread, throwable); | |
| // Don't stop the app if not on the main thread | |
| if (mIsDefaultHandler) | |
| mDefaultUEH.uncaughtException(thread, throwable); | |
| } | |
| /** | |
| * Set default uncaught crash handler for the app to {@link CrashHandler}. | |
| */ | |
| public static void setDefaultCrashHandler( final Context context, final CrashHandlerClient crashHandlerClient) { | |
| if (!(Thread.getDefaultUncaughtExceptionHandler() instanceof CrashHandler)) { | |
| Thread.setDefaultUncaughtExceptionHandler(new CrashHandler(context, crashHandlerClient, true)); | |
| } | |
| } | |
| /** | |
| * Set uncaught crash handler of current non-main thread to {@link CrashHandler}. | |
| */ | |
| public static void setCrashHandler( final Context context, final CrashHandlerClient crashHandlerClient) { | |
| Thread.currentThread().setUncaughtExceptionHandler(new CrashHandler(context, crashHandlerClient, false)); | |
| } | |
| /** | |
| * Get {@link CrashHandler} instance that can be set as uncaught crash handler of a non-main thread. | |
| */ | |
| public static CrashHandler getCrashHandler( final Context context, final CrashHandlerClient crashHandlerClient) { | |
| return new CrashHandler(context, crashHandlerClient, false); | |
| } | |
| /** | |
| * Log a crash in the crash log file at path returned by {@link CrashHandlerClient#getCrashLogFilePath(Context)}. | |
| * | |
| * @param context The {@link Context} for operations. | |
| * @param crashHandlerClient The {@link CrashHandlerClient} implementation. | |
| * @param thread The {@link Thread} in which the crash happened. | |
| * @param throwable The {@link Throwable} thrown for the crash. | |
| */ | |
| public static void logCrash( Context context, | |
| CrashHandlerClient crashHandlerClient, | |
| Thread thread, Throwable throwable) { | |
| Logger.logInfo(LOG_TAG, "logCrash() for " + thread + ": " + throwable.getMessage()); | |
| new CrashHandler(context, crashHandlerClient, false).logCrash(thread, throwable); | |
| } | |
| public void logCrash( Thread thread, Throwable throwable) { | |
| if (!mCrashHandlerClient.onPreLogCrash(mContext, thread, throwable)) { | |
| logCrashToFile(mContext, mCrashHandlerClient, thread, throwable); | |
| mCrashHandlerClient.onPostLogCrash(mContext, thread, throwable); | |
| } | |
| } | |
| public void logCrashToFile( Context context, | |
| CrashHandlerClient crashHandlerClient, | |
| Thread thread, Throwable throwable) { | |
| StringBuilder reportString = new StringBuilder(); | |
| reportString.append("## Crash Details\n"); | |
| reportString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("Crash Thread", thread.toString(), "-")); | |
| reportString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("Crash Timestamp", AndroidUtils.getCurrentMilliSecondUTCTimeStamp(), "-")); | |
| reportString.append("\n\n").append(MarkdownUtils.getMultiLineMarkdownStringEntry("Crash Message", throwable.getMessage(), "-")); | |
| reportString.append("\n\n").append(Logger.getStackTracesMarkdownString("Stacktrace", Logger.getStackTracesStringArray(throwable))); | |
| String appInfoMarkdownString = crashHandlerClient.getAppInfoMarkdownString(context); | |
| if (appInfoMarkdownString != null && !appInfoMarkdownString.isEmpty()) | |
| reportString.append("\n\n").append(appInfoMarkdownString); | |
| reportString.append("\n\n").append(AndroidUtils.getDeviceInfoMarkdownString(context)); | |
| // Log report string to logcat | |
| Logger.logError(reportString.toString()); | |
| // Write report string to crash log file | |
| Error error = FileUtils.writeTextToFile("crash log", crashHandlerClient.getCrashLogFilePath(context), | |
| Charset.defaultCharset(), reportString.toString(), false); | |
| if (error != null) { | |
| Logger.logErrorExtended(LOG_TAG, error.toString()); | |
| } | |
| } | |
| public interface CrashHandlerClient { | |
| /** | |
| * Called before {@link #logCrashToFile(Context, CrashHandlerClient, Thread, Throwable)} is called. | |
| * | |
| * @param context The {@link Context} passed to {@link CrashHandler#CrashHandler(Context, CrashHandlerClient, boolean)}. | |
| * @param thread The {@link Thread} in which the crash happened. | |
| * @param throwable The {@link Throwable} thrown for the crash. | |
| * @return Should return {@code true} if crash has been handled and should not be logged, | |
| * otherwise {@code false}. | |
| */ | |
| boolean onPreLogCrash(Context context, Thread thread, Throwable throwable); | |
| /** | |
| * Called after {@link #logCrashToFile(Context, CrashHandlerClient, Thread, Throwable)} is called. | |
| * | |
| * @param context The {@link Context} passed to {@link CrashHandler#CrashHandler(Context, CrashHandlerClient, boolean)}. | |
| * @param thread The {@link Thread} in which the crash happened. | |
| * @param throwable The {@link Throwable} thrown for the crash. | |
| */ | |
| void onPostLogCrash(Context context, Thread thread, Throwable throwable); | |
| /** | |
| * Get crash log file path. | |
| * | |
| * @param context The {@link Context} passed to {@link CrashHandler#CrashHandler(Context, CrashHandlerClient, boolean)}. | |
| * @return Should return the crash log file path. | |
| */ | |
| String getCrashLogFilePath(Context context); | |
| /** | |
| * Get app info markdown string to add to crash log. | |
| * | |
| * @param context The {@link Context} passed to {@link CrashHandler#CrashHandler(Context, CrashHandlerClient, boolean)}. | |
| * @return Should return app info markdown string. | |
| */ | |
| String getAppInfoMarkdownString(Context context); | |
| } | |
| } | |
Xet Storage Details
- Size:
- 7.32 kB
- Xet hash:
- bb9a2247c126924cb5052ffda74725746d0882590b5ec0740204b7fe07d53652
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.