FinTecSystems / xs2a-android

[Client] Native Android SDK for Tink Germany XS2A API.
https://tink.com/de/fts
Other
6 stars 4 forks source link

NullPointerException com.fintecsystems.xs2awizard_networking.NetworkingInstance #9

Closed hossamCheck24 closed 1 year ago

hossamCheck24 commented 1 year ago

Hello @maik-mursall we face crash inside the sdk this is logs of crash could you please help java.lang.NullPointerException: null at com.fintecsystems.xs2awizard_networking.NetworkingInstance.constructBody(SourceFile:93) at com.fintecsystems.xs2awizard_networking.NetworkingInstance.encodeAndSendMessage(SourceFile:70) at com.fintecsystems.xs2awizard.components.XS2AWizardViewModel.submitForm(SourceFile:245) at com.fintecsystems.xs2awizard.components.XS2AWizardViewModel.submitForm(SourceFile:225) at com.fintecsystems.xs2awizard.components.XS2AWizardViewModel.initForm(SourceFile:130) at com.fintecsystems.xs2awizard.components.XS2AWizardViewModel.onStart(SourceFile:110) at com.fintecsystems.xs2awizard.XS2AWizardKt$XS2AWizard$2.invoke(SourceFile:66) at com.fintecsystems.xs2awizard.XS2AWizardKt$XS2AWizard$2.invoke(SourceFile:64) at androidx.compose.runtime.DisposableEffectImpl.onRemembered at androidx.compose.runtime.CompositionImpl$RememberEventDispatcher.dispatchRememberObservers(SourceFile:1032) at androidx.compose.runtime.CompositionImpl.applyChangesInLocked(SourceFile:793) at androidx.compose.runtime.CompositionImpl.applyChanges(SourceFile:815) at androidx.compose.runtime.Recomposer.composeInitial$runtime_release(SourceFile:827) at androidx.compose.runtime.CompositionImpl.setContent(SourceFile:521) at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(SourceFile:163) at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke at androidx.compose.ui.platform.AndroidComposeView.setOnViewTreeOwnersAvailable(SourceFile:1015) at androidx.compose.ui.platform.WrappedComposition.setContent at androidx.compose.ui.platform.WrappedComposition.onStateChanged(SourceFile:184) at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(SourceFile:362) at androidx.lifecycle.LifecycleRegistry.addObserver(SourceFile:202) at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(SourceFile:140) at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke at androidx.compose.ui.platform.AndroidComposeView.onAttachedToWindow(SourceFile:1106) at android.view.View.dispatchAttachedToWindow(View.java:20189) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3512) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3519) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3519) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3519) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3519) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3519) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3519) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3519) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3519) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3519) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3519) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3519) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3519) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3519) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3519) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3519) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2139) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1811) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8127) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1054) at android.view.Choreographer.doCallbacks(Choreographer.java:877) at android.view.Choreographer.doFrame(Choreographer.java:811) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1039) at android.os.Handler.handleCallback(Handler.java:883) at android.os.Handler.dispatchMessage(Handler.java:100) at android.os.Looper.loop(Looper.java:214) at android.app.ActivityThread.main(ActivityThread.java:7631) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:964) could you please have a look

maik-mursall commented 1 year ago

Hi @hossamCheck24, it looks like the wizardSessionKey has not been set.

How do you call the XS2AWizard-Composable?

I'm able to reproduce this crash by calling it with just the ViewModel:

val xs2aWizardViewModel = viewModel<XS2AWizardViewModel>()

XS2AWizard(
    modifier = Modifier.fillMaxSize(),
    xs2aWizardViewModel = xs2aWizardViewModel
)

One fix is to provide the XS2AWizardConfig to the Composable:

val xs2aWizardViewModel = viewModel<XS2AWizardViewModel>()
val xS2AWizardConfig = xS2AWizardConfig.value!! // Or from some other variable

XS2AWizard(
    modifier = Modifier.fillMaxSize(),
    xS2AWizardConfig = xS2AWizardConfig,
    xs2aWizardViewModel = xs2aWizardViewModel
)

Alternatively you can also set the config within the ViewModel:

val xs2aWizardViewModel = viewModel<XS2AWizardViewModel>()
val xS2AWizardConfig = xS2AWizardConfig.value!!

// Set it here or somewhere else, where it is more appropriate.
// Just make sure it's set before you call the XS2AWizard-Composable
xs2aWizardViewModel.config = xS2AWizardConfig

