我最近在我的应用程序中集成了 Google + API,这很容易,我唯一的问题是一切都需要你离开应用程序然后回来(它为此使用 URL 方案)。这不是我想要的行为,有没有办法直接调用他们的服务并像在 LinkedIn API 中一样对响应做任何我想做的事情?
我真的很想避免在 Safari 和我的应用程序之间来回切换。任何建议/文件表示赞赏。
谢谢,
奥斯卡
我最近在我的应用程序中集成了 Google + API,这很容易,我唯一的问题是一切都需要你离开应用程序然后回来(它为此使用 URL 方案)。这不是我想要的行为,有没有办法直接调用他们的服务并像在 LinkedIn API 中一样对响应做任何我想做的事情?
我真的很想避免在 Safari 和我的应用程序之间来回切换。任何建议/文件表示赞赏。
谢谢,
奥斯卡
来自谷歌的更新
今天,我们发布了一个新的 Google Sign In iOS SDK,它内置了对通过 WebView 登录的完整支持:developers.google.com/identity/sign-in/ios SDK 支持调度到任何处理 Sign 的 Google 应用程序在存在时,使用 WebView 后备。在所有情况下,都避免了 Safari 开关,我们认为这是避免应用被拒绝的关键因素。我们期待从使用新 SDK 的人们那里获得反馈,并希望它的使用可以取代人们在此期间实施的(巧妙而勤奋的)变通办法。
不再需要下面的方法
此方法使用自定义 UIWebView 处理登录内部,此方法有效且已获 Apple 批准
我的应用被踢出审查原因
"The app opens a web page in mobile Safari for logging in to Google plus,
then returns the user to the app. The user should be able log in without opening
Safari first."
请参阅此链接https://code.google.com/p/google-plus-platform/issues/detail?id=900 我确实通过以下步骤解决了它
1)创建UIApplication的子类,覆盖openURL:
。H
#import <UIKit/UIKit.h>
#define ApplicationOpenGoogleAuthNotification @"ApplicationOpenGoogleAuthNotification"
@interface Application : UIApplication
@end
.m
#import "Application.h"
@implementation Application
- (BOOL)openURL:(NSURL*)url {
if ([[url absoluteString] hasPrefix:@"googlechrome-x-callback:"]) {
return NO;
} else if ([[url absoluteString] hasPrefix:@"https://accounts.google.com/o/oauth2/auth"]) {
[[NSNotificationCenter defaultCenter] postNotificationName:ApplicationOpenGoogleAuthNotification object:url];
return NO;
}
return [super openURL:url];
}
@end
2)到 info.plist,添加 Principal 类,并为其添加 Application(或任何您命名的类)
添加 plist 键“NSPrincipalClass”并作为主应用程序的类的值(扩展 UIApplication 的类,在本例中为 Application(参见上面的代码))
3) 捕获通知并打开内部 webview
当您的自定义应用程序类发送 ApplicationOpenGoogleAuthNotification 时,在某处(可能在 AppDelegate 中)侦听它,当您收到此通知时,打开 UIWebView(使用通知传递的 URL 作为 webview 的 url)(在我的情况下 LoginViewController 侦听对于此通知,当收到通知时,它会打开一个视图控制器,其中仅包含一个连接到委托的 web 视图)
4)在webview里面
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if ([[[request URL] absoluteString] hasPrefix:@"com.XXX.XXX:/oauth2callback"]) {
[GPPURLHandler handleURL:url sourceApplication:@"com.google.chrome.ios"n annotation:nil];
// Looks like we did log in (onhand of the url), we are logged in, the Google APi handles the rest
[self.navigationController popViewControllerAnimated:YES];
return NO;
}
return YES;
}
所以,这取决于你想做什么。
登录:这将始终调用另一个应用程序。如果安装了 Google+ 应用程序,它将调用它,否则它将回退到 Chrome 和 Safari。
分享/互动帖子:现在这总是使用 Chrome 或移动 Safari。
检索朋友,编写应用程序活动,检索个人资料信息:所有这些都是使用登录后检索到的访问令牌完成的,因此不需要离开应用程序。
虽然不受支持,但可以跳过 SDK 并弹出 UIWebView,动态构建 OAuth 链接并将用户发送到该链接(查看随 SDK 提供的开源库中的 GTMOAuth2ViewControllerTouch)。下面是一个非常粗略的示例,您可以将其重新插入 GPPSignIn 实例。
但是,您将保证用户必须输入他们的用户名和密码(可能还有第二个因素)。使用 Google+ 应用程序几乎可以保证您已经登录,并且使用 Chrome/Safari 路由,用户可能已经登录(特别是如果他们正在使用其他应用程序通过 Google+ 登录)。
这也没有解决共享问题,所以我强烈建议尽可能使用现有的 SDK。以您希望它的工作方式提交功能请求也是一件好事:https ://code.google.com/p/google-plus-platform/issues/list
@interface ViewController() {
GTMOAuth2ViewControllerTouch *controller;
}
@end;
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
GPPSignIn *signIn = [GPPSignIn sharedInstance];
signIn.clientID = @""; // YOUR CLIENT ID HERE.
signIn.delegate = self;
}
- (IBAction)didTapSignIn:(id)sender {
void (^handler)(id, id, id) =
^(GTMOAuth2ViewControllerTouch *viewController,
GTMOAuth2Authentication *auth,
NSError *error) {
[self dismissViewControllerAnimated:YES completion:^{
[controller release];
}];
if (error) {
NSLog(@"%@", error);
return;
} else {
BOOL signedIn = [[GPPSignIn sharedInstance] trySilentAuthentication];
if(!signedIn) {
NSLog(@"Sign In failed");
}
}
};
controller = [[GTMOAuth2ViewControllerTouch
controllerWithScope:kGTLAuthScopePlusLogin
clientID:[GPPSignIn sharedInstance].clientID
clientSecret:nil
keychainItemName:[GPPSignIn sharedInstance].keychainName
completionHandler:handler] retain];
[self presentViewController:controller animated:YES completion:nil];
}
- (void)finishedWithAuth:(GTMOAuth2Authentication *)auth
error:(NSError *)error {
if (!error) {
UIAlertView * al = [[UIAlertView alloc] initWithTitle:@"Authorised"
message:@"Authorised!"
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[al show];
[al release];
}
}
此代码唯一真正的技巧是它使用 [GPPSignIn sharedInstance].keychainName - 这意味着身份验证令牌与 GPPSignIn 按钮存储在相同的钥匙串条目中,这反过来意味着我们可以使用 [[GPPSignIn sharedInstance] trySilentAuthentication] 一旦被填充,并保持与主库相同的基于回调的流程。
如果未安装 Google Plus 应用程序,@PeterLapisu 方法效果很好。然后从 app 传出的 url 前缀如下:
但是,如果安装了 Google 应用程序,则会多出一个 url,前缀列表如下所示:
因此,如果安装了 Google App,它将与包含 webview 的应用程序 UIViewController 同时启动。然后,如果用户成功使用 Google App 登录,他将被引导回我们的应用程序,并且 ViewController 将可见。
为了防止这个谷歌应用程序应该被允许登录用户并将他引导回我们的应用程序。根据此讨论:https ://code.google.com/p/google-plus-platform/issues/detail?id= 900 Apple 允许。
所以在我的实现中,我首先检查是否安装了谷歌应用程序:
- (BOOL)openURL:(NSURL*)url {
NSURL *googlePlusURL = [[NSURL alloc] initWithString:@"gplus://plus.google.com/"];
BOOL hasGPPlusAppInstalled = [[UIApplication sharedApplication] canOpenURL:googlePlusURL];
if(!hasGPPlusAppInstalled)
{
if ([[url absoluteString] hasPrefix:@"googlechrome-x-callback:"]) {
return NO;
} else if ([[url absoluteString] hasPrefix:@"https://accounts.google.com/o/oauth2/auth"]) {
[[NSNotificationCenter defaultCenter] postNotificationName:ApplicationOpenGoogleAuthNotification object:url];
return NO;
}
}
return [super openURL:url];
}
编辑:
现在我可以确认我的应用程序最终通过此解决方案获得批准。
我希望它会帮助某人。它合并了 Google+ 和 Gmail 示例,完全避免使用 Google 登录按钮,即您无需离开应用程序。
将 Google+ 和 Gmail API 添加到您的 Google 项目中,在您的应用程序中登录到 google,就像使用 OAuth2 中的 GTMOAuth2ViewControllerTouch.xib 登录到 gmail 一样,并将范围设置为 Google+:
-(IBAction)dologin{
NSString *scope = kGTLAuthScopePlusLogin;//Google+ scope
GTMOAuth2Authentication * auth = [GTMOAuth2ViewControllerTouch
authForGoogleFromKeychainForName:kKeychainItemName
clientID:kClientID
clientSecret:kClientSecret];
if ([auth refreshToken] == nil) {
GTMOAuth2ViewControllerTouch *authController;
authController = [[GTMOAuth2ViewControllerTouch alloc]
initWithScope:scope
clientID:kClientID
clientSecret:kClientSecret
keychainItemName:kKeychainItemName
delegate:self
finishedSelector:@selector(viewController:finishedWithAuth:error:)];
[[self navigationController] pushViewController:authController animated:YES];
}else{
[auth beginTokenFetchWithDelegate:self didFinishSelector:@selector(auth:finishedRefreshWithFetcher:error:)];
}
}
如果登录成功,则保留身份验证对象,然后在使用 google plus 服务时使用该身份验证对象:
GTLServicePlus* plusService = [[[GTLServicePlus alloc] init] autorelease];
[plusService setAuthorizer:self.auth];//!!!here use our authentication object!!!
不需要 GPPSignIn。
完整的文章在这里:这是另一个解决方案
使用(新的)Google 登录 iOS SDK。
当没有 Google 应用程序存在以完成登录过程时,SDK 原生支持通过 WebView 登录。为此,它还支持向多个 Google 应用程序的潜在发送。