如何使用Thread.setDefaultUncaughtExceptionHandler?

时间:2017-08-22 11:14:43

标签: android

我的应用有多个标签,每个标签都有一个RecyclerView。通过单击RecyclerView项,ReadRecentNewsActivity将打开。我已在onClick上设置了共享视图转换。

问题出现在onClick本身,而大部分时间ReadRecentNewsActivity正在正确启动,在某些新闻项目上显示此错误。

我认为此错误是由于共享转换而不是删除它,我想捕获此异常并打开该特定新闻项而不进行共享转换...

enter image description here

1 个答案:

答案 0 :(得分:0)

如何使用Thread.setDefaultUncaughtExceptionHandler?

您正在询问如何创建自定义错误处理程序,因此您可以捕获此特定异常并确定它是什么。是的,每个开发人员都应该为他们的应用程序提供自定义错误处理程序。

实际上,使用自定义错误处理程序,您可以通过文件名,方法甚至行号来确定发生例外的位置。

下面提供了我个人使用的错误处理程序。拿一份副本,用它做你想做的事。

将此调用放入Activity的onCreate()例程中:

 ErrorHandler.toCatch(this);

反过来,它将调用Thread.setDefaultUncaughtExceptionHandler例程:

  Thread.setDefaultUncaughtExceptionHandler(new ErrorHandler(activity));

错误处理程序实现java.lang.Thread.UncaughtExceptionHandler并且cosequently具有方法uncaughtException(Thread thread,Throwable exception)来处理任何异常。

public class ErrorHandler implements java.lang.Thread.UncaughtExceptionHandler{}

