Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] CardBrandView change to Composable causes app crashes #8625

Open
magouyaware opened this issue Jun 13, 2024 · 8 comments
Open

[BUG] CardBrandView change to Composable causes app crashes #8625

magouyaware opened this issue Jun 13, 2024 · 8 comments
Labels

Comments

@magouyaware
Copy link

magouyaware commented Jun 13, 2024

Summary

This issue is a weird one in that it can be traced back to the Stripe Android SDK but only manifests itself within React Native. The issue at play affects both Stripe's React Native SDK as well as our Olo Pay React Native SDK, both of which are built on top of Stripe's Android SDK.

It appears that CardBrandView was changed in v20.36.0 to be a Composable as part of the Card Brand Choice feature. This change affects CardInputWidget, CardMultilineWidget, and CardFormView and causes many issues in React Native, which doesn't have great support for Jetpack Compose.

Updating to v20.36.0 or later caused issues that we had never seen before:

  • App crashes
  • Card brand icon completely disappears and stops rendering (likely due to this issue)

These issues occur in our React Native SDK, which is built on top of our Android SDK, and have been traced back to Stripe's Android SDK implementation, specifically related to using a Composable inside normal views.

Stripe's own React Native SDK is also affected by this, and we have found many issues in Stripe's React Native repo that others have reported that ultimately are due to this Android Composable. Here are few (this is by no means an exhaustive list):

Android version

20.36.0 and newer

Installation method

Gradle

SDK classes

Video

Disappearing.Card.Brand.Icon.mov
Compose.Crash.mov

Crash Stacktrace

Exception in native call
java.lang.IllegalStateException: Cannot locate windowRecomposer; View androidx.compose.ui.platform.ComposeView{3fa3229 V.E...... ......I. 0,0-0,0 #7f080153 app:id/icon} is not attached to a window
	at androidx.compose.ui.platform.WindowRecomposer_androidKt.getWindowRecomposer(WindowRecomposer.android.kt:295)
	at androidx.compose.ui.platform.AbstractComposeView.resolveParentCompositionContext(ComposeView.android.kt:244)
	at androidx.compose.ui.platform.AbstractComposeView.ensureCompositionCreated(ComposeView.android.kt:251)
	at androidx.compose.ui.platform.AbstractComposeView.onMeasure(ComposeView.android.kt:288)
	at android.view.View.measure(View.java:26357)
	at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6981)
	at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
	at android.view.View.measure(View.java:26357)
	at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6981)
	at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
	at android.view.View.measure(View.java:26357)
	at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6981)
	at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1608)
	at android.widget.LinearLayout.measureVertical(LinearLayout.java:878)
	at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
	at android.view.View.measure(View.java:26357)
	at androidx.constraintlayout.widget.ConstraintLayout$Measurer.measure(ConstraintLayout.java:811)
	at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.measure(BasicMeasure.java:466)
	at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.measureChildren(BasicMeasure.java:134)
	at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.solverMeasure(BasicMeasure.java:278)
	at androidx.constraintlayout.core.widgets.ConstraintWidgetContainer.measure(ConstraintWidgetContainer.java:120)
	at androidx.constraintlayout.widget.ConstraintLayout.resolveSystem(ConstraintLayout.java:1594)
	at androidx.constraintlayout.widget.ConstraintLayout.onMeasure(ConstraintLayout.java:1708)
	at android.view.View.measure(View.java:26357)
	at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6981)
	at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
	at androidx.cardview.widget.CardView.onMeasure(CardView.java:260)
	at com.google.android.material.card.MaterialCardView.onMeasure(MaterialCardView.java:211)
	at android.view.View.measure(View.java:26357)
	at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6981)
	at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1608)
	at android.widget.LinearLayout.measureVertical(LinearLayout.java:878)
	at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
	at android.view.View.measure(View.java:26357)
	at androidx.constraintlayout.widget.ConstraintLayout$Measurer.measure(ConstraintLayout.java:811)
	at androidx.constraintlayout.core.widgets.ConstraintWidgetContainer.measure(ConstraintWidgetContainer.java:632)
	at androidx.constraintlayout.core.widgets.analyzer.Direct.horizontalSolvingPass(Direct.java:323)
	at androidx.constraintlayout.core.widgets.analyzer.Direct.solveHorizontalMatchConstraint(Direct.java:709)
	at androidx.constraintlayout.core.widgets.analyzer.Direct.horizontalSolvingPass(Direct.java:374)
	at androidx.constraintlayout.core.widgets.analyzer.Direct.solvingPass(Direct.java:144)
	at androidx.constraintlayout.core.widgets.ConstraintWidgetContainer.layout(ConstraintWidgetContainer.java:693)
	at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.solveLinearSystem(BasicMeasure.java:160)
	at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.solverMeasure(BasicMeasure.java:291)
	at androidx.constraintlayout.core.widgets.ConstraintWidgetContainer.measure(ConstraintWidgetContainer.java:120)
	at androidx.constraintlayout.widget.ConstraintLayout.resolveSystem(ConstraintLayout.java:1594)
	at androidx.constraintlayout.widget.ConstraintLayout.onMeasure(ConstraintLayout.java:1708)
	at android.view.View.measure(View.java:26357)
	at androidx.constraintlayout.widget.ConstraintLayout$Measurer.measure(ConstraintLayout.java:811)
	at androidx.constraintlayout.core.widgets.ConstraintWidgetContainer.measure(ConstraintWidgetContainer.java:632)
	at androidx.constraintlayout.core.widgets.analyzer.Direct.horizontalSolvingPass(Direct.java:323)
	at androidx.constraintlayout.core.widgets.analyzer.Direct.solveHorizontalMatchConstraint(Direct.java:709)
	at androidx.constraintlayout.core.widgets.analyzer.Direct.horizontalSolvingPass(Direct.java:374)
	at androidx.constraintlayout.core.widgets.analyzer.Direct.solvingPass(Direct.java:144)
	at androidx.constraintlayout.core.widgets.ConstraintWidgetContainer.layout(ConstraintWidgetContainer.java:693)
	at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.solveLinearSystem(BasicMeasure.java:160)
	at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.solverMeasure(BasicMeasure.java:291)
	at androidx.constraintlayout.core.widgets.ConstraintWidgetContainer.measure(ConstraintWidgetContainer.java:120)
	at androidx.constraintlayout.widget.ConstraintLayout.resolveSystem(ConstraintLayout.java:1594)
	at androidx.constraintlayout.widget.ConstraintLayout.onMeasure(ConstraintLayout.java:1708)
	at android.view.View.measure(View.java:26357)
	at com.facebook.react.uimanager.NativeViewHierarchyManager.updateLayout(NativeViewHierarchyManager.java:189)
	at com.facebook.react.uimanager.UIViewOperationQueue$UpdateLayoutOperation.execute(UIViewOperationQueue.java:169)
	at com.facebook.react.uimanager.UIViewOperationQueue$1.run(UIViewOperationQueue.java:915)
	at com.facebook.react.uimanager.UIViewOperationQueue.flushPendingBatches(UIViewOperationQueue.java:1026)
	at com.facebook.react.uimanager.UIViewOperationQueue.access$2600(UIViewOperationQueue.java:47)
	at com.facebook.react.uimanager.UIViewOperationQueue$DispatchUIFrameCallback.doFrameGuarded(UIViewOperationQueue.java:1086)
	at com.facebook.react.uimanager.GuardedFrameCallback.doFrame(GuardedFrameCallback.java:29)
	at com.facebook.react.modules.core.ReactChoreographer$ReactChoreographerDispatcher.doFrame(ReactChoreographer.java:175)
	at com.facebook.react.modules.core.ChoreographerCompat$FrameCallback$1.doFrame(ChoreographerCompat.java:85)
	at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1229)
	at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1239)
	at android.view.Choreographer.doCallbacks(Choreographer.java:899)
	at android.view.Choreographer.doFrame(Choreographer.java:827)
	at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1214)
	at android.os.Handler.handleCallback(Handler.java:942)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at android.os.Looper.loopOnce(Looper.java:201)
	at android.os.Looper.loop(Looper.java:288)
	at android.app.ActivityThread.main(ActivityThread.java:7872)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)

