1 package kotlinx.coroutines.android 2 3 import android.os.* 4 import kotlinx.coroutines.* 5 import java.lang.reflect.* 6 import kotlin.coroutines.* 7 8 internal class AndroidExceptionPreHandler : 9 AbstractCoroutineContextElement(CoroutineExceptionHandler), CoroutineExceptionHandler 10 { 11 @Volatile 12 private var _preHandler: Any? = this // uninitialized marker 13 14 // Reflectively lookup pre-handler. preHandlernull15 private fun preHandler(): Method? { 16 val current = _preHandler 17 if (current !== this) return current as Method? 18 val declared = try { 19 Thread::class.java.getDeclaredMethod("getUncaughtExceptionPreHandler").takeIf { 20 Modifier.isPublic(it.modifiers) && Modifier.isStatic(it.modifiers) 21 } 22 } catch (e: Throwable) { 23 null /* not found */ 24 } 25 _preHandler = declared 26 return declared 27 } 28 handleExceptionnull29 override fun handleException(context: CoroutineContext, exception: Throwable) { 30 /* 31 * Android Oreo introduced private API for a global pre-handler for uncaught exceptions, to ensure that the 32 * exceptions are logged even if the default uncaught exception handler is replaced by the app. The pre-handler 33 * is invoked from the Thread's private dispatchUncaughtException() method, so our manual invocation of the 34 * Thread's uncaught exception handler bypasses the pre-handler in Android Oreo, and uncaught coroutine 35 * exceptions are not logged. This issue was addressed in Android Pie, which added a check in the default 36 * uncaught exception handler to invoke the pre-handler if it was not invoked already (see 37 * https://android-review.googlesource.com/c/platform/frameworks/base/+/654578/). So the issue is present only 38 * in Android Oreo. 39 * 40 * We're fixing this by manually invoking the pre-handler using reflection, if running on an Android Oreo SDK 41 * version (26 and 27). 42 */ 43 if (Build.VERSION.SDK_INT in 26..27) { 44 (preHandler()?.invoke(null) as? Thread.UncaughtExceptionHandler) 45 ?.uncaughtException(Thread.currentThread(), exception) 46 } 47 } 48 } 49