通过ErrorHandler.java搜索方法reportErrorHelper.reportError中的第624行。然后你可以使用你的IDE(例如Android Studio)在那里放置一个断点,现在每次出现错误时,它都会停在那里,你会得到一些信息。

  public class ErrorHandler implements
    java.lang.Thread.UncaughtExceptionHandler{


private ErrorHandler(Activity activity){

    mPackageName = getPackageName(activity);
}



public static ErrorHandler getINSTANCE(Activity activity){

    if (mErrorHandler == null){

        mErrorHandler = new ErrorHandler(activity);
    }

    return mErrorHandler;
}


private static String getPackageName(Context pContext){

    String packageName = "";

    try{

        ActivityManager activityManager = (ActivityManager) pContext
                .getSystemService(Context.ACTIVITY_SERVICE);

        if (Build.VERSION.SDK_INT > 20){

            packageName = activityManager.getRunningAppProcesses().get(0).processName;
        }else{

            // <uses-permission android:name="android.permission.GET_TASKS" />
            packageName = activityManager.getRunningTasks(1).get(0).topActivity
                    .getPackageName();
        }

        // There is a limit to the tag length of 23.
        packageName = packageName
                .substring(0, packageName.length() > 22 ? 22 : packageName.length());

    }catch (Exception ex){
    }

    if (packageName.isEmpty()){
        packageName = pContext.getPackageName();
    }

    return packageName;
}




public static void toCatch(Activity activity){

    Thread.setDefaultUncaughtExceptionHandler(getINSTANCE(activity));
}







public static void logError(String message){

    if (message.isEmpty()){

        return;
    }

    logError(new Throwable(message.trim()));
}




public static void logError(Throwable exception){

    try{

        logCrash(exception);

    }catch (Exception e){

        Log.e(mPackageName, e.getMessage());
    }
}



// Return the last error message
public static String getErrorMessage(){

    return mErrorMessage;
}




public static void setErrorMessage(String errMsg){

    mErrorMessage = errMsg;
}



// Return the last crash information
public static ApplicationErrorReport.CrashInfo crashInfo(){

    return mCrashInfo;
}




private static String getAppLabel(Context pContext){

    PackageManager lPackageManager = pContext.getPackageManager();

    ApplicationInfo lApplicationInfo = null;

    try{

        lApplicationInfo = lPackageManager
                .getApplicationInfo(pContext.getApplicationInfo().packageName, 0);

    }catch (final PackageManager.NameNotFoundException e){
    }

    return (String) (lApplicationInfo != null ? lPackageManager
            .getApplicationLabel(lApplicationInfo) : "Unknown");
}



public static boolean inDebugger(){

    //  If in Debugger Environment
    boolean debugging = Debug.isDebuggerConnected();

    return debugging;
}


@NonNull
private static String errorMsg(Throwable exception, String exceptError){

    if (!exceptError.contains("error")){

        mReportBuilder.append(reportError(exception));
    }

    if (!exceptError.contains("callstack")){

        mReportBuilder.append(reportCallStack(exception));
    }

    if (!exceptError.contains("deviceinfo")){

        mReportBuilder.append(reportDeviceInfo());
    }

    if (!exceptError.contains("firmware")){

        mReportBuilder.append(reportFirmware());
    }

    return mReportBuilder.toString();
}




private static String reportError(Throwable exception){

    mCrashInfo = new ApplicationErrorReport.CrashInfo(exception);

    if (mCrashInfo.exceptionMessage == null){

        mErrorMessage = "<unknown error>";
    }else{

        mErrorMessage = mCrashInfo.exceptionMessage
                .replace(": " + mCrashInfo.exceptionClassName, "");
    }

    String throwFile = mCrashInfo.throwFileName == null ? "<unknown file>"
                                                        : mCrashInfo.throwFileName;

    return "\n************ " + mCrashInfo.exceptionClassName + " ************\n"
            + mErrorMessage + LINE_SEPARATOR
            + "\n File: " + throwFile
            + "\n Method: " + mCrashInfo.throwMethodName + "()"
            + "\n Line No.: " + Integer.toString(mCrashInfo.throwLineNumber)
            + LINE_SEPARATOR;
    //          + "Class: " + crashInfo.throwClassName + LINE_SEPARATOR
}




private static String reportCallStack(Throwable exception){

    StringWriter stackTrace = new StringWriter();

    exception.printStackTrace(new PrintWriter(stackTrace));

    String callStack = stackTrace.toString();

    String errMsg = exception.toString();

    return "\n************ CALLSTACK ************\n"
            + callStack.replace(errMsg, "")
            + LINE_SEPARATOR;
}




private static String reportDeviceInfo(){

    return "\n************ DEVICE INFORMATION ***********\n"
            + "Brand: "
            + Build.BRAND
            + LINE_SEPARATOR
            + "Device: "
            + Build.DEVICE
            + LINE_SEPARATOR
            + "Model: "
            + Build.MODEL
            + LINE_SEPARATOR
            + "Id: "
            + Build.ID
            + LINE_SEPARATOR
            + "Product: "
            + Build.PRODUCT
            + LINE_SEPARATOR;
}




private static String reportFirmware(){

    return "\n************ FIRMWARE ************\n"
            + "SDK: "
            + Build.VERSION.SDK_INT
            + LINE_SEPARATOR
            + "Release: "
            + Build.VERSION.RELEASE
            + LINE_SEPARATOR
            + "Incremental: "
            + Build.VERSION.INCREMENTAL
            + LINE_SEPARATOR;
}




// Empty the report as it is begin re-populated.
private static void reportEmptied(){

    // No need to empty
    if (mReportBuilder.length() == 0){

        return;
    }

    mReportBuilder.setLength(0);

    mReportBuilder.trimToSize();
}




@Override
public void uncaughtException(Thread thread, Throwable exception){

    // Don't re-enter -- avoid infinite loops if crash-reporting crashes.
    if (mCrashing) return;

    mCrashing = true;

    catchException(thread, exception);

    defaultExceptionHandler(thread, exception);
}




public String catchException(Thread thread, Throwable exception){

    String errorMsg = "";

    try{

        errorMsg = logCrash(exception);

    }catch (Exception ex){

        Log.e(mPackageName, ex.getMessage());
    }

    return errorMsg;
}




public static void defaultExceptionHandler(Thread thread, Throwable exception){

    try{

        // Execute the old handler.
        if (mOldHandler != null){

            mOldHandler.uncaughtException(thread, exception);
        }

    }catch (Exception ex){

        Log.e(mPackageName, ex.getMessage());
    }
}




public static String logCrash(Throwable exception){

    return errorMsg(exception, "deviceinfo firmware");
}




public void onDestroy(){

    mErrorHandler = null;
}

// Prevents infinite loops.
private static volatile boolean mCrashing = false;

private static final StringBuilder mReportBuilder = new StringBuilder();

private static final String LINE_SEPARATOR = "\n";

private static final UncaughtExceptionHandler mOldHandler = Thread
        .getDefaultUncaughtExceptionHandler();

private static ErrorHandler mErrorHandler;

private static String mPackageName;

private static ApplicationErrorReport.CrashInfo mCrashInfo;

private static String mErrorMessage = "";
  }