firebase / firebase-unity-sdk

The Firebase SDK for Unity
http://firebase.google.com
Apache License 2.0
229 stars 38 forks source link

[Bug] Remote config fetch seems to hang forever on iOS on random sessions #920

Open BrooklynDipi opened 10 months ago

BrooklynDipi commented 10 months ago

[REQUIRED] Please fill in the following fields:

[REQUIRED] Please describe the issue here:

(Please list the full steps to reproduce the issue. Include device logs, Unity logs, and stack traces if available.)

When using RemoteConfig on iOS devices, the function, FetchAsync(), has a roughly 30% chance of failing. This also occurs with FetchAndActivateAsync(). I use this tool to version check the application on start-up. If the application is out of date, it stops the user from progressing. Sometimes this function does not complete so the values needed to evaluate your continuation are not accurate. This issue does not occur on Android.

I found a similar issue to this that occurred back in 2022 here on the quickstart bug page. They seemed to have solved it by setting the External Dependency Manager's iOS resolver settings to "Link Frameworks Statically" in addition to an SDK update. I suspect this is the issue that is possibly occurring for me currently. That said, I am unable to set "Link Frameworks Statically" to true as it breaks FacebookSDK.

The reason I suspect this is a similar issue is because of the logs I receive in XCode when running on iOS. I have debug logs that print the fetched version number as well as the current application version number. In this 30% chance window, I see the call stack for FetchAsync() begin but it does not produce any results, and the string that is set by its fetched values always results in an empty string.

I am hoping though that perhaps I am making a silly mistake and that this is not the reason. I have tried many different approaches to using the RemoteConfig API that have all resulted in a lack of consistency on iOS only. Android has been functional every time. I generally initialize Firebase in Awake() in our Auth script and I have previously hooked in the FetchAsync() function to that script, where its called after CheckAndFixDependenciesAsync(). No difference was made.

I made sure to review and try approaches from the documentation here.

Steps to reproduce:

What's the issue repro rate? (eg 100%, 1/5 etc)

What happened? How can we make the problem occur? This could be a description, log/console output, etc.

Relevant Code:

using DG.Tweening;
using Firebase;
using Firebase.Extensions;
using Firebase.RemoteConfig;
using System;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;

public class RemoteConfigVersionControl : MonoBehaviour
{
    public static RemoteConfigVersionControl Instance;

    public GameObject UpdateGraphic;

    [HideInInspector]
    public bool isVersionCurrent = false;

    [HideInInspector]
    public string thisVersionNumber;

    [HideInInspector]
    public string currentVersionNumbers;

    private void Awake()
    {
        Instance = this;

        thisVersionNumber = Application.version;

        currentVersionNumbers = "0";
    }

    private async void Start()
    {
        await FirebaseApp.CheckAndFixDependenciesAsync();

        await FetchDataAsync();
    }

    private Task FetchDataAsync()
    {
        Debug.Log("Fetching data...");

        Task fetchTask = FirebaseRemoteConfig.DefaultInstance.FetchAsync(TimeSpan.Zero);

        return fetchTask.ContinueWithOnMainThread(FetchComplete);
    }

    private void FetchComplete(Task fetchTask)
    {
        if (!fetchTask.IsCompleted)
        {
            Debug.LogError("Retrieval hasn't finished.");
            return;
        }

        var remoteConfig = FirebaseRemoteConfig.DefaultInstance;

        var info = remoteConfig.Info;

        if (info.LastFetchStatus != LastFetchStatus.Success)
        {
            Debug.LogError($"{nameof(FetchComplete)} was unsuccessful\n{nameof(info.LastFetchStatus)}: {info.LastFetchStatus}");
            return;
        }

        // Fetch successful. Parameter values must be activated to use.
        remoteConfig.ActivateAsync()
          .ContinueWithOnMainThread(
            task =>
            {
                Debug.Log($"Remote data loaded and ready for use. Last fetch time {info.FetchTime}.");

                currentVersionNumbers = FirebaseRemoteConfig.DefaultInstance.GetValue("VersionNumber").StringValue;

                VersionComparison();
            });
    }

    public void VersionComparison()
    {
        Debug.Log("THIS VERSION NUMBER: " + thisVersionNumber);

        Debug.Log("CURRENT VERSION NUMBER: " + currentVersionNumbers);

        if (currentVersionNumbers == "0")
        {
            isVersionCurrent = true;
        }
        else if (currentVersionNumbers.Contains(thisVersionNumber))
        {
            isVersionCurrent = true;
        }
        else
        {
            isVersionCurrent = false;
        }
    }

    public void EnableUpdateGraphic()
    {
        if (UpdateGraphic != null)
        {
            var UpdateGraphicImage = UpdateGraphic.GetComponent<Image>();

            UpdateGraphic.SetActive(true);

            UpdateGraphicImage.DOFade(1, .5f);
        }
    }
}

Call stack for unfinished function

Fetching data...
RemoteConfigVersionControl:FetchDataAsync()
<Start>d__6:MoveNext()
System.Runtime.CompilerServices.AsyncVoidMethodBuilder:Start(TStateMachine&)
RemoteConfigVersionControl:Start()