XS2AWizard(
    modifier = Modifier.fillMaxSize(),
    xs2aWizardViewModel = xs2aWizardViewModel
)
hossamCheck24 commented 1 year ago

@maik-mursall actually we don't use XS2AWizard but we use view model and init it like this private val finTechViewModel by activityViewModels<XS2AWizardViewModel>() this how we init fragment private fun createFinTecFragment(config: XS2AWizardConfig) { val xs2aWizardFragment = XS2AWizardFragment(config) childFragmentManager .beginTransaction() .add(R.id.fragmentContainer, xs2aWizardFragment, FIN_TECH_XS2A_WIZARD_FRAGMENT_NAME) .commit()} are we need to set viewModel with configAlso before we call fragment like this finTechViewModel.config = config

maik-mursall commented 1 year ago

@hossamCheck24 The code formatting is a bit weird, but it looks correct... I will be able to further investigate this Issue tomorrow. Does it work, when you set finTechViewModel.config = config?

hossamCheck24 commented 1 year ago

i try it but the problem we couldn't know if problem solved or not because it happen for user and we get reported

maik-mursall commented 1 year ago

So you too cannot reproduce this Issue? I will try around a bit, but cannot promise, that I will find something :/

hossamCheck24 commented 1 year ago

when we investigate more we found that it happen when the fragment recreate so I think it won't save the configuration when recreate the fragment or configration change

maik-mursall commented 1 year ago

Can you provide any more information on that?

On my Test-App the Fragment successfully recreates after the Activity is destroyed. I'm using the "Don't keep Actvities" Developer Feature to test that behaviour.

hossamCheck24 commented 1 year ago

so recreation is happening successfully i try this also I don't know how this problem happens if the crash happens again i will let you know about this problem but i make sure that we didn't send an empty configuration or even empty session key

hossamCheck24 commented 1 year ago

i try with same "Don't keep Activites" and also add "Background process limit "to "no background processes" it happen with me what you need to do is to 1-put the application in the background 2- open another application from background 3- open the SDK again then it will crash with the following

`
The link description rules are missing in the application settings.
2022-11-18 14:21:39.825 32653-32653 AndroidRuntime          de....24.android.kreditplugin.alpha  E  FATAL EXCEPTION: main
                                                                                                    Process: de.check24.android.kreditplugin.alpha, PID: 32653
                                                                                                    java.lang.NullPointerException
                                                                                                        at com.fintecsystems.xs2awizard_networking.NetworkingInstance.constructBody(NetworkingInstance.kt:89)
                                                                                                        at com.fintecsystems.xs2awizard_networking.NetworkingInstance.encodeAndSendMessage(NetworkingInstance.kt:70)
                                                                                                        at com.fintecsystems.xs2awizard.components.XS2AWizardViewModel.submitForm(XS2AWizardViewModel.kt:245)
                                                                                                        at com.fintecsystems.xs2awizard.components.XS2AWizardViewModel.submitForm(XS2AWizardViewModel.kt:225)
                                                                                                        at com.fintecsystems.xs2awizard.components.XS2AWizardViewModel.initForm(XS2AWizardViewModel.kt:130)
                                                                                                        at com.fintecsystems.xs2awizard.components.XS2AWizardViewModel.onStart(XS2AWizardViewModel.kt:110)
                                                                                                        at com.fintecsystems.xs2awizard.XS2AWizardKt$XS2AWizard$2.invoke(XS2AWizard.kt:66)
                                                                                                        at com.fintecsystems.xs2awizard.XS2AWizardKt$XS2AWizard$2.invoke(XS2AWizard.kt:64)
                                                                                                        at androidx.compose.runtime.DisposableEffectImpl.onRemembered(Effects.kt:81)
                                                                                                        at androidx.compose.runtime.CompositionImpl$RememberEventDispatcher.dispatchRememberObservers(Composition.kt:1032)
                                                                                                        at androidx.compose.runtime.CompositionImpl.applyChangesInLocked(Composition.kt:793)
                                                                                                        at androidx.compose.runtime.CompositionImpl.applyChanges(Composition.kt:813)
                                                                                                        at androidx.compose.runtime.Recomposer.composeInitial$runtime_release(Recomposer.kt:827)
                                                                                                        at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:519)
                                                                                                        at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:140)
                                                                                                        at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:131)
                                                                                                        at androidx.compose.ui.platform.AndroidComposeView.setOnViewTreeOwnersAvailable(AndroidComposeView.android.kt:1015)
                                                                                                        at androidx.compose.ui.platform.WrappedComposition.setContent(Wrapper.android.kt:131)
                                                                                                        at androidx.compose.ui.platform.WrappedComposition.onStateChanged(Wrapper.android.kt:182)
                                                                                                        at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:360)
                                                                                                        at androidx.lifecycle.LifecycleRegistry.addObserver(LifecycleRegistry.java:202)
                                                                                                        at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:138)
                                                                                                        at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:131)
                                                                                                        at androidx.compose.ui.platform.AndroidComposeView.onAttachedToWindow(AndroidComposeView.android.kt:1102)
                                                                                                        at android.view.View.dispatchAttachedToWindow(View.java:20479)
                                                                                                        at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3489)
                                                                                                        at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3496)
                                                                                                        at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3496)
                                                                                                        at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3496)
                                                                                                        at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3496)
                                                                                                        at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3496)
                                                                                                        at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3496)
                                                                                                        at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3496)
                                                                                                        at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3496)
                                                                                                        at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3496)
                                                                                                        at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3496)
                                                                                                        at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3496)
                                                                                                        at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3496)
                                                                                                        at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3496)
                                                                                                        at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3496)
                                                                                                        at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3496)
                                                                                                        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2417)
                                                                                                        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1952)
                                                                                                        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8171)
                                                                                                        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:972)
                                                                                                        at android.view.Choreographer.doCallbacks(Choreographer.java:796)
---------------------------- PROCESS ENDED (32653) for package de.check24.android.kreditplugin.alpha ----------------------------
`
maik-mursall commented 1 year ago

