Crash in Android BillingClient with coroutines
Asked Answered
E

3

6

I'm getting notified that my Billing solution is crashing in a weird way. I'm unable to reproduce it or find a fix/bypass the problem. Maybe you could help.

Fatal Exception: java.lang.IllegalStateException: Already resumed at kotlin.coroutines.SafeContinuation.resumeWith + 45(SafeContinuation.java:45) at com.android.billingclient.api.BillingClientKotlinKt$querySkuDetails$2$1.onSkuDetailsResponse + 2(BillingClientKotlinKt.java:2) at com.android.billingclient.api.zzj.run + 8(zzj.java:8) at android.os.Handler.handleCallback + 907(Handler.java:907) at android.os.Handler.dispatchMessage + 105(Handler.java:105) at android.os.Looper.loop + 216(Looper.java:216) at android.app.ActivityThread.main + 7625(ActivityThread.java:7625) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run + 524(RuntimeInit.java:524) at com.android.internal.os.ZygoteInit.main + 987(ZygoteInit.java:987)

//billing
implementation 'com.android.billingclient:billing:2.2.0'
implementation 'com.android.billingclient:billing-ktx:2.1.0'
Ecstatic answered 14/4, 2020 at 20:53 Comment(6)
I have same issue, too. Did you resolve this issue? @EcstaticCognition
Don't use billing-ktx, write it yourselfEcstatic
Have you solved it?Topaz
Implemented it on my own.Ecstatic
Can you share your solution as an answer? Many people will be thankful.Topaz
The bug is still present in version 3.0.0. Here's a link to the Google issue tracker: issuetracker.google.com/issues/161586451Currish
B
5

Since last week we have this code running to prevent the exception:

suspend fun BillingClient.querySkuDetailsFixed(params: SkuDetailsParams) = suspendCancellableCoroutine<SkuDetailsResult> { continuation ->
querySkuDetailsAsync(params) { billingResult, skuDetails: List<SkuDetails>? ->
    if (continuation.isActive) {
        // doing some logging
        continuation.resumeWith(Result.success(SkuDetailsResult(billingResult, skuDetails)))
    } else {
      // Already resumed, doing some logging
    }
}
}

In the logs we see that we get 2 calls from the library:

The first response has always the BillingResponseCode -3 SERVICE_TIMEOUT.

The second response often has either 6 ERROR or 2 SERVICE_UNAVAILABLE.

In our case this is happening when the app is awaken in the background for a PeriodicWorkRequest.

Bradleybradly answered 23/6, 2020 at 14:20 Comment(0)
G
0

Update Google Play Billing Library to version 3.0.2 or newer. It was a bug in a library that is fixed according to release notes:

Fixed a bug in the Kotlin extension where the coroutine fails with error "Already resumed".

Gleason answered 3/4, 2021 at 15:45 Comment(0)
V
0

I can 100% reproduce this crash, even using latest billing 5.0.0: "com.android.billingclient:billing-ktx:5.0.0".

I'm trying to wrap callback-base API for billing into coroutines:

private suspend fun doStart() {
        if (billingClient.isReady) {
            return
        }

        suspendCoroutine { cont ->
            val callback = object : BillingClientStateListener {
                override fun onBillingServiceDisconnected() {
                    cont.resumeWithException(RuntimeException())
                }

                override fun onBillingSetupFinished(result: BillingResult) {
                    when (result.responseCode) {
                        BillingClient.BillingResponseCode.OK -> cont.resume(true)
                        else -> cont.resumeWithException(RuntimeException())
                    }
                }
            }

            billingClient.startConnection(callback)
        }
    }

So, I start my billingClient lazily in onResume of single MainActivity and load active in-app purchases. As you can see from this method doStart(), it first checks billingClient.isReady, to avoid multiple starts.

I also have open-app ads integrated to my app, and let's say Open App Ad starts every 2nd COLD open of the app (COLD - after the app being killed, i.e. in onCreate()). We Open App Ad shows, it covers the entire screen.

So the crash happens in 100% cases when it's about time to show Open App Ad. Some conflict between started->then->resumed MainActivity and Ad proxy Activity. Stacktrace is exactly same, pointing to the line in onBillingServiceDisconnected():

cont.resumeWithException(RuntimeException()).

Vestal answered 19/8, 2022 at 17:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.