@jaynewstrom-stripe
Copy link
Collaborator

Hi @magouyaware thanks for the report. I'm able to reproduce the issue when extending from android.app.Activity. We made some assumptions that aren't true in that case.

If there's any possibility to extend from androidx.appcompat.app.AppCompatActivity instead, the issues should be resolved. That being said, I know that's not possible in all cases.

I'm going to talk with the team to come up with a path forward.

@Resource-4
Copy link

@jaynewstrom-stripe When is the expected fix for this issue?

@jaynewstrom-stripe
Copy link
Collaborator

We don't have an estimate for the fix at this time. I'll update this issue when we have more information.

@Resource-4
Copy link

Do you have any workaround or suggestion until the issue is fixed?

@magouyaware
Copy link
Author

@jaynewstrom-stripe I just took a look at the react native test harness app we use to test our SDK and verified that we are using a subclass of androidx.appcompat.app.AppCompatActivity

Our activity extends ReactActivity, which I believe is pretty standard for all newish React Native apps. ReactActivity extends AppCompatActivity

Screenshot 2024-06-21 at 4 06 08 PM

@magouyaware
Copy link
Author

magouyaware commented Jun 25, 2024

@jaynewstrom-stripe This is a pretty big deal for us and is preventing us from being able to update our React Native SDK to use a newer version of our Android SDK.

Right now, the current version of our React Native SDK is using a version of our Android SDK that is built on Stripe Android v20.25.5... released over a year ago on June 5th, 2023.

We cannot update to a newer version of our Android SDK because it introduces this crash issue, and we have several bug fixes that we cannot address in our RN SDK simply because we are blocked from updating the Olo Pay Android SDK version it uses.

@jaynewstrom-stripe
Copy link
Collaborator

We acknowledge this is a big deal, and we're actively working to fix it. We will post an update when we have more to share.

@Resource-4
Copy link

Any update? @jaynewstrom-stripe. We really need this to resolve ASAP.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants