robovm / robovm-robopods

63 stars 86 forks source link

Signing in using the GPGS roboPods does not use a webview #82

Open ebbybeh opened 8 years ago

ebbybeh commented 8 years ago

I have managed to successfully sign in using the roboPods but have not been able to get the sign in to happen via a webview. Instead the app redirects to the Google+ app which has resulted in an instant rejection by Apple in the past. I have followed this: https://developers.google.com/games/services/ios/quickstart and have gone through the robopod sample (though it was not as helpful as my project is a LibGDX project and following the sample led to a host of errors).

I am honestly stumped. Here is what I have:

In the main build file under ios, I have added:

compile "org.robovm:robopods-google-play-games-ios:1.12.0"
compile "org.robovm:robopods-google-signin-ios:1.12.0"

In the main launcher file I have:

@Override
public void didBecomeActive(UIApplication application) {
    if(GameConstants.LOG_ENABLED)Foundation.log("***Did become active");
    GIDSignIn.getSharedInstance().setUiDelegate(this);
    super.didBecomeActive(application);
}

and

@Override
public void willDispatch(GIDSignIn signIn, NSError error) { 
    if(GameConstants.LOG_ENABLED)Foundation.log(***will Dispatch***Error: " + error);   
}

@Override
public void presentViewController(GIDSignIn signIn, UIViewController viewController) {
    if(GameConstants.LOG_ENABLED)Foundation.log("***present View Controller");
}

@Override
public void dismissViewController(GIDSignIn signIn, UIViewController viewController) {
    if(GameConstants.LOG_ENABLED)Foundation.log("***dismiss View Controller");
}

(Note: none of those implemented methods from GIDSignInUIDelegate gets called when I sign in) as my main class (IOSLauncher) implements GIDSignInUIDelegate.

My info file has:

 <key>CFBundleURLTypes</key>   
 <array>
   <dict>
       <key>CFBundleTypeRole</key>
       <string>Editor</string>
       <key>CFBundleURLName</key>
       <string>${app.id}</string>
       <key>CFBundleURLSchemes</key>
       <array>
           <string>${app.id}</string>
       </array>
   </dict>   
   <dict>
       <key>CFBundleURLSchemes</key>
       <array>
           <string>com.googleusercontent.apps.1111111111111111-xxxxxxxxxxxxxxxxxxxxxx</string>
       </array>
   </dict>    

Finally, to sign in I call:

GPGManager.getSharedInstance().setStatusDelegate(GooglePlayDelegate);
GPGManager.getSharedInstance().signIn(clientId, false);

Again, I can sign in successfully, but without the webview, it is pointless.

alek-sandr commented 8 years ago

I faced with same problem. So after some experiments i found working solution (maybe it is incorrect, but i trying to make it working couple days). So here is some excerpts from my game. IOSLauncher.java

package tk.aleksdev.tentwelve.ios;

import com.badlogic.gdx.backends.iosrobovm.IOSApplication;
import com.badlogic.gdx.backends.iosrobovm.IOSApplicationConfiguration;
import org.robovm.apple.foundation.*;
import org.robovm.apple.uikit.*;
import org.robovm.pods.google.GGLContext;
import org.robovm.pods.google.games.GPGManager;
import org.robovm.pods.google.signin.GIDSignIn;
import tk.aleksdev.tentwelve.Config;
import tk.aleksdev.tentwelve.TenTwelve;

public class IOSLauncher extends IOSApplication.Delegate {

    @Override
    protected IOSApplication createApplication() {
        IOSApplicationConfiguration config = new IOSApplicationConfiguration();
        config.orientationPortrait = true;
        config.orientationLandscape = false;
        config.useAccelerometer = false;
        config.useCompass = false;
        config.preventScreenDimming = false;

        return new IOSApplication(new TenTwelve(new IOSGameServices()), config);
    }

    public static void main(String[] argv) {
        NSAutoreleasePool pool = new NSAutoreleasePool();
        UIApplication.main(argv, null, IOSLauncher.class);
        pool.close();
    }

    @Override
    public boolean didFinishLaunching(UIApplication application, UIApplicationLaunchOptions launchOptions) {
        super.didFinishLaunching(application, launchOptions);
        Foundation.log("IOSLauncher didFinishLaunching()");
        try {
            GGLContext.getSharedInstance().configure();
            GIDSignIn.getSharedInstance().setAllowsSignInWithWebView(true);
            GPGManager.getSharedInstance().signIn(IOSGameServices.CLIENT_ID, true);
        } catch (NSErrorException e) {
            Foundation.log("Error configuring the Google context: " + e);
        }
        return true;
    }
}

IOSGameServices.java

package tk.aleksdev.tentwelve.ios;

import com.badlogic.gdx.backends.iosrobovm.IOSPreferences;
import org.robovm.apple.foundation.*;
import org.robovm.apple.uikit.UIApplication;
import org.robovm.apple.uikit.UIViewController;
import org.robovm.pods.google.games.*;
import org.robovm.pods.google.signin.*;
import tk.aleksdev.tentwelve.util.GameServices;

public class IOSGameServices implements GameServices {
    public static final String CLIENT_ID = "xxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com";

    public IOSGameServices() {
        GPGManager.getSharedInstance().setStatusDelegate(new GPGStatusDelegateAdapter() {
            @Override
            public void didFinishGamesSignIn(NSError error) {
                Foundation.log("didFinishGamesSignIn(" + error + ")");
            }

            @Override
            public void didFinishGamesSignOut(NSError error) {
                Foundation.log("didFinishGamesSignOut(" + error + ")");
            }

            @Override
            public void didFinishGoogleAuth(NSError error) {
                Foundation.log("didFinishGoogleAuth(" + error + ")");
            }

            @Override
            public boolean shouldReauthenticate(NSError error) {
                Foundation.log("shouldReauthenticate(" + error + ")");
                return false;
            }

            @Override
            public void willReauthenticate(NSError error) {
                Foundation.log("willReauthenticate(" + error + ")");
            }

            @Override
            public void didDisconnect(NSError error) {
                Foundation.log("didDisconnect(" + error + ")");
            }
        });

        GIDSignIn.getSharedInstance().setUiDelegate(new GIDSignInUIDelegateAdapter() {
            private UIViewController libgdxViewController;

            @Override
            public void willDispatch(GIDSignIn signIn, NSError error) {
                Foundation.log("willDispatch()");
            }

            @Override
            public void presentViewController(GIDSignIn signIn, UIViewController viewController) {
                Foundation.log("presentViewController()");
                libgdxViewController = UIApplication.getSharedApplication().getKeyWindow().getRootViewController();
                UIApplication.getSharedApplication().getKeyWindow().setRootViewController(viewController);
            }

            @Override
            public void dismissViewController(GIDSignIn signIn, UIViewController viewController) {
                Foundation.log("dismissViewController()");
                UIApplication.getSharedApplication().getKeyWindow().setRootViewController(libgdxViewController);
            }
        });
    }

    @Override
    public void signIn() {
        Foundation.log("signIn()");
        GPGManager.getSharedInstance().signIn(CLIENT_ID, false);
    }

    @Override
    public void signOut() {
        Foundation.log("signOut()");
        GPGManager.getSharedInstance().signOut();
    }

    @Override
    public void showScores() {
        if (isSignedIn()) {
            GPGLauncherController.getSharedInstance().presentLeaderboardList();
        } else {
            signIn();
        }
    }

    @Override
    public void showAchievements() {
        if (isSignedIn()) {
            GPGLauncherController.getSharedInstance().presentAchievementList();
        } else {
            signIn();
        }
    }

    @Override
    public boolean isSignedIn() {
        return GPGManager.getSharedInstance().isSignedIn();
    }
}

I hope it help.

ebbybeh commented 8 years ago

Thanks for the help, but your suggestions did not work. The problem seems to be that :willDispatch, presentViewController, and dismissViewController are not being called.

One thing I did switch was the following in the openUrl method:

@Override
public boolean openURL(UIApplication application, NSURL url, String sourceApplication, NSPropertyList annotation) {

//        return GPPURLHandler.handleURL(url, sourceApplication, annotation);
      return GIDSignIn.getSharedInstance().handleURL(url, sourceApplication, annotation);
 }

I stopped using the GPPURLHandler since the GPGManager delegate was not getting called when using it.

alek-sandr commented 8 years ago

The code i posted above must work, i copied it from working project. And it works without overriging openUrl(). Here is excerpt from my info.plist.xml

<key>CFBundleURLTypes</key>
    <array>
        <dict>
            <key>CFBundleTypeRole</key>
            <string>Editor</string>
            <key>CFBundleURLName</key>
            <string>tk.aleksdev.tentwelve.ios</string> <------ package name
            <key>CFBundleURLSchemes</key>
            <array>
                <string>tk.aleksdev.tentwelve.ios</string> <------ package name
            </array>
        </dict>
        <dict>
            <key>CFBundleTypeRole</key>
            <string>Editor</string>
            <key>CFBundleURLName</key>
            <string>com.googleusercontent.apps.xxxxxxxxx-xxxxxxxxxxxxxxxxxx</string> <----  OAuth2 client id from GPG console
            <key>CFBundleURLSchemes</key>
            <array>
                <string>com.googleusercontent.apps.xxxxxxxxx-xxxxxxxxxxxxxxxxxx</string>
            </array>
        </dict>
    </array>

Also you should have file GoogleService-Info.plist generated by https://developers.google.com/mobile/add%3Fplatform%3Dios in resources folder.

ebbybeh commented 8 years ago

Thanks a bunch for your help! Changing the location of where I set the delegates seems to have helped.

knepe commented 8 years ago

@ebbybeh Where do you set your delegates now? I have the same issue as you had, no webview, only Safari. Can you post some of your code please?

Also, could someone share how "frameworks" section should look like in the robovm.xml file?

ebbybeh commented 8 years ago

Take a look at the robopod samples to see how the robovm.xml file needs to be.

This is how I sign in:

    GIDSignIn.getSharedInstance().setAllowsSignInWithWebView(true);

    GIDSignIn.getSharedInstance().setUiDelegate(new GIDSignInUIDelegateAdapter() {
        private UIViewController libgdxViewController;

        @Override
        public void willDispatch(GIDSignIn signIn, NSError error) {
            Foundation.log("***willDispatch()");
        }

        @Override
        public void presentViewController(GIDSignIn signIn, UIViewController viewController) {
            Foundation.log("***presentViewController()");
            libgdxViewController = UIApplication.getSharedApplication().getKeyWindow().getRootViewController();
            UIApplication.getSharedApplication().getKeyWindow().setRootViewController(viewController);
        }

        @Override
        public void dismissViewController(GIDSignIn signIn, UIViewController viewController) {
            Foundation.log("***dismissViewController()");
            viewController.dismissViewController(true, null);
            UIApplication.getSharedApplication().getKeyWindow().setRootViewController(libgdxViewController);
        }
    });

    GPGManager.getSharedInstance().setStatusDelegate(pDelegate);
    GPGManager.getSharedInstance().signIn(clientId, false);

and in openURL I return:

GIDSignIn.getSharedInstance().handleURL(url, sourceApplication, annotation)
alek-sandr commented 8 years ago

I changed code of GIDSignInUIDelegateAdapter to next

GIDSignIn.getSharedInstance().setUiDelegate(new GIDSignInUIDelegateAdapter() {

            @Override
            public void willDispatch(GIDSignIn signIn, NSError error) {
                Foundation.log("willDispatch()");
            }

            @Override
            public void presentViewController(GIDSignIn signIn, UIViewController viewController) {
                Foundation.log("presentViewController()");
                UIApplication.getSharedApplication().getKeyWindow().getRootViewController()
                        .presentViewController(viewController, true, null);
            }

            @Override
            public void dismissViewController(GIDSignIn signIn, UIViewController viewController) {
                Foundation.log("dismissViewController()");
                viewController.dismissViewController(true, null);
            }
        });

Now login form appears with sliding animation like other GPG views.

ldthai commented 8 years ago

working with double line signIn: (but very slow) GPGManager.getSharedInstance().signIn(clientId, false); GPGManager.getSharedInstance().signIn(clientId, false);

single not working: GPGManager.getSharedInstance().signIn(clientId, false);

I had post my code in here(LIBGDX FORUM)

Who had better way to solve?

julienvillegas commented 8 years ago

Working for me! Thanks

dsgraham81 commented 8 years ago

Thanks for this guys, I am finally able to get these mostly working. The issue I am having now is it is bringing up the sign-in just fine now, but after you allow, it redirects to Google.com and not back to my game. Any ideas?

DavidBVal commented 8 years ago

@dsgraham81, for me overriding OpenURL with

GIDSignIn.getSharedInstance().handleURL(url, sourceApplication, annotation)

fixed the returning problem.

I know this issue is old, but I tried all of the above and still the app is calling Safari instead of the webview. I've tried the code from alek-sandr, and still, login calls to Safari. I admit I don't even understand how this all works... where is the webview being defined? I don't have to create it manually, and call it myself to be displayed? I have assigned the delegates correctly because the line

Foundation.log("presentViewController()");

actually shows in the log when Safari opens. And the login itself and everything else in GPG works flawlessly, but of course, it is useless without a webview.

julienvillegas commented 7 years ago

@dsgraham81 I use to have the same issue (being redirected to Google.com after login) which I had solved in the past overriding the openURL method as follow.

@Override
public boolean openURL(UIApplication application, NSURL url, String sourceApplication, NSPropertyList annotation) {

//        return GPPURLHandler.handleURL(url, sourceApplication, annotation);
      return GIDSignIn.getSharedInstance().handleURL(url, sourceApplication, annotation);
 }

However I see this method is now deprecated so I am not sure how this can now be solved. Have you, or anyone else, found a solution?