stripe / stripe-android

Stripe Android SDK
https://stripe.com/docs/mobile/android
MIT License
1.29k stars 645 forks source link

com.stripe.android.view.CardInputWidget crashes when inflated inside BottomSheetDialog #7755

Closed grepx closed 4 months ago

grepx commented 10 months ago

Summary

Hi, I'm having a problem with com.stripe.android.view.CardInputWidget - it crashes when inflated inside BottomSheetDialog from SDK version 20.32.0 - version 20.31.0 is fine. The issue is still present in the latest SDK version 20.36.0. Compiles fine and crash happens at runtime on Android 14 (haven't tested other Android versions). I've tested using the CardInputWidget inside the Fragment that launches the BottomSheetDialog and that seems to work fine - so it does seem like this has something particular to do with BottomSheetDialog.

Code to reproduce

View creation happens via inflation inside an xml file:

    <com.stripe.android.view.CardInputWidget
        android:id="@+id/cardInputWidget"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
...

Which is then inflated inside a com.google.android.material.bottomsheet.BottomSheetDialog using a view binding:

val viewBinding = CardInputBinding.inflate(layoutInflater)

Android version

Android 14

Impacted devices

Haven't tested other devices - happens on Pixel 7.

Installation method

Via gradle dependency.

Dependency Versions

kotlin: 1.9.10 stripe-android: 20.32.0 Android Gradle Plugin: 8.1.4 Gradle: 8.0

SDK classes

com.stripe.android.view.CardInputWidget

Video

Other information

This issue looks similar to the one described in https://github.com/stripe/stripe-android/issues/7484 and started occurring in the same release. It has not been fixed in the latest version (20.36.0) of the SDK though.

Stack Trace only contains Android SDK classes:

AndroidRuntime  E  FATAL EXCEPTION: main
                         E  Process: com.depop.dev, PID: 7068
                         E  java.lang.IllegalStateException: ViewTreeLifecycleOwner not found from android.widget.FrameLayout{3565a3d V.E...... ......I. 0,0-0,0 #7f0a02ff app:id/container}
                         E      at androidx.compose.ui.platform.WindowRecomposer_androidKt.createLifecycleAwareWindowRecomposer(WindowRecomposer.android.kt:352)
                         E      at androidx.compose.ui.platform.WindowRecomposer_androidKt.createLifecycleAwareWindowRecomposer$default(WindowRecomposer.android.kt:325)
                         E      at androidx.compose.ui.platform.WindowRecomposerFactory$Companion$LifecycleAware$1.createRecomposer(WindowRecomposer.android.kt:168)
                         E      at androidx.compose.ui.platform.WindowRecomposerPolicy.createAndInstallWindowRecomposer$ui_release(WindowRecomposer.android.kt:224)
                         E      at androidx.compose.ui.platform.WindowRecomposer_androidKt.getWindowRecomposer(WindowRecomposer.android.kt:300)
                         E      at androidx.compose.ui.platform.AbstractComposeView.resolveParentCompositionContext(ComposeView.android.kt:244)
                         E      at androidx.compose.ui.platform.AbstractComposeView.ensureCompositionCreated(ComposeView.android.kt:251)
                         E      at androidx.compose.ui.platform.AbstractComposeView.onAttachedToWindow(ComposeView.android.kt:283)
                         E      at android.view.View.dispatchAttachedToWindow(View.java:21980)
                         E      at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3490)
                         E      at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497)
                         E      at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497)
                         E      at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497)
                         E      at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497)
                         E      at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497)
                         E      at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497)
                         E      at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497)
                         E      at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497)
                         E      at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497)
                         E      at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497)
                         E      at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497)
                         E      at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3014)
                         E      at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2465)
                         E      at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:9305)
                         E      at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1339)
                         E      at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1348)
                         E      at android.view.Choreographer.doCallbacks(Choreographer.java:952)
                         E      at android.view.Choreographer.doFrame(Choreographer.java:882)
                         E      at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1322)
                         E      at android.os.Handler.handleCallback(Handler.java:958)
                         E      at android.os.Handler.dispatchMessage(Handler.java:99)
                         E      at android.os.Looper.loopOnce(Looper.java:205)
                         E      at android.os.Looper.loop(Looper.java:294)
                         E      at android.app.ActivityThread.main(ActivityThread.java:8177)
                         E      at java.lang.reflect.Method.invoke(Native Method)
                         E      at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
                         E      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
tillh-stripe commented 9 months ago

Hi @grepx 👋 Thanks for reporting this issue, and for the detailed description. I’m able to reproduce the crash.

I’ll look into a solution for BottomSheetDialog. In the meantime, is it feasible for you to switch to a BottomSheetDialogFragment? This one is a Fragment and thus a LifecycleOwner, which means that the crash won’t occur.

Even easier: We provide a pre-built bottom sheet called PaymentSheet, where you wouldn’t have to build any UI yourself. The docs are here and I’d be more than happy to help with the migration. It does support lots of local payment methods across the world, but you can also limit it to just cards if you want.

rscherf commented 7 months ago

I'd also love to see this fixed, as it is blocking me from implementing the co-badged-card requirements on the CardInputWidget, as I need to move from 20.29.2 to > 20.37.4:

https://docs.stripe.com/co-badged-cards-compliance?type=mobile-elements&mobile-ui=card-element#integration-guides

On the older version, there is no crash, however on the newer version it crashes.

View dialogView = LayoutInflater.from(this).inflate(R.layout.pv_stripe_card_input_widget, null);
com.stripe.android.view.CardInputWidget cardInputWidget = dialogView.findViewById(R.id.cardInputWidget);

androidx.appcompat.app.AlertDialog cardInputDialog = new MaterialAlertDialogBuilder(this, R.style.PaymentAlertDialogStyle)
                .setView(dialogView)
                .create();
cardInputDialog.show();
jaynewstrom-stripe commented 4 months ago

I'm going to close this as a duplicate of https://github.com/stripe/stripe-android/issues/8625

I realize this isn't fixed yet, and I apologize for that. We will work on a path forward and update the other issue when we have something to share.