Hi @hossamCheck24, I will look into it.

maik-mursall commented 1 year ago

@hossamCheck24, I noticed, that on those low end devices the state for storing the config reference in the Bundle is lost. In those cases it'll be impossible to recreate the Wizard. I will try to build some features to prevent the crash. I keep you updated :)

hossamCheck24 commented 1 year ago

Hi @maik-mursall any update about this issue I know we talked about this issue two days ago but now it happen multiple time not only on small memory device but also for newer device when process I think it killed please take this in your consideration and thanks a lot for your support

maik-mursall commented 1 year ago

Hi @hossamCheck24, the only thing I'll be able to do is to prevent the initialization of the Wizard, e.g. prevent the XS2AWizardViewModel.onStart call. This would still lead the Fragment to exist, resulting in a white screen. Would this be a suitable fix for you?

hossamCheck24 commented 1 year ago

Hi @maik-mursall
we need another solution to this if it white screen it will be not good for the user, we need to inform the user that there are problems inside SDK so we can show them a popup or error message to the customer could you check if config is null or there are some null stuff to send us an event to handle this error Thanks again for your effort

maik-mursall commented 1 year ago

I could do that for sure. I would probably add something like XS2AWizardConfig.onInitializationError, if that's fine for you. Alternatively I could alter onNetworkError to be able to send those kinds of Errors as well. Which of the two would you rather like?

hossamCheck24 commented 1 year ago

thanks, @maik-mursall for the fast replay yes could add another property for this also XS2AWizardConfig.onInitializationError it will be great

maik-mursall commented 1 year ago

@hossamCheck24, I'm really sorry, but I noticed while trying to implement this, that I forgot, that the core Issue is that the config gets lost during recreation. So adding another callback to the config wouldn't work.

I have to think up another solution, do you have an Idea for an situation like that?

matiasServettoC24 commented 1 year ago

Hi @maik-mursall , I work with Hossam. Both of us were checking the current solution. We notice that you are sending the config object in the constructor of the lib fragment: https://github.com/FinTecSystems/xs2a-android/blob/master/xs2awizard/src/main/java/com/fintecsystems/xs2awizard/wrappers/XS2AWizardFragment.kt#L22

This is not a good practice, given that the system will create a new instance given that we reach this scenario.

In case you manage to store the config in the saved instance bundle, then the callbacks will get detached from our code and we will never receive any state. Given the previous reason, it is also not a good solution to have these callbacks define as you did here.

Take a look to the following documentation: https://developer.android.com/guide/fragments/communicate#fragment-result Given that we are adding your fragment as a child fragment of ours, we can easily listen to a result from your side and get rid of the broken-state-fragment.

This anyways hides the architectural problem we have with the current solution. This is a common best practice of creating a fragment with arguments: https://stackoverflow.com/a/9245510 Of course the pointers to functions wont work. But data will be saved and recreated correctly from the arguments & using the fragment-result api to send up messages will cover that part too.

matiasServettoC24 commented 1 year ago

