braintree / braintree_android

Braintree SDK for Android
https://developer.paypal.com/braintree/docs/start/hello-client/android/v4
MIT License
405 stars 232 forks source link

Crash on VenmoClient and venmoListener initilize after Fragment/Activity onResume. #732

Open sreereddymenon opened 1 year ago

sreereddymenon commented 1 year ago

Braintree SDK Version

4.28.0

Environment

Sandbox

Android Version & Device

Google Pixel 3

Braintree dependencies

   using following depedencies 

    venmo               : '4.28.0',
    paypal              : '4.28.0',
    dataCollector       : '4.28.0',

Describe the bug

Let me describe the scenario,

Our app consists of single activity approach, our app is a single activity with multiple modules/multiple fragments(NavGraph).....

we have a bottomsheet where we show Add Venmo Button, Upon clicking on that button, we initialize BraintreeClient by fetching clientToken (we show progressIndiactor while fetching it) from our server. once we have the token, we call

    braintreeClient = BraintreeClient(activity, token)

     then 

     venmoClient = VenmoClient(this, braintreeClient)
    venmoClient.setListener(venmoListener)

Crash Log

FATAL EXCEPTION: main

                                                                                                    Process: com.sei.android, PID: 9661

                                                                                                    java.lang.IllegalStateException: LifecycleOwner MainActivity@45d7e5b is attempting to register while current state is RESUMED. LifecycleOwners must call register before they are STARTED.

                                                                                                    at androidx.activity.result.ActivityResultRegistry.i(ActivityResultRegistry.java:123)

                                                                                                    at com.braintreepayments.api.VenmoLifecycleObserver.d(VenmoLifecycleObserver.java:34)

                                                                                                    at androidx.lifecycle.b0$b.a(LifecycleRegistry.kt:314)

                                                                                                    at androidx.lifecycle.b0.a(LifecycleRegistry.kt:192)

                                                                                                    at com.braintreepayments.api.t3.h(VenmoClient.java:95)

                                                                                                    at com.braintreepayments.api.t3.(VenmoClient.java:89)

                                                                                                    at com.braintreepayments.api.t3.(VenmoClient.java:66)

                                                                                                    at com.braintreepayments.api.t3.(VenmoClient.java:52)

                                                                                                   

To reproduce

Initilize venmoClient after fragment is resumed

Expected behavior

It shouldn't crash

Screenshots

No response

sreereddymenon commented 1 year ago

I know..what you guys gonna suggest.. Definitely not possible to initialize braintree client before we open up bottomsheet or any such tricks!!

sshropshire commented 1 year ago

Hi @sreereddymenon thanks for using the Braintree SDK for Android. Have you taken a look at ClientTokenProvider?

This is a known limitation in our SDK because we use the Activity Result API internally, and it has the same restriction. We are working on a solution for this in our next major version to remove this restriction.

Another option would be to fetch a client token and forward it to your in progress activity via Intent extras. It's a bit much, but it's a viable workaround.

Let me know if any of the above helps.

sreereddymenon commented 1 year ago

@sshropshire Got it!! Thats not possible with our current app architecture. I have started initializing the VenmoClient without passing the fragment/activity instance.

    venmoClient = VenmoClient(brainTreeClient())

 venmoClient.tokenizeVenmoAccount(
            requireActivity(),
            venmoRequest,
            VenmoTokenizeAccountCallback { error: java.lang.Exception? ->

}

and then handling the onactivityresult ourselves using

 venmoClient.onActivityResult(requireContext(), resultCode, data,
                VenmoOnActivityResultCallback { venmoAccountNonce: VenmoAccountNonce?, error: Exception? ->

}

this implementation is working well and I have no idea if we do have any consequences/drawbacks.. Thank you!!

sshropshire commented 1 year ago

Ok the deprecated methods are still covered by our unit tests so there shouldn't be any drawbacks. We've considered removing deprecation for some methods, but we may hold off until the beta to avoid confusion with new merchants onboarding. I'll keep this open for tracking until our initial beta removes this restriction.

tdchow commented 1 month ago

Hey @sreereddymenon! We just released a beta for the next major version, v5.

In this new version, the VenmoClient no longer requires references to Fragment or Activity. We'd love for you to try out the new version and provide feedback.

v5 Venmo Migration Guide: https://github.com/braintree/braintree_android/blob/main/v5_MIGRATION_GUIDE.md#venmo v5 Release: https://github.com/braintree/braintree_android/releases/tag/5.0.0-beta1