stripe / stripe-terminal-android

Stripe Terminal Android SDK
https://stripe.dev/stripe-terminal-android/
Other
94 stars 46 forks source link

Reader Issue (3.9.2) #502

Closed Mahdi-Rida closed 1 month ago

Mahdi-Rida commented 2 months ago

when i try to connect to a reader in live mode, and after 1 minute of waiting i got this failure error : getReader | onFailure: Cannot get readers 11: com.stripe.stripeterminal.external.models.TerminalException: Contactless transaction failed com.stripe.core.aidlrpc.AidlRpcException: Service never connected.

My code is :

fun initTerminal(app: Application) {

    try {
        Log.d(TAG, "init: start")
        TerminalApplicationDelegate.onCreate(app)
        Terminal.initTerminal(
            app,
            LogLevel.ERROR,
            tokenProvider, this
        )
    } catch (e: Exception) {
        Log.d(TAG, "initTerminal: Location services are required in order to initialize")
        throw RuntimeException(
            "Location services are required in order to initialize " +
                    "the Terminal.",
            e
        )
    }

    initialize()
}

get Reader : suspendCancellableCoroutine { continuation -> Log.d(TAG, "getReader: start") val config = DiscoveryConfiguration.LocalMobileDiscoveryConfiguration( isSimulated = BuildConfig.DEBUG, ) try { discoveryCancelable = Terminal.getInstance().discoverReaders( config, object : DiscoveryListener { override fun onUpdateDiscoveredReaders(readers: List) { if (readers.isEmpty()) { disconnectReader() _state.update { it.copy(isLoading = false, errorMessage = "Reader not found") } Log.d(TAG, "onUpdateDiscoveredReaders: No Readers found") continuation.resume(Unit) } else { Log.d(TAG, "onUpdateDiscoveredReaders: readers : $readers") val locationConfig = ConnectionConfiguration.LocalMobileConnectionConfiguration( locationID ) Terminal.getInstance() .connectLocalMobileReader( readers[0], locationConfig, object : ReaderCallback { override fun onSuccess(reader: Reader) { deviceReader = reader Log.d( TAG, "getReader | onSuccess: reader Set : ${reader}" ) continuation.resume(Unit) }

                                                override fun onFailure(e: TerminalException) {
                                                    disconnectReader()
                                                    _state.update {
                                                        it.copy(
                                                            errorMessage = "Cannot get reader: ${e.errorCode}",
                                                            isLoading = false
                                                        )
                                                    }
                                                    Log.d(
                                                        TAG,
                                                        "getReader | onFailure: Cannot get reader: ${e.message}"
                                                    )
                                                    continuation.resume(Unit)
                                                }
                                            })
                                }
                            }
                        },
                        object : Callback {
                            override fun onSuccess() {
                                Log.d(
                                    TAG,
                                    "getReader | onSuccess: Finished discovering readers"
                                )
                            }

                            override fun onFailure(e: TerminalException) {
                                _state.update { it.copy(errorMessage = "Cannot get readers : ${e.message}") }
                                Log.d(
                                    TAG,
                                    "getReader | onFailure: Cannot get readers 11: ${e.toString()}"
                                )
                                continuation.resume(Unit)
                            }
                        }
                    )
                } catch (e: Exception) {
                    Log.d(TAG, "getReader: error: ${e.message}")
                }

            }
Mahdi-Rida commented 2 months ago

Hello again, i tried your simple example code , using the version 2.20.0, eveything is working good, but when i try the same code on my version 3.9.0 or 3.9.1 or 3.9.2 , when i call the init terminal from myh Application, then i try to getReaders, the app crashes sometimes, and the result of the get readers is -> getReader | onFailure: Cannot get readers 11: com.stripe.stripeterminal.external.models.TerminalException: Contactless transaction failed com.stripe.core.aidlrpc.AidlRpcException: Service never connected.

sidhant-stripe commented 2 months ago

Hi Mahdi, can you share a full stack trace and any other logcat error output for this crash? It would also help to know what target SDK version you're using for this build and the model of device you're using.

sidhant-stripe commented 2 months ago

Also, are you using desugaring?

Mahdi-Rida commented 2 months ago

Hello Again,

Yes am using desugaring : coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:2.0.3"

Note : I’ve tried the following versions : 3.9.0/3.9.1/3.9.2/3.9.3 -> same problem

These are the steps that causes the crash : 1- App Starts (this should never be called again) 2- Init the Terminal in the onCreate of the App Till now we’re good 3- get readers with isSimulate = false (because we are testing in live mode) 4- Once the get readers is called -> The App Starts again , the terminal is initialized again (this is the crash of the application) because am not expecting the app to start again, this happened only in this case

This is the full logcat:

09:22:33.765 application | onCreate: start 09:22:33.765 stripeManager | init: start 09:22:34.012 stripeManager | fetchUserLocationID: start 09:22:37.107 stripeManager | fetchUserLocationID: locationId : tml_FoxjAagimUD4qM 09:22:37.107 stripeManager | fetchPaymentConfiguration: start 09:22:37.341 stripeManager | fetchConnectionToken: secret : pst_test_YWNjdF8xTFRSYnhGUG1wbVRFZmNYLDNjUVBrdHMxajdOaTBHbWhyZDNLNHFCTDJCclN3RzQ_00nbJrdBCp —> getReaders 09:23:48.509 application | onCreate: start 09:23:49.983 application | onCreate: start 09:23:48.509 stripeManager | init: start 09:23:49.983 stripeManager | init: start 09:24:48.415 stripeManager | getReader | onFailure: Cannot get readers : com.stripe.stripeterminal.external.models.TerminalException: Contactless transaction failed com.stripe.core.aidlrpc.AidlRpcException: Service never connected.