Leaving the technical aspect aside. We did a sync with our product manager. His request is that in case your solution ends up in this missing configuration state, please do not show to the customer a blank screen. It is not a good solution for our customers. You should show an error screen and a Button that triggers an event to us to handle the close of your fragment.

this is not ideal, you need to understand that our customers may be using another apps while they are in our flow to check data. If they switch apps then the process may be kill on the back and forth between check24 app & the others they may use (mail, pdfs, chat, etc).

maik-mursall commented 1 year ago

Hi @matiasServettoC24, thank you for helping with this Issue. You're right, the "Config-Object"-approach makes solving this Issue impossible and in retrospect should not exist.

I will try to rewrite the configuration-flow to use the Bundle and Fragment-Results for Fragments.

But before that, there needs to be a solution for Jetpack Compose as well. I was thinking, because the ViewModel holds the entire business logic and state, the ViewModel could be used for that instead. Do you have any experience on how to create a similar behaviour with ViewModels?

matiasServettoC24 commented 1 year ago

Sadly I have no experience with Jetpack Compose yet :(

maik-mursall commented 1 year ago

Hi @matiasServettoC24, @hossamCheck24, sorry for the delay but I was sick the last few days...

I've opened #10, so you would be able to see how far the progress is. If you'd like to you can checkout the branch and check if the solution would suit your needs :)

As a heads up: Proper documentation is still missing but will be added before I merge the PR.

maik-mursall commented 1 year ago

This will be the flow now:

// Construct and commit the fragment
val xs2aWizard = XS2AWizardFragment(
    sessionKey = "your-session-key",
)

supportFragmentManager.beginTransaction().let {
    it.add(R.id.xs2a_wizard_container, xs2aWizard)
    it.commit()
}

To register to the events do the following:

supportFragmentManager.setXs2aCallbacks(this, this)

// Alternatively
val xs2aCallbacks = object : XS2AWizardEventListener { ... }

supportFragmentManager.setXs2aCallbacks(this, xs2aCallbacks)

If needed call clearXs2aCallbacks of fragment manager on destroy.

hossamCheck24 commented 1 year ago

hi @maik-mursall
Sorry for hearing that and hope you are fine now, i will give try to that fix and let you know
Regards

hossamCheck24 commented 1 year ago

hi @maik-mursall again i try your fix and I found that it crashes due to this issue Caused by: java.io.NotSerializableException: com.fintecsystems.xs2awizard.components.theme.styles.ButtonStyle

also I found that you are still sending data in the contractor of the fragment which will cause a lot of issues

All subclasses of Fragment must include a public no-argument constructor. The framework will often re-instantiate a fragment class when needed, in particular during state restore, and needs to be able to find this constructor to instantiate it. If the no-argument constructor is not available, a runtime exception will occur in some cases during state restore you could check this https://developer.android.com/reference/android/app/Fragment

matiasServettoC24 commented 1 year ago

Additional info. As I shared with you on my first comment, this is the recommended way to send arguments: https://stackoverflow.com/a/9245510

Please never implement ever a Fragment constructor!

maik-mursall commented 1 year ago

Hi @hossamCheck24, @matiasServettoC24, thank you for testing, I will work to find a fix for the exception.

As for your concern regarding the constructor:

All subclasses of Fragment must include a public no-argument constructor.

One empty constructor must exist on a Fragment, which the XS2AWizardFragment has. When you call the XS2AWizardFragment, you call secondary constructor not the primary.

