Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Not fetch Google user when handle sign in with another Google app using GIDSignIn

I'm using Google Sign-In for iOS and when using simulator it's working fine because no google app is installed and user is fetch, but when using my iPhone 6 device open youtube (with some registered account inside them) for handle sign in. After, when come back on the app code don't enter on this function :

-(void)signIn:(GIDSignIn *) signIn 
    didSignInForUser:(GIDGoogleUser *)
    user withError:(NSError *) error

Anyone can help me i can't use another function for login i must call [[GIDSignIn sharedIstance] signIn] and this function detect if another google app is installed and automatically open another google app or Webview.

like image 664
Ridney Avatar asked Jun 16 '15 09:06

Ridney


3 Answers

I resolved the issue by properly setting some properties for the GIDSignIn Instance. For example:

GIDSignIn*sigNIn=[GIDSignIn sharedInstance];
[sigNIn setDelegate:self];
[sigNIn setUiDelegate:self];
sigNIn.shouldFetchBasicProfile = YES;
sigNIn.allowsSignInWithBrowser = NO;
sigNIn.allowsSignInWithWebView = YES;
sigNIn.scopes = @[@"https://www.googleapis.com/auth/plus.login",@"https://www.googleapis.com/auth/userinfo.email",@"https://www.googleapis.com/auth/userinfo.profile"];
sigNIn.clientID =@"xxxxxxxxxxxxxxxxxxxxxxxgai.apps.googleusercontent.com";
[sigNIn signIn];
like image 58
Vignesh Shiv Avatar answered Nov 02 '22 06:11

Vignesh Shiv


I'm going to assume that you are using GIDSignin with your own server which requires you to include a serverclientID with your GIDSignin. This would force my app to try to use youtube or google plus to log in rather than open a webview or even a browser. This would return a GIDSigninError=-1 "a potentially recoverable error.." and would not allow the user to log in.

The way I solved this was by blocking URLs from google or youtube before they were opened by overriding UIApplication's canOpenURL function. I did this by subclassing UIApplication and implementing canOpenURL like this:

@interface MyApp : UIApplication
- (BOOL)canOpenURL:(NSURL *)url;
@end

@implementation MyApp
- (BOOL)canOpenURL:(NSURL *)url
{
    if ([[url scheme] hasPrefix:@"com-google-gidconsent"] || [[url scheme] hasPrefix:@"com.google.gppconsent"]) {
        return NO;
    }
    return [super canOpenURL:url];
}
@end

int main(int argc, char * argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, NSStringFromClass([MyApp class]), NSStringFromClass([AppDelegate class]));
    }
}

Notice that usually there would be a nil after argv but this is where you put your subclass of UIApplication. This is also how you can use your own subclass of AppDelegate.

The other solution would be to create a category on UIApplication that overrides canOpenURL and use swizzling to call the original implementation within your custom canOpenURL. This is a good article on swizzling: https://blog.newrelic.com/2014/04/16/right-way-to-swizzle/

I must warn you though, these two solutions are hacks and you have to be really careful about the side-effects doing this can have on your application. I'm not even sure apple would be ok with this.

like image 22
Diego Watanabe Avatar answered Nov 02 '22 07:11

Diego Watanabe


import UIKit
import GoogleSignIn
import Google

class ViewController: UIViewController,GIDSignInUIDelegate, GIDSignInDelegate {

override func viewDidLoad() {
    super.viewDidLoad()
    let gidSingIn = GIDSignIn()

    GIDSignIn.sharedInstance().uiDelegate = self
        gidSingIn.delegate = self
    GIDSignIn.sharedInstance().delegate = self

    var configureError:NSError?
    GGLContext.sharedInstance().configureWithError(&configureError)

    assert(configureError == nil, "Error configuring Google services: \(configureError)")


    let button = GIDSignInButton(frame:CGRectMake(0,0,30, 200))
        button.center = self.view.center
        button.backgroundColor = UIColor.blueColor()
       self.view.addSubview(button)



    // Do any additional setup after loading the view, typically from a nib.
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

@IBAction func signInGoogle(sender: AnyObject) {

    print("pressed")

}

func signIn(signIn: GIDSignIn!, didSignInForUser user: GIDGoogleUser!,
            withError error: NSError!) {
    if (error == nil) {
        // Perform any operations on signed in user here.
        print(user.userID)                // For client-side use only!
        print(user.authentication.idToken) // Safe to send to the server
        print(user.profile.name)
        print(user.profile.givenName)
        print(user.profile.familyName)
        print(user.profile.email)
        print(user.authentication.accessToken)
        print(user.profile)
    } else {
        print("\(error.localizedDescription)")
    }
}
func signIn(signIn: GIDSignIn!, didDisconnectWithUser user:GIDGoogleUser!,
            withError error: NSError!) {
}

} // this is login with gmail account not for googleplus. just copy and past within your controller. and add following func in your AppDelegate Class

func application(application: UIApplication,
                 openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {
    var options: [String: AnyObject] = [UIApplicationOpenURLOptionsSourceApplicationKey: sourceApplication!,UIApplicationOpenURLOptionsAnnotationKey: annotation]
    return GIDSignIn.sharedInstance().handleURL(url,
                                                sourceApplication: sourceApplication,
                                                annotation: annotation)
}
like image 1
AyAz Avatar answered Nov 02 '22 07:11

AyAz