导语:
第三方登录和分享是现在App的「主流功能」,不管友盟,还是ShareSDK,都有很好的集成文档,Please feel free to check!至于写这篇指南的初衷是刚好公司最近做Standard Module,也刚好需要集成这一块,还得做成友盟那样以供使用。(心累,迫于老大的淫威之下
QQ SDK官方文档
实现QQ登录
一、准备工作
- 在腾讯开放平台,注册成为开发者。
- 创建应用,申请你的appid和appkey。
!!!Ps:在准备工作的时候,可能会遇到一个坑:QQ互联开放平台和腾讯开放平台是相互独立的,所以 若已在QQ互联创建过应用,可在创建应用时选择关联QQ互联,输入在QQ互联创建的网页应用APPID、APPKEY即可完成关联。(两个平台做一样的事,鹅厂真心钱多
appid和appkey的用途
- appid:应用的唯一标识。在OAuth2.0认证过程中,appid的值即为oauth_consumer_key的值。
- appkey:appid对应的密钥,访问用户资源时用来验证应用的合法性。在OAuth2.0认证过程中,appkey的值即为oauth_consumer_secret的值。
二、集成SDK
下载好完整包,如图导入工程需要的文件。
- TencentOpenAPI.framework打包了iOS SDK的头文件定义和具体实现
- TencentOpenApi_iOS_Bundle.bundle 打包了iOS SDK需要的资源文件
三、配置工程
1. 添加SDK依赖的系统库文件
Security.framework
SystemConfiguration.framework
CoreTelephony.framework
CoreGraphics.Framework
libiconv.tbd
libsqlite3.tbd
libstdc++.tbd
libz.tbd
2. 修改必要的工程配置属性
在工程配置中的Build Settings
一栏中找到Linking
配置区,给Other Linker Flags
配置项添加属性值-fobjc-arc
3. 修改Info.plist文件
在XCode中,选中TARGETS
一栏,在Info
标签栏中找到URL Types
,添加一条新的URL scheme
。(必须填写
Identifier: tencentopenapi
URL Schemes: tencent + "appid"
想要实现应用间跳转,而不是打开一个登陆网页,在Info.plist
中添加LSApplicationQueriesSchemes
:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>mqqapi</string>
<string>mqq</string>
<string>mqqOpensdkSSoLogin</string>
<string>mqqconnect</string>
<string>mqqopensdkdataline</string>
<string>mqqopensdkgrouptribeshare</string>
<string>mqqopensdkfriend</string>
<string>mqqopensdkapi</string>
<string>mqqopensdkapiV2</string>
<string>mqqopensdkapiV3</string>
<string>mqzoneopensdk</string>
<string>mqqopensdkapiV3</string>
<string>mqqopensdkapiV3</string>
<string>mqzone</string>
<string>mqzonev2</string>
<string>mqzoneshare</string>
<string>wtloginqzone</string>
<string>mqzonewx</string>
<string>mqzoneopensdkapiV2</string>
<string>mqzoneopensdkapi19</string>
<string>mqzoneopensdkapi</string>
<string>mqzoneopensdk</string>
</array>
四、代码实现
1.AppDelegate
在AppDelegate中添加头文件,并重写AppDelegate的handleOpenURL
和openURL
方法
-
iOS9之前,分别重写
handleOpenURL && openURL
方法//handleOpenURL(ios10已弃用) NS_DEPRECATED_IOS(2_0, 9_0, "Please use application:openURL:options:") - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url{ [TencentOAuth HandleOpenURL:url]; return YES; } //openURL(iOS10已弃用) NS_DEPRECATED_IOS(4_2, 9_0, "Please use application:openURL:options:") - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{ [TencentOAuth HandleOpenURL:url]; return YES; }
-
iOS9之后,
handleOpenURL && openURL
合成为同一个方法//handleOpenURL && openURL - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options{ [TencentOAuth HandleOpenURL:url]; return YES; }
2.登录控制器实现对应的代理事件
在LoginViewController添加对应的头文件,添加QQ Login
点击事件,实现TencentSessionDelegate
的对应delegate事件。
#import "LoginViewController.h"
#import <TencentOpenAPI/TencentOAuth.h>
@interface LoginViewController ()<TencentSessionDelegate>
@property (nonatomic, strong) TencentOAuth* tencentOAuth;
@end
@implementation LoginViewController
- (void)loginBtnClicked{
self.tencentOAuth = [[TencentOAuth alloc] initWithAppId:@"你申请的appID" andDelegate:self];
//在这个数组里,可以添加你想要用户授权的信息的相关字段
//注意,若是授权太多信息, 用户可能会拒绝授权
NSArray *permissions = [NSArray arrayWithObjects:
@"get_user_info",
@"get_simple_userinfo",
@"add_t",
nil];
//授权类型
[self.tencentOAuth setAuthShareType:AuthShareType_QQ];
//调用SDK登录
[self.tencentOAuth authorize:permissions inSafari:false];
}
- (void)tencentDidNotNetWork{
NSLog(@"网络连接失败");
}
- (void)tencentDidLogin{
if (self.tencentOAuth.accessToken && 0 != [self.tencentOAuth.accessToken length]){
//accessToken有效期3个月,想要获取用户信息,必须调用getUserInfo
NSLog(@"记录登录用户的OpenID、Token以及过期时间");
[self.tencentOAuth getUserInfo];
}else{
NSLog(@"登录不成功 没有获取accesstoken");
}
}
- (void)tencentDidNotLogin:(BOOL)cancelled{
if (cancelled){
NSLog(@"用户取消登录");
}else{
NSLog(@"登录失败");
}
}
3.获取用户信息
当DidLogin调用getUserInfo,会有此回调返回userInfo
- (void)getUserInfoResponse:(APIResponse *)response{
if (response && response.retCode == URLREQUEST_SUCCEED) {
NSDictionary* userInfo = [response jsonResponse];
NSLog(@"%@",userInfo);
}else{
NSLog(@"QQ auth fail ,getUserInfoResponse:%d", response.detailRetCode);
}
}
4.登录篇注意事项
�当未调起原生客户端授权,只弹出网页,检查URL scheme设置 && 是否添加
LSApplicationQueriesSchemes
到Info.plist
-
当Xcode提示“未选择授权类型”,可添加:
[self.tencentOAuth setAuthShareType:AuthShareType_QQ];
分割线,接下来讲讲QQ分享
实现QQ分享
步骤同上一、二、三
代码实现
1.在AppDelegate中初始化OAuth
@interface AppDelegate ()<QQApiInterfaceDelegate>
@property (nonatomic, strong) TencentOAuth* tencentOAuth;
@end
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
// 根据自己的AppID初始化OAuth
self.tencentOAuth = [[TencentOAuth alloc] initWithAppId:@"QQAppID" andDelegate:nil];
return YES;
}
2.在AppDelegate中实现回调事件
此回调事件,需要在AppDelegate里添加头文件<TencentOpenAPI/QQApiInterface.h>
,重写handleOpenURL && openURL
方法
-
添加头文件
#import <TencentOpenAPI/QQApiInterface.h>
-
重写
handleOpenURL
方法//iOS9之前,分别重写`handleOpenURL && openURL`方法 //handleOpenURL(ios10已弃用) NS_DEPRECATED_IOS(2_0, 9_0, "Please use application:openURL:options:") - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url{ if ([url.scheme isEqualToString:[NSString stringWithFormat:@"tencent%@",QQAppID]]) { return [QQApiInterface handleOpenURL:url delegate:self]; } else{ return YES; } } //iOS9之后,`handleOpenURL && openURL` 合成为同一个方法 //handleOpenURL && openURL - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options{ if ([url.scheme isEqualToString:[NSString stringWithFormat:@"tencent%@",QQAppID]]) { return [QQApiInterface handleOpenURL:url delegate:self]; } else{ return YES; } }
-
处理回调事件
@interface AppDelegate ()<QQApiInterfaceDelegate> - (void)onReq:(QQBaseReq *)req{ NSLog(@"处理来至QQ的请求"); } - (void)onResp:(QQBaseResp *)resp{ NSLog(@"处理来至QQ的响应"); NSLog(@"response") switch (resp.type) { case ESENDMESSAGETOQQRESPTYPE: { SendMessageToQQResp* sendResp = (SendMessageToQQResp*)resp; if ([sendResp.result isEqualToString:@"0"]) { UIAlertController* vc = [UIAlertController alertControllerWithTitle:@"成功" message:@"QQ分享成功" preferredStyle:UIAlertControllerStyleAlert]; [vc addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { }]]; [self.window.rootViewController presentViewController:vc animated:YES completion:nil]; } else { UIAlertController* vc = [UIAlertController alertControllerWithTitle:@"失败" message:@"QQ分享失败" preferredStyle:UIAlertControllerStyleAlert]; [vc addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { }]]; [self.window.rootViewController presentViewController:vc animated:YES completion:nil]; } break; } default: { break; } } } - (void)isOnlineResponse:(NSDictionary *)response{ NSLog(@"处理QQ在线状态的回调"); NSLog(@"response : %@",response); }
3.在ShareViewController中导入对应的头文件
#import <TencentOpenAPI/TencentOAuth.h>
#import <TencentOpenAPI/TencentMessageObject.h>
#import <TencentOpenAPI/TencentApiInterface.h>
#import <TencentOpenAPI/QQApiInterface.h>
#import <TencentOpenAPI/QQApiInterfaceObject.h>
4.在ShareViewController实现分享事件示例代码
-
文本
- (void)shareText { if (![TencentOAuth iphoneQQInstalled]) { UIAlertController* vc = [UIAlertController alertControllerWithTitle:@"你还没有安装QQ客户端" message:nil preferredStyle:UIAlertControllerStyleAlert]; [vc addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { }]]; [self presentViewController:vc animated:YES completion:nil]; } else{ QQApiTextObject* object = [QQApiTextObject objectWithText:@"分享的内容"]; [object setShareDestType:ShareDestTypeQQ]; SendMessageToQQReq* req = [SendMessageToQQReq reqWithContent:object]; QQApiSendResultCode code = [QQApiInterface sendReq:req]; NSLog(@"result code : %d",code); } }
-
图片
- (void)shareImage { if (![TencentOAuth iphoneQQInstalled]) { UIAlertController* vc = [UIAlertController alertControllerWithTitle:@"你还没有安装QQ客户端" message:nil preferredStyle:UIAlertControllerStyleAlert]; [vc addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { }]]; [self presentViewController:vc animated:YES completion:nil]; } else{ NSString* filePath = [[NSBundle mainBundle] pathForResource:@"icon" ofType:@"png"]; NSData* imageData = [NSData dataWithContentsOfFile:filePath]; QQApiImageObject* obj = [QQApiImageObject objectWithData:imageData previewImageData:imageData title:@"title" description:@"github猫"]; [obj setShareDestType:ShareDestTypeQQ]; SendMessageToQQReq* req = [SendMessageToQQReq reqWithContent:obj]; QQApiSendResultCode code = [QQApiInterface sendReq:req]; NSLog(@"result code : %d",code); } }
-
新闻
- (void)shareNews { if (![TencentOAuth iphoneQQInstalled]) { UIAlertController* vc = [UIAlertController alertControllerWithTitle:@"你还没有安装QQ客户端" message:nil preferredStyle:UIAlertControllerStyleAlert]; [vc addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { }]]; [self presentViewController:vc animated:YES completion:nil]; } else{ //分享跳转URL,注意要经过UTF8处理 NSString *url = [@"http://xxx.xxx.xxx/" stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; //分享图预览图URL地址 NSString *previewImageUrl = @"preImageUrl.png"; QQApiNewsObject *newsObj = [QQApiNewsObject objectWithURL :[NSURL URLWithString:url] title: @"title" description :@"description" previewImageURL:[NSURL URLWithString:previewImageUrl]]; SendMessageToQQReq *req = [SendMessageToQQReq reqWithContent:newsObj]; //将内容分享到qq //QQApiSendResultCode sent = [QQApiInterface sendReq:req]; //将内容分享到qzone QQApiSendResultCode sent = [QQApiInterface SendReqToQZone:req]; } }
分享类型:
分享消息类型 | QQ好友 | QQ空间 | web QQ好友 | web QQ空间 |
---|---|---|---|---|
QQApiTextObject | ✔️ | ❌ | ❌ | ❌ |
QQApiImageObject | ✔️ | ❌ | ❌ | ❌ |
QQApiNewsObject | ✔️ | ✔️ | ✔️ | ✔️ |
QQApiAudioObject | ✔️ | ✔️ | ✔️ | ✔️ |
QQApiVideoObject | ✔️ | ✔️ | ✔️ | ✔️ |
5.分享篇注意事项
-
分享的回调无法执行,请注意实现
<QQApiInterfaceDelegate>
,即[QQApiInterface handleOpenURL:url delegate:self(代理对象)];
-
当Xcode打印“result code 为 -2”时(未知的分享类型),请注意实现
setShareDestType
方法,即QQApiTextObject* object = [QQApiTextObject objectWithText:@"分享的内容"]; [object setShareDestType:ShareDestTypeQQ];
结束语
我在使用原生集成时,遇到的这些坑都由于Tencent的文档太久没更新导致花了一段时间。最后仔细的查看SDK接口才发现解决方式,希望能够给看到这篇文章的人提供到一点帮助。在接下来一段时间,还会继续写几篇关于 微信、微博、Facebook等等的SDK集成指南。还在研究中,共勉啦。