// Empty Primary constructor
class XS2AWizardFragment() : Fragment(), XS2AWizardEventListener {
    // Secondary constructor used for setting bundle args
    constructor(
        sessionKey: String,
        backendURL: String? = null,
        theme: IXS2ATheme? = null,
        language: XS2AWizardLanguage? = null,
        enableScroll: Boolean = true,
        enableBackButton: Boolean = true,
        enableAutomaticRetry: Boolean = true
    ) : this() {
        arguments = Bundle().apply {
            putString(XS2AWizardBundleKeys.sessionKey, sessionKey)
            putString(XS2AWizardBundleKeys.backendURL, backendURL)

            putSerializable(XS2AWizardBundleKeys.theme, theme)
            putSerializable(XS2AWizardBundleKeys.language, language)

            putBoolean(XS2AWizardBundleKeys.enableScroll, enableScroll)
            putBoolean(XS2AWizardBundleKeys.enableBackButton, enableBackButton)
            putBoolean(XS2AWizardBundleKeys.enableAutomaticRetry, enableAutomaticRetry)
        }
    }

This is functionally the exact same as creating a newInstance method, just without the boilerplate:

fun newInstance(
    sessionKey: String,
    backendURL: String? = null,
    theme: IXS2ATheme? = null,
    language: XS2AWizardLanguage? = null,
    enableScroll: Boolean = true,
    enableBackButton: Boolean = true,
    enableAutomaticRetry: Boolean = true
): XS2AWizardFragment {
    val xs2aWizardFragment = XS2AWizardFragment() // This is redundant

    xs2aWizardFragment.arguments = Bundle().apply {
        putString(XS2AWizardBundleKeys.sessionKey, sessionKey)
        putString(XS2AWizardBundleKeys.backendURL, backendURL)

        putSerializable(XS2AWizardBundleKeys.theme, theme)
        putSerializable(XS2AWizardBundleKeys.language, language)

        putBoolean(XS2AWizardBundleKeys.enableScroll, enableScroll)
        putBoolean(XS2AWizardBundleKeys.enableBackButton, enableBackButton)
        putBoolean(XS2AWizardBundleKeys.enableAutomaticRetry, enableAutomaticRetry)
    }

    return xs2aWizardFragment // This is redundant
}

Here is the XS2AWizardFragment source

hossamCheck24 commented 1 year ago

@maik-mursall Thanks a lot for the clarification I know that you pushed some code for this issue 2 day ago, Are you still working on this issue? or I give try what you pushed Thanks

maik-mursall commented 1 year ago

@hossamCheck24, I think you can give it a try again :).

As a heads up: XS2ASupportTheme and IXS2ATheme have been removed in favor of a all-purpose XS2ATheme. This + some other changes makes saving the theme in the bundle possible, which was the cause of the crash.

If you're interested here are the diffs with the detailed changes.

Please let me know if this change works for you :)

maik-mursall commented 1 year ago

Oh and I already noticed a Bug, where some form elements won't take a custom font. But I'm already on it :)

maik-mursall commented 1 year ago

@hossamCheck24 I fixed the font Issue. If everything works out I will then begin writing the docs + migration guide and probably release next week :)

hossamCheck24 commented 1 year ago

hello again @maik-mursall I give a try for this for the SDK now the crash not happen when you return back from back ground process but it crashes when it tries to send event and SDK fragment not available anymore Process: de.check24.android.kreditplugin.alpha, PID: 7124 java.lang.IllegalStateException: Fragment XS2AWizardFragment{577c881} (ce461596-6bb1-4cf7-9c66-d931a4345096) not associated with a fragment manager. at androidx.fragment.app.Fragment.getParentFragmentManager(Fragment.java:1059) at com.fintecsystems.xs2awizard.wrappers.XS2AWizardFragment.onStep(XS2AWizardFragment.kt:122) at com.fintecsystems.xs2awizard.components.XS2AWizardViewModel.parseCallback(XS2AWizardViewModel.kt:550) at com.fintecsystems.xs2awizard.components.XS2AWizardViewModel.onFormReceived(XS2AWizardViewModel.kt:379) at com.fintecsystems.xs2awizard.components.XS2AWizardViewModel.access$onFormReceived(XS2AWizardViewModel.kt:37) at com.fintecsystems.xs2awizard.components.XS2AWizardViewModel$submitForm$1.invoke(XS2AWizardViewModel.kt:296) at com.fintecsystems.xs2awizard.components.XS2AWizardViewModel$submitForm$1.invoke(XS2AWizardViewModel.kt:296) at com.fintecsystems.xs2awizard_networking.NetworkingInstance.encodeAndSendMessage$lambda-0(NetworkingInstance.kt:71) at com.fintecsystems.xs2awizard_networking.NetworkingInstance.$r8$lambda$anHYWY7pjrOorpwbWet4a1oDsRg(Unknown Source:0) at com.fintecsystems.xs2awizard_networking.NetworkingInstance$$ExternalSyntheticLambda0.onResponse(Unknown Source:4) at com.android.volley.toolbox.StringRequest.deliverResponse(StringRequest.java:82) at com.android.volley.toolbox.StringRequest.deliverResponse(StringRequest.java:29) at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:102) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:223) at android.app.ActivityThread.main(ActivityThread.java:7656) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) could you check please

maik-mursall commented 1 year ago

hi @hossamCheck24, should be fixed :)

hossamCheck24 commented 1 year ago

