diff --git a/app/src/main/java/de/danoeh/antennapod/PodcastApp.java b/app/src/main/java/de/danoeh/antennapod/PodcastApp.java index ed3f4e8f1..534d48479 100644 --- a/app/src/main/java/de/danoeh/antennapod/PodcastApp.java +++ b/app/src/main/java/de/danoeh/antennapod/PodcastApp.java @@ -12,6 +12,8 @@ import com.joanzapata.iconify.fonts.MaterialModule; import de.danoeh.antennapod.activity.SplashActivity; import de.danoeh.antennapod.core.ApCoreEventBusIndex; import de.danoeh.antennapod.core.ClientConfig; +import de.danoeh.antennapod.error.CrashReportWriter; +import de.danoeh.antennapod.error.RxJavaErrorHandlerSetup; import de.danoeh.antennapod.spa.SPAUtil; import org.greenrobot.eventbus.EventBus; @@ -38,6 +40,7 @@ public class PodcastApp extends Application { super.onCreate(); Thread.setDefaultUncaughtExceptionHandler(new CrashReportWriter()); + RxJavaErrorHandlerSetup.setupRxJavaErrorHandler(); if (BuildConfig.DEBUG) { StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder() diff --git a/app/src/main/java/de/danoeh/antennapod/activity/BugReportActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/BugReportActivity.java index 48264bb26..fde7c0484 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/BugReportActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/BugReportActivity.java @@ -7,7 +7,7 @@ import android.os.Bundle; import com.google.android.material.snackbar.Snackbar; import androidx.appcompat.app.AppCompatActivity; import android.widget.TextView; -import de.danoeh.antennapod.CrashReportWriter; +import de.danoeh.antennapod.error.CrashReportWriter; import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.util.IntentUtils; diff --git a/app/src/main/java/de/danoeh/antennapod/CrashReportWriter.java b/app/src/main/java/de/danoeh/antennapod/error/CrashReportWriter.java similarity index 90% rename from app/src/main/java/de/danoeh/antennapod/CrashReportWriter.java rename to app/src/main/java/de/danoeh/antennapod/error/CrashReportWriter.java index b5d0f6945..dc62863f9 100644 --- a/app/src/main/java/de/danoeh/antennapod/CrashReportWriter.java +++ b/app/src/main/java/de/danoeh/antennapod/error/CrashReportWriter.java @@ -1,8 +1,9 @@ -package de.danoeh.antennapod; +package de.danoeh.antennapod.error; import android.os.Build; import android.util.Log; +import de.danoeh.antennapod.BuildConfig; import org.apache.commons.io.IOUtils; import java.io.File; @@ -31,6 +32,11 @@ public class CrashReportWriter implements Thread.UncaughtExceptionHandler { @Override public void uncaughtException(Thread thread, Throwable ex) { + write(ex); + defaultHandler.uncaughtException(thread, ex); + } + + public static void write(Throwable exception) { File path = getFile(); PrintWriter out = null; try { @@ -41,14 +47,13 @@ public class CrashReportWriter implements Thread.UncaughtExceptionHandler { out.println(); out.println("## StackTrace"); out.println("```"); - ex.printStackTrace(out); + exception.printStackTrace(out); out.println("```"); } catch (IOException e) { Log.e(TAG, Log.getStackTraceString(e)); } finally { IOUtils.closeQuietly(out); } - defaultHandler.uncaughtException(thread, ex); } public static String getSystemInfo() { diff --git a/app/src/main/java/de/danoeh/antennapod/error/RxJavaErrorHandlerSetup.java b/app/src/main/java/de/danoeh/antennapod/error/RxJavaErrorHandlerSetup.java new file mode 100644 index 000000000..1c7f5f0b4 --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/error/RxJavaErrorHandlerSetup.java @@ -0,0 +1,36 @@ +package de.danoeh.antennapod.error; + +import android.util.Log; +import de.danoeh.antennapod.BuildConfig; +import io.reactivex.exceptions.UndeliverableException; +import io.reactivex.plugins.RxJavaPlugins; + +public class RxJavaErrorHandlerSetup { + private static final String TAG = "RxJavaErrorHandler"; + + private RxJavaErrorHandlerSetup() { + + } + + public static void setupRxJavaErrorHandler() { + RxJavaPlugins.setErrorHandler(exception -> { + if (exception instanceof UndeliverableException) { + // Probably just disposed because the fragment was left + Log.d(TAG, "Ignored exception: " + Log.getStackTraceString(exception)); + return; + } + + // Usually, undeliverable exceptions are wrapped in an UndeliverableException. + // If an undeliverable exception is a NPE (or some others), wrapping does not happen. + // AntennaPod threads might throw NPEs after disposing because we set controllers to null. + // Just swallow all exceptions here. + Log.e(TAG, Log.getStackTraceString(exception)); + CrashReportWriter.write(exception); + + if (BuildConfig.DEBUG) { + Thread.currentThread().getUncaughtExceptionHandler() + .uncaughtException(Thread.currentThread(), exception); + } + }); + } +} diff --git a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceUpgrader.java b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceUpgrader.java index 367593131..7a282fc82 100644 --- a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceUpgrader.java +++ b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceUpgrader.java @@ -5,12 +5,11 @@ import android.content.SharedPreferences; import android.preference.PreferenceManager; import de.danoeh.antennapod.BuildConfig; -import de.danoeh.antennapod.CrashReportWriter; +import de.danoeh.antennapod.error.CrashReportWriter; import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.preferences.UserPreferences.EnqueueLocation; import de.danoeh.antennapod.core.util.download.AutoUpdateManager; -import de.danoeh.antennapod.core.util.gui.NotificationUtils; public class PreferenceUpgrader { private static final String PREF_CONFIGURED_VERSION = "version_code"; diff --git a/core/src/free/java/de/danoeh/antennapod/core/ClientConfig.java b/core/src/free/java/de/danoeh/antennapod/core/ClientConfig.java index 824a4fae3..ecb9d68df 100644 --- a/core/src/free/java/de/danoeh/antennapod/core/ClientConfig.java +++ b/core/src/free/java/de/danoeh/antennapod/core/ClientConfig.java @@ -9,7 +9,6 @@ import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; import de.danoeh.antennapod.core.storage.PodDBAdapter; import de.danoeh.antennapod.core.util.NetworkUtils; -import de.danoeh.antennapod.core.util.exception.RxJavaErrorHandlerSetup; import de.danoeh.antennapod.core.util.gui.NotificationUtils; import java.io.File; @@ -49,7 +48,6 @@ public class ClientConfig { NetworkUtils.init(context); AntennapodHttpClient.setCacheDirectory(new File(context.getCacheDir(), "okhttp")); SleepTimerPreferences.init(context); - RxJavaErrorHandlerSetup.setupRxJavaErrorHandler(); NotificationUtils.createChannels(context); initialized = true; } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/exception/RxJavaErrorHandlerSetup.java b/core/src/main/java/de/danoeh/antennapod/core/util/exception/RxJavaErrorHandlerSetup.java deleted file mode 100644 index 223104d2e..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/util/exception/RxJavaErrorHandlerSetup.java +++ /dev/null @@ -1,24 +0,0 @@ -package de.danoeh.antennapod.core.util.exception; - -import android.util.Log; -import io.reactivex.exceptions.UndeliverableException; -import io.reactivex.plugins.RxJavaPlugins; - -public class RxJavaErrorHandlerSetup { - - private RxJavaErrorHandlerSetup() { - - } - - public static void setupRxJavaErrorHandler() { - RxJavaPlugins.setErrorHandler(e -> { - if (e instanceof UndeliverableException) { - // Probably just disposed because the fragment was left - Log.d("RxJavaErrorHandler", "Ignored exception: " + Log.getStackTraceString(e)); - return; - } - Thread.currentThread().getUncaughtExceptionHandler() - .uncaughtException(Thread.currentThread(), e); - }); - } -} diff --git a/core/src/play/java/de/danoeh/antennapod/core/ClientConfig.java b/core/src/play/java/de/danoeh/antennapod/core/ClientConfig.java index 7d38aedc2..41e95d99e 100644 --- a/core/src/play/java/de/danoeh/antennapod/core/ClientConfig.java +++ b/core/src/play/java/de/danoeh/antennapod/core/ClientConfig.java @@ -1,7 +1,6 @@ package de.danoeh.antennapod.core; import android.content.Context; -import android.content.Intent; import android.util.Log; import com.google.android.gms.common.GoogleApiAvailability; import com.google.android.gms.common.GooglePlayServicesNotAvailableException; @@ -15,7 +14,6 @@ import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; import de.danoeh.antennapod.core.storage.PodDBAdapter; import de.danoeh.antennapod.core.util.NetworkUtils; -import de.danoeh.antennapod.core.util.exception.RxJavaErrorHandlerSetup; import de.danoeh.antennapod.core.util.gui.NotificationUtils; import java.io.File; @@ -67,7 +65,6 @@ public class ClientConfig { } AntennapodHttpClient.setCacheDirectory(new File(context.getCacheDir(), "okhttp")); SleepTimerPreferences.init(context); - RxJavaErrorHandlerSetup.setupRxJavaErrorHandler(); NotificationUtils.createChannels(context); initialized = true; }