class MapboxUncaughtExceptionHanlder implements Thread.UncaughtExceptionHandler,
  SharedPreferences.OnSharedPreferenceChangeListener {

  @Override
  public void uncaughtException(Thread thread, Throwable throwable) {
    // If we're not enabled or crash is not in Mapbox code
    // then just pass the Exception on to the defaultExceptionHandler.
    List<Throwable> causalChain;
    if (isEnabled.get() && isMapboxCrash(causalChain = getCausalChain(throwable))) {
      try {
        CrashReport report = CrashReportBuilder.setup(applicationContext, mapboxPackage, version)
          .addExceptionThread(thread)
          .addCausalChain(causalChain)
          .build();

        ensureDirectoryWritable(applicationContext, mapboxPackage);

        File file = FileUtils.getFile(applicationContext, getReportFileName(mapboxPackage, report.getDateString()));
        FileUtils.writeToFile(file, report.toJson());
      } catch (Exception ex) {
        Log.e(TAG, ex.toString());
      }
    }

    // Give default exception handler a chance to handle exception
    if (defaultExceptionHandler != null) {
      defaultExceptionHandler.uncaughtException(thread, throwable);
    } else {
      Log.i(TAG, "Default exception handler is null");
    }
  }

  @VisibleForTesting  MapboxUncaughtExceptionHanlder(@NonNull Context applicationContext,
                                 @NonNull SharedPreferences sharedPreferences,
                                 @NonNull String mapboxPackage,
                                 @NonNull String version,
                                 Thread.UncaughtExceptionHandler defaultExceptionHandler);

}