Call stack for finished function

Fetching data...
RemoteConfigVersionControl:FetchDataAsync()
<Start>d__6:MoveNext()
System.Threading.ExecutionContext:RunInternal(ExecutionContext, ContextCallback, Object, Boolean)
System.Runtime.CompilerServices.MoveNextRunner:Run()
UnityEngine.WorkRequest:Invoke()
UnityEngine.UnitySynchronizationContext:Exec()

Remote data loaded and ready for use. Last fetch time 1/3/2024 9:03:55 PM.
<>c__DisplayClass8_0:<FetchComplete>b__0(Task`1)
Firebase.Extensions.<>c__DisplayClass4_1`1:<ContinueWithOnMainThread>b__1()
Firebase.<>c__DisplayClass5_0`1:<RunAsync>b__0()
Firebase.ExceptionAggregator:Wrap(Action)
Firebase.Dispatcher:PollJobs()
Firebase.Platform.FirebaseHandler:Update()

THIS VERSION NUMBER: 1.03.408
RemoteConfigVersionControl:VersionComparison()
<>c__DisplayClass8_0:<FetchComplete>b__0(Task`1)
Firebase.Extensions.<>c__DisplayClass4_1`1:<ContinueWithOnMainThread>b__1()
Firebase.<>c__DisplayClass5_0`1:<RunAsync>b__0()
Firebase.ExceptionAggregator:Wrap(Action)
Firebase.Dispatcher:PollJobs()
Firebase.Platform.FirebaseHandler:Update()

CURRENT VERSION NUMBER: 1.03.395
1.03.406

RemoteConfigVersionControl:VersionComparison()
<>c__DisplayClass8_0:<FetchComplete>b__0(Task`1)
Firebase.Extensions.<>c__DisplayClass4_1`1:<ContinueWithOnMainThread>b__1()
Firebase.<>c__DisplayClass5_0`1:<RunAsync>b__0()
Firebase.ExceptionAggregator:Wrap(Action)
Firebase.Dispatcher:PollJobs()
Firebase.Platform.FirebaseHandler:Update()

image

georgemarkosian commented 7 months ago

Hello there, we experience this one as well. We have several users that reported it and presumably many more that didn't.

We use Firebase 11.6.0 and Unity 2022.3.20. One of the reporters has Galaxy S23+ and wrote that the issue is reproduced 100% of the time. Reinstalling and device restarting didn't help.

BrooklynDipi commented 7 months ago

Hello there, we experience this one as well. We have several users that reported it and presumably many more that didn't.

We use Firebase 11.6.0 and Unity 2022.3.20. One of the reporters has Galaxy S23+ and wrote that the issue is reproduced 100% of the time. Reinstalling and device restarting didn't help.

I have the 23 Ultra and I was getting it randomly so that's very odd. Very frustrating. We were running ads on our app and getting many comments complaining about the same issue.

Ultimately, our backend dev created his own solution for me to use. Hopefully this gets fixed tho as I'd love to use it for other features. Don't have much help otherwise but you are seen!

georgemarkosian commented 7 months ago

Hello there, we experience this one as well. We have several users that reported it and presumably many more that didn't. We use Firebase 11.6.0 and Unity 2022.3.20. One of the reporters has Galaxy S23+ and wrote that the issue is reproduced 100% of the time. Reinstalling and device restarting didn't help.

I have the 23 Ultra and I was getting it randomly so that's very odd. Very frustrating. We were running ads on our app and getting many comments complaining about the same issue.

Ultimately, our backend dev created his own solution for me to use. Hopefully this gets fixed tho as I'd love to use it for other features. Don't have much help otherwise but you are seen!

Thank you for your response. Our app relies on the remote config at the very start so the issue is critical. While only a fraction of our users are affected, some of them are subscribers who could unsubscribe and leave.

We'll try to find a workaround but we hope this will be addressed soon.

tallior commented 7 months ago

Any updates or workarounds for this issue ?

a-maurice commented 7 months ago

My understanding of the underlying issue is that when the dependencies are being linked dynamically, there is a danger that it is getting two separate versions of Firebase/Core, and then using them for different calls, which causes the issue (as described here: https://github.com/firebase/quickstart-unity/issues/1198#issuecomment-1040690857)

The workaround that we've recommended is to use static linking, but that seems to not be possible with some other SDKs, like the Facebook one. Unfortunately there isn't a ton we can do at our level, as it seems to mostly be an issue with how Cocoapods is linking in the different libraries.

Some things that you can try to do, using the Swift Package Manager instead of Cocoapods. We haven't done it ourselves, but theoretically you could get the Firebase (and/or Facebook) frameworks through SPM, which might help. From some searching, there are also some Cocoapod plugins that allow you to specify different linking patterns per pod, such as https://github.com/microsoft/cocoapods-pod-linkage, which could help.

tallior commented 7 months ago

Thanks for the reply @a-maurice I will give that a look, but i am not sure how this solution would work in the context of a Unity game (and not a standard, native iOS app).

Is there any way to remove the usage of pods altogether (for Firebase / Facebook) and include it directly in our project somehow?

abhishekbodhekar commented 1 month ago

any update on this?