All Downloads are FREE. Search and download functionalities are using the official Maven repository.

.kotlinx.kotlinx-coroutines-android.1.9.0-RC.2.source-code.AndroidExceptionPreHandler.kt Maven / Gradle / Ivy

There is a newer version: 1.9.0
Show newest version
package kotlinx.coroutines.android

import android.os.*
import kotlinx.coroutines.*
import java.lang.reflect.*
import kotlin.coroutines.*

internal class AndroidExceptionPreHandler :
    AbstractCoroutineContextElement(CoroutineExceptionHandler), CoroutineExceptionHandler
{
    @Volatile
    private var _preHandler: Any? = this // uninitialized marker

    // Reflectively lookup pre-handler.
    private fun preHandler(): Method? {
        val current = _preHandler
        if (current !== this) return current as Method?
        val declared = try {
            Thread::class.java.getDeclaredMethod("getUncaughtExceptionPreHandler").takeIf {
                Modifier.isPublic(it.modifiers) && Modifier.isStatic(it.modifiers)
            }
        } catch (e: Throwable) {
            null /* not found */
        }
        _preHandler = declared
        return declared
    }

    override fun handleException(context: CoroutineContext, exception: Throwable) {
        /*
         * Android Oreo introduced private API for a global pre-handler for uncaught exceptions, to ensure that the
         * exceptions are logged even if the default uncaught exception handler is replaced by the app. The pre-handler
         * is invoked from the Thread's private dispatchUncaughtException() method, so our manual invocation of the
         * Thread's uncaught exception handler bypasses the pre-handler in Android Oreo, and uncaught coroutine
         * exceptions are not logged. This issue was addressed in Android Pie, which added a check in the default
         * uncaught exception handler to invoke the pre-handler if it was not invoked already (see
         * https://android-review.googlesource.com/c/platform/frameworks/base/+/654578/). So the issue is present only
         * in Android Oreo.
         *
         * We're fixing this by manually invoking the pre-handler using reflection, if running on an Android Oreo SDK
         * version (26 and 27).
         */
        if (Build.VERSION.SDK_INT in 26..27) {
            (preHandler()?.invoke(null) as? Thread.UncaughtExceptionHandler)
                ?.uncaughtException(Thread.currentThread(), exception)
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy