playgameservices / play-games-plugin-for-unity

Google Play Games plugin for Unity
Other
3.43k stars 954 forks source link

Problem authenticating when Google Play Games is not installed (or is not signed in) #3104

Open ChibiPhoenixGithub opened 2 years ago

ChibiPhoenixGithub commented 2 years ago

Hello,

I am having a problem where the Authenticate method 'hangs' when the sign in is called if the Google Play Games (GPG) app is not installed on the device. It takes a very long time for the method to time-out (if it even does). This also occurs if trying to authenticate when GPG is installed, but was never signed in.

I am using an older packadge 0.10.12, but no mention of this issue was made in the changelog. Testing the "happy path" (GPG is installed and signed in) works as expected.

I am considering implementing a time-out, to force quit the current attempt and if it takes to long, continue without authenticating. However, I did not find a method to force-cancel the authentication.

ozdemir08 commented 2 years ago

Could you capture a bug report and share with us? If you are using a standard Android device, meaning if the device has Play Services automatically installed, a sign-in attempt should prompt the installer when Play Games is not installed on the device.

ChibiPhoenixGithub commented 2 years ago

I mostly got these reports from people using a lower-end device. I made my login a little more robust by falling back to the 'hard' login (requiring UI consent) incase the silent sign-in fails. This seems to have resolved the issue.

It seems the silent sign-in (even though it mentions it should show UI at least once) can sometimes fail to actually show the install UI. I did manage to recreate the issue a while back using AVD (using the Pixel3 as device). After a fresh install, starting my app (without Play Games installed) and at the point of the silent sign-in, it sometimes failed to show the install, resulting in an endless startup screen... However, since I added the fallback it seems to work reliably, even when using AVD.

ozdemir08 commented 2 years ago

Could you share your authentication code? The code below will prompt ui sign-in only once. But

PlayGamesPlatform.Instance.Authenticate(SignInInteractivity.CanPromptOnce, (result) =>{
        // handle results
    });

If you are doing only silent sign-in by using this method, then users will not see any ui.

ChibiPhoenixGithub commented 2 years ago

I sign in during initialization (first time loading) like so (I also have a button in the Menu for users to sign-in / -out, but the initialization one was not doing what I had expected.

    public void Initialize(string cloudSaveName, string cloudProfileName)
    {
        if (IsInitialized == false)
        {
            IsInitialized = true;            
            this.cloudSaveName = cloudSaveName;
            this.cloudProfileName = cloudProfileName;

            SubscribeToEvents();
            InitializePlayGamesPlatform(BuildPlayGamesClientConfiguration());

            try
            {
                SilentSignIn(SignInCallback);
            }
            catch (Exception ex)
            {
                GuiWriter.Instance.Write(ex.Message, Color.red, false, 5f);
            }
        }
    }

I used to only use the silent sign-in method you provided, with some additional logic. However, since I changed it to:

    private void SilentSignIn(Action<SignInStatus> callback)
    {
        if (Social.localUser.authenticated == false)
        {
            PlayGamesPlatform.Instance.Authenticate(SignInInteractivity.CanPromptOnce, async (SignInStatus result) =>
            {
                if (result != SignInStatus.Success)
                {
                    // If silent sign-in fails, check if the user has previously declined to sign in.
                    bool isSignInDeclined = false;
                    if (PlayerPrefs.HasKey(signInStatusKey))
                    {
                        isSignInDeclined = Convert.ToBoolean(PlayerPrefs.GetInt(signInStatusKey));
                    }

                    // If the user hasn’t previously declined to sign in, check the internet connection and prompt interactive sign-in if internet is available
                    if (isSignInDeclined == false &&
                        await IsConnectedToTheInternet())
                    {
                        PlayGamesPlatform.Instance.Authenticate(SignInInteractivity.CanPromptAlways, (SignInStatus result) =>
                        {                        
                            // If the interactive sign-in is cancelled by the user, remember this as a 'decline' for any next silent sign-in attempts.
                            if (result == SignInStatus.Canceled)
                            {
                                PlayerPrefs.SetInt(signInStatusKey, 1);
                                PlayerPrefs.Save();
                            }

                            callback?.Invoke(result);
                        });
                    }
                    else
                    {
                        callback?.Invoke(SignInStatus.Canceled);
                    }
                }
                else
                {
                    callback?.Invoke(result);
                }
            });
        }
    }

I have not had any issues.

However, I understood the summary of SignInInteractivity.CanPromptOnce (English is not my native language) as, first try to sign in quietly, if that does not work show the user a prompt. Though the code you reference describes exactly what is happening ;-)