And one more thing, there is no stacktrace from the terminal sdk itself, I discovered this crash by following my logs only

sidhant-stripe commented 2 months ago

Hi Mahdi, another user found that this issue was resolved by updating the desugaring library: https://github.com/stripe/stripe-terminal-android/issues/504#issuecomment-2353548776

can you try this and let us know if it resolves the issue?

Mahdi-Rida commented 2 months ago

Hello Sidhant, i was following your discussion, i tried the update, didnt work, i tried to remove the disugaring, nothing helped, my logcat is so obvious, my application crashes twice after calling getREader, and that's because the terminal initialization takes the application as parameter, something happened in the sdk, in old versions this problem is not exist, but i cant downgrade because the company project is up to date and can't be downgraded, a lot of features will be unavailable

sidhant-stripe commented 2 months ago

What device are you testing this on? Does this crash occur on all devices you've tested with? Also, are you using targetSdk 35 by any chance?

Mahdi-Rida commented 2 months ago

i tried on google pixel 6, samsung s22 ultra, same issue on both, i tried target sdk 34 and 35, also same problem

Mahdi-Rida commented 2 months ago

Sorry for this but is this issue happend on your side ?

Mahdi-Rida commented 2 months ago

Hello Again, Any Update please ? we are blocked here

sidhant-stripe commented 2 months ago

Hi Mahdi, I took a look at your logs and I saw this:

com.stripe.stripeterminal.external.models.TerminalException: Debuggable applications are not supported in the production version of the localmobile reader. Please use a simulated version of the reader by setting `DiscoveryConfiguration.isSimulated` to true.
    at com.stripe.stripeterminal.internal.common.adapter.CotsAdapter.callAidlWithExceptionConverted(CotsAdapter.kt:681)
    at com.stripe.stripeterminal.internal.common.adapter.CotsAdapter.access$callAidlWithExceptionConverted(CotsAdapter.kt:83)
    at com.stripe.stripeterminal.internal.common.adapter.CotsAdapter$DiscoverReadersOperation.execute(CotsAdapter.kt:706)
    at com.stripe.stripeterminal.internal.common.adapter.CotsAdapter$DiscoverReadersOperation.execute(CotsAdapter.kt:701)
    at com.stripe.stripeterminal.internal.common.adapter.CotsAdapter.discoverReaders(CotsAdapter.kt:514)
    at com.stripe.stripeterminal.internal.common.adapter.ProxyAdapter.discoverReaders(ProxyAdapter.kt:259)
    at com.stripe.stripeterminal.internal.common.terminalsession.TerminalSession$DiscoverReadersOperation.executeIfNotCanceled(TerminalSession.kt:2432)
    at com.stripe.stripeterminal.internal.common.terminalsession.TerminalSession$CancelableOperation.execute(TerminalSession.kt:1312)
    at com.stripe.stripeterminal.internal.common.terminalsession.TerminalSession$ExternalOperation.run$terminalsession_release(TerminalSession.kt:1267)
    at com.stripe.stripeterminal.internal.common.terminalsession.TerminalSession.enqueueOperation$lambda$6(TerminalSession.kt:1082)
    at com.stripe.stripeterminal.internal.common.terminalsession.TerminalSession.$r8$lambda$9_FdDGpM1BaifeFRjKBBfCCLP6o(Unknown Source:0)
    at com.stripe.stripeterminal.internal.common.terminalsession.TerminalSession$$ExternalSyntheticLambda0.run(D8$$SyntheticClass:0)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:487)
    at java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
    at java.lang.Thread.run(Thread.java:1012)

It looks like you're attempting to use a non-simulated reader in a debug build. If you build in release, this should work.

Mahdi-Rida commented 2 months ago

Hello , here i was trying on the emulator, but the real problem exists on real device

sidhant-stripe commented 2 months ago

Hi Mahdi,

The issue is not that this is an emulated device, rather it's happening because your app is debuggable. We do not permit debuggable apps to get access to a non-simulated reader. You will have to build a release apk, which you can do by clicking Build -> Generate signed app bundle/apk and then selecting the release build variant.

You will also need to make sure that your app is not debuggable. Please try these steps and let me know if it works for you.

Mahdi-Rida commented 2 months ago

Hello , I ran the app in release mode before i opened the issue, Note s22 ultra, google pixel 6, with build variant release and isSimulated = false , the issue is when i try to get the reader, the Application is created one more time or twice , this must not happen, this is a crash in the terminal sdk causes my app to recreate, would you like a video recording with live test in release mode ?

chr-stripe commented 2 months ago

Hi Mahdi,

The fact that a new Application is created when using the Tap to Pay SDK in release mode is expected. The Tap to Pay service runs in a separate process for your application, which does cause your Application's onCreate() method to be called again in this new process.

If you are performing some initialization in your Application class that should only be performed in the main app process, you can use some code like the one in described in issue #323 to skip this initialization when the Tap to Pay process starts.

Mahdi-Rida commented 1 month ago

Hello, Thank you for your help, i did exactly what you mentioned above, but am still getting this : onFailure: Cannot get readers 11: com.stripe.stripeterminal.external.models.TerminalException: Contactless transaction failed com.stripe.core.aidlrpc.AidlRpcException: Service never connected.

sidhant-stripe commented 1 month ago

Hi Mahdi, can you confirm that the UUID of the device you're experiencing this on is 936b7b1b-f244-4789-8d99-ad246220e459? You should be able to see the UUID in the logs. I'm also seeing on our end that you're using targetSdk 35, please make sure to remain on 34 for the time being.

Mahdi-Rida commented 1 month ago

Hello, Downgrading to sdk 34 solve the issue, thank you for your good support