1
votes

I have a Unity app that includes a button to sign into Google Plus. In the iOS version of the app I've had to override the default behaviour of the Google Plus SDK to prevent it switching to Safari to sign in and to use a WebView instead. This is due to Apple's policy of rejecting apps that sign into Google Plus via Safari.

That's all fine and the sign-in process works via the WebView. I've added a "Cancel" button that overlays the WebView so that users can decide not to sign in and return to the app. The code that handles the cancel button is:

- (IBAction)handleCancelClick:(id)sender {
    // Cancel the sign-in process
    [[GPGManager sharedInstance] signOut];
    //Reactivate the sign-in button
    UnitySendMessage("Persistent Services", "cancelSignIn", "");
    // Hide the webview
    [_unityViewController dismissViewControllerAnimated:YES completion:nil];
}

The problem is that subsequent attempts to sign in after using the cancel button fail. I see the following error when debugging in XCode:

2015-04-29 21:33:05.328 [Core] (Error) -[GPGManager finishedWithAuth:error:]:[main]
FAILED LOGGING INTO GOOGLE PLUS GAMES Error Domain=com.google.GooglePlusPlatform
Code=-1 "Mismatched authentication" UserInfo=0x1c163870 
{NSLocalizedDescription=Mismatched authentication}

As I say, this only happens after the cancel button has been used. If the sign-in process goes through in a single flow, it works.

The Unity code that's called when the sign-in button is pressed is:

public void logIn () {
        Debug.Log ("Attempting to log in");
        signingIn = true;
        Social.localUser.Authenticate ((bool success) =>
        {
            if (success) {
                ...
            } else {
                Debug.Log ("Failed to Log in to Google Play Services");
            }
            signingIn = false;

        });
}

I'm assuming that the first time Social.localUser.Authenticate() is called, some state is set up that isn't overwritten on subsequent calls. When the sign-in process finishes it then checks the callback auth code against what was set on the first call to Authenticate() and they don't match. But I may be way off the mark.

Can you suggest a way of completely resetting the sign-in process when cancelling or of otherwise resolving this problem?

1

1 Answers

0
votes

I got around the problem by making sure Social.localuser.Authenticate() isn't called a second time. Subsequent presses of the 'sign-in' button just cause the WebView to be redisplayed.

To achieve this, I set a flag in the Unity method called from Objective-C code when the 'Cancel' button is pressed.

#if UNITY_IOS
/**
 * Currently only called from Native iOS code.
 */
public void cancelSignInFromIos() {
    hasCancelledInIos = true;
}
#endif

I then wrap the sign-in code in a conditional statement that checks the value of this flag. If the 'Cancel' button has been pressed, I send a message back to native code to instruct it to display the WebView.

if (!hasCancelledInIos)
    Social.localUser.Authenticate ((bool success) =>
    {
        ...
    }
} else {
    #if UNITY_IOS
    hasCancelledInIos = false;
    fromUnityshowWebView ();
    #endif
}

The native method is defined in Unity-side code like this:

#if UNITY_IOS
System.Runtime.InteropServices.DllImport("__Internal")]
extern static public void fromUnityshowWebView();
#endif

And is implemented in native code like this:

extern "C" {
    void fromUnityshowWebView() {
        [[NSNotificationCenter defaultCenter] postNotificationName:ApplicationOpenGoogleAuthNotification object:@"blank"];
    }
}

The notification fired here is handled by a method that displays the WebView overlay e.g.

- (void) showWebView
{
    [unityViewController presentViewController:self.webViewController animated:YES completion:nil];
}

Long-winded, but it works.