Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
BrooklynDipi opened this issue Jan 3, 2024 · 6 comments

Comments

@BrooklynDipi
Copy link

[REQUIRED] Please fill in the following fields:

  • Unity editor version: 2022.3.11f1
  • Firebase Unity SDK version: 11.6.0
  • Source you installed the SDK: tgz via UnityPackageManager
  • Problematic Firebase Component: RemoteConfig
  • Other Firebase Components in use: Auth, Crashlytics, Analytics, and External Dependency Manager
  • Additional SDKs you are using: Facebook
  • Platform you are using the Unity editor on: Windows 11, MacOS
  • Platform you are targeting: iOS, Android
  • Scripting Runtime: IL2CPP
  • Pre-built SDK from the website or open-source from this repo: Google APIs for Unity Archive

[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)

  • Seems to be roughly 30%. I have tested this by simply closing and reopening the app on an iOS device to see if I get the intended results.

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

  • Fetch values from remote config with "Link Frameworks Statically" set to false.

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
Copy link

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
Copy link
Author

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
Copy link

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
Copy link

tallior commented Mar 31, 2024

Any updates or workarounds for this issue ?

@a-maurice
Copy link
Collaborator

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: firebase/quickstart-unity#1198 (comment))

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
Copy link

tallior commented Apr 12, 2024

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants