RodrigoSMarques / flutter_branch_sdk

Flutter Plugin for create deep link using Branch Metrics SDK. This plugin provides a cross-platform (iOS, Android, Web).
https://branch.io
MIT License
101 stars 91 forks source link

Completion of `await FlutterBranchSdk.init()` doesn't mean native iOS plugin is ready? #309

Closed MrLightful closed 6 months ago

MrLightful commented 7 months ago

Describe the bug Completion of await FlutterBranchSdk.init() doesn't necessarily mean native iOS plugin is fully initialized? Especially during the first launch.

In my app:

Sometimes, especially during the first launch, the app won't catch links (not deferred, but ones I try to open with app installed). It opens the app, but not the link.

And I noticed that during app launch in XCode's console it produced this log: [BranchSDK][Debug][Branch initSafetyCheck] Branch avoided an error by preemptively initializing.

Googling it, I discovered multiple issues BranchMetrics/ios-branch-deep-linking-attribution#936 and RodrigoSMarques/flutter_branch_sdk#168.

At first, I thought that somehow I was throwing some events too early, before init'ing. But eventually got assured that nothing to branch happens before await FlutterBranchSdk.init() is completed. Trying out some recommendations, I set extra hardcoded delay after await FlutterBranchSdk.init(), which seems to help.

So, I digged into init() through platform channels, and discovered that iOS's channel method does not wait for banch's native sdk to complete session initialization. It returns result prematurely, from what I understand.

So it triggers branch's native sdk initSession on line 331 with async completion handler, but result is returned prematurely on lines 331-332, without completion of the initSession.

RodrigoSMarques commented 7 months ago

Hi @romatallinn

the purpose of the FlutterBranchSdk.init() method is to initialize the SDK methods and not wait for its result.

If during code execution (setupBranch) the SDK initSessionreturns a result and there is not yet a listener for the result, the value will be stored (line 294) and sent as soon as the listener is available (line 105).

There is an issue in which it was mentioned that during the first launch, the SDK may take longer to find the installation data. Some suggest adding a delay to get around the problem.

In the example application, I identified this condition at times.

If you look here you will find a commented code, where I add a delay of 3 seconds. This worked in my tests.

I never wanted to "official" this as a solution, as it is not correct, but in my tests it worked.

RodrigoSMarques commented 7 months ago

Hi @romatallinn

The init method was implemented in version 7 to allow configuration of the test key through code, but this caused some problems for the plugin.

I'm already working on a new version that should resolve these issues.

MrLightful commented 6 months ago

@RodrigoSMarques thanks a lot for the release.

So, just to confirm, await FlutterBranchSdk.init() now implies that native plugin is ready? And it doesn't need to be delayed anymore?

RodrigoSMarques commented 6 months ago

Hi @romatallinn

In version 8.0.0, the plugin has the same behavior as versions prior to 7.x.x

The native SDK is initialized even before Dart/Flutter code is executed. Initialization is not delayed.

The FlutterBranchSdk.init() function only performs additional configurations after the Native SDK is initialized.

For this reason, it is no longer possible to configure the test key via code, so as not to delay initialization.

Deferring startup was causing data loss by not recognizing link clicks on application startup.

shubhrajyotidey305 commented 5 months ago

I am facing the same issue again. I am using the flutter branch sdk that is 8.0.2. The native plugin prints all the datas with the deeplink but the flutter branch listener returns {+clicked_branch_link: false, +is_first_session: false}