Hello Maix again after i run the new update I got this crash i don't see that you change any thing on compose but it always now crash when I start the SDK with this exception java.lang.NoSuchMethodError: No static method FormText-uqHkpk8(Landroidx/compose/ui/Modifier;Ljava/lang/String;JJLandroidx/compose/ui/text/font/FontWeight;ILandroidx/compose/ui/text/style/TextAlign;Landroidx/compose/runtime/Composer;II)V in class Lcom/fintecsystems/xs2awizard/form/components/shared/FormTextKt; or its super classes (declaration of 'com.fintecsystems.xs2awizard.form.components.shared.FormTextKt' appears in /data/data/de.check24.android.kreditplugin.alpha/code_cache/.overlay/base.apk/classes2.dex) at com.fintecsystems.xs2awizard.form.components.shared.FormTextFieldKt$FormTextField$4.invoke(FormTextField.kt:59) at com.fintecsystems.xs2awizard.form.components.shared.FormTextFieldKt$FormTextField$4.invoke(FormTextField.kt:57)

maik-mursall commented 1 year ago

This is very weird, have you tried to clean the build cache? Android Studio>Build>Clean Project

I'm able to build and run the SDK without any problems.

Maybe try to "Gradle sync" again as well?

hossamCheck24 commented 1 year ago

yes i think i made all this stuff could you please give build to give try with it may be it related to gradle issue when import it as module

maik-mursall commented 1 year ago

I'm not sure if I understand you. What exactly would you like me to do?

hossamCheck24 commented 1 year ago

we need to have build to add it directly to the project with the new version you have to just add it as an implementation , not as a module if you could merge it to develop and provide us with new version it will be nice

hossamCheck24 commented 1 year ago

Hi @maik-mursall when. you manage to merge this issue to the master and get new release for the SDK

maik-mursall commented 1 year ago

Hi @hossamCheck24, I released it under 4.0.0 for you to test. Check within a few hours until it's public on the repository

hossamCheck24 commented 1 year ago

could you check i have a small issue in the style

image
maik-mursall commented 1 year ago

Is your tintColor and onTintColor the same?

hossamCheck24 commented 1 year ago

yes now it solved after i change onTink Color thanks @maik-mursall :D

matiasServettoC24 commented 1 year ago

@maik-mursall How are you?

I have bad news: The version 4.0.0 you provided is not accepted for our QA The crash is not happening but the customer ends up in an infinite loop.

What is going on is:

  1. user selects a login method that requires them to go to another app
  2. the process get killed when our app is on background
  3. the user does the login in the other app
  4. he returns to our app and the sdk shows the login screen again
  5. the user needs repeat the process and is asked to go to the other app again
  6. repeat from step 2

Why is not possible for your sdk to store the proper state? We feel the solution is just avoiding the crash but the result is an invalid flow & does not meet our expectations.

maik-mursall commented 1 year ago

Hi @matiasServettoC24, I'm good, hope you too.

This seems really odd, at least in the test environment this Issue doesn't occur for me. Which Bank/Transport was your customer using?

maik-mursall commented 1 year ago

@hossamCheck24

@maik-mursall Hope, you are fine please check the attached video -old-url- as you can see every time in the background when the process is killed the SDK starts initialize from the beginning again you could try to by going to developer option and select Background process limit and then select No background processes also don't keep activity then you could reproduce it

I've seen the video and I will investigate it further. But please be careful in future, since your password was visible through the keyboard inputs. That's why I deleted the original comment.

maik-mursall commented 1 year ago

@matiasServettoC24, @hossamCheck24, I tried to replicate the Issue the same way you did in the video.

With multiple different banks everything worked as expected without getting stuck in a loop like you describe. One of the Banks was the Sparkasse as well, albeit a different one.

Like always I disabled background processes and activities are being destroyed instantly.

Can you replicate this Issue with other banks as well? Or was this the only one? Maybe it was a issue with the backend and not with the sdk.

matiasServettoC24 commented 1 year ago

Hi @maik-mursall, I will sync with the QAs to find out if the problem happens also on other banks. Thanks for checking.

matiasServettoC24 commented 1 year ago

Hi @maik-mursall Sorry the late reply: hossam is on vacation since our last conversation & I was sick most of last week. Last week I was working on a demo app to share with you & thanks to it I found the line of code that was resetting the flow.

I will be providing our QA a new build & I will let you know if the problems are fixed.

In case it succeeds, sadly, we wont be able to do any release unless IDnow library removes/updates the dependency to this lib

maik-mursall commented 1 year ago

Hi @matiasServettoC24, I hope you had a great start into the new year :)

Does everything work now?