iOS第三方登录及分享入门指南 —— QQ(一)

导语:

第三方登录和分享是现在App的「主流功能」,不管友盟,还是ShareSDK,都有很好的集成文档,Please feel free to check!至于写这篇指南的初衷是刚好公司最近做Standard Module,也刚好需要集成这一块,还得做成友盟那样以供使用。(心累,迫于老大的淫威之下

QQ SDK官方文档
  • 这里可以看到QQ SDK的详细集成索引
  • 这里可以下载QQ SDK

实现QQ登录

一、准备工作

  1. 在腾讯开放平台,注册成为开发者。
  2. 创建应用,申请你的appidappkey

!!!Ps:在准备工作的时候,可能会遇到一个坑:QQ互联开放平台和腾讯开放平台是相互独立的,所以 若已在QQ互联创建过应用,可在创建应用时选择关联QQ互联,输入在QQ互联创建的网页应用APPID、APPKEY即可完成关联。(两个平台做一样的事,鹅厂真心钱多

iOS第三方登录及分享入门指南 —— QQ(一)_第1张图片
创建应用.png
appid和appkey的用途
  • appid:应用的唯一标识。在OAuth2.0认证过程中,appid的值即为oauth_consumer_key的值。
  • appkey:appid对应的密钥,访问用户资源时用来验证应用的合法性。在OAuth2.0认证过程中,appkey的值即为oauth_consumer_secret的值。

二、集成SDK

下载好完整包,如图导入工程需要的文件。

iOS第三方登录及分享入门指南 —— QQ(一)_第2张图片
14932765373824.jpg
  • 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

iOS第三方登录及分享入门指南 —— QQ(一)_第3张图片
配置属性.jpg
3. 修改Info.plist文件

在XCode中,选中TARGETS一栏,在Info标签栏中找到URL Types,添加一条新的URL scheme。(必须填写

Identifier: tencentopenapi
URL Schemes: tencent + "appid"

想要实现应用间跳转,而不是打开一个登陆网页,在Info.plist中添加LSApplicationQueriesSchemes

LSApplicationQueriesSchemes

mqqapi
mqq
mqqOpensdkSSoLogin
mqqconnect
mqqopensdkdataline
mqqopensdkgrouptribeshare
mqqopensdkfriend
mqqopensdkapi
mqqopensdkapiV2
mqqopensdkapiV3
mqzoneopensdk
mqqopensdkapiV3
mqqopensdkapiV3
mqzone
mqzonev2
mqzoneshare
wtloginqzone
mqzonewx
mqzoneopensdkapiV2
mqzoneopensdkapi19
mqzoneopensdkapi
mqzoneopensdk

四、代码实现

1.AppDelegate

在AppDelegate中添加头文件,并重写AppDelegate的handleOpenURLopenURL方法

  • 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 *)options{
          [TencentOAuth HandleOpenURL:url];
          return YES;
      }
    
2.登录控制器实现对应的代理事件

在LoginViewController添加对应的头文件,添加QQ Login点击事件,实现TencentSessionDelegate的对应delegate事件。

#import "LoginViewController.h"
#import 
 
@interface LoginViewController ()
@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设置 && 是否添加LSApplicationQueriesSchemesInfo.plist

  • 当Xcode提示“未选择授权类型”,可添加:

      [self.tencentOAuth setAuthShareType:AuthShareType_QQ];
    

分割线,接下来讲讲QQ分享

实现QQ分享

步骤同上一、二、三

代码实现

1.在AppDelegate中初始化OAuth
@interface AppDelegate ()
@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里添加头文件,重写handleOpenURL && openURL方法

  • 添加头文件

      #import 
    
  • 重写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 *)options{
          if ([url.scheme isEqualToString:[NSString stringWithFormat:@"tencent%@",QQAppID]]) {
              return [QQApiInterface handleOpenURL:url delegate:self];
      }
      else{
              return YES;
          }
      }
    
  • 处理回调事件

      @interface AppDelegate ()
    
      - (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 
#import 
#import 
#import 
#import 
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.分享篇注意事项
  • 分享的回调无法执行,请注意实现,即

      [QQApiInterface handleOpenURL:url delegate:self(代理对象)];
    
  • 当Xcode打印“result code 为 -2”时(未知的分享类型),请注意实现setShareDestType方法,即

      QQApiTextObject* object = [QQApiTextObject objectWithText:@"分享的内容"];
      [object setShareDestType:ShareDestTypeQQ];
    

结束语

我在使用原生集成时,遇到的这些坑都由于Tencent的文档太久没更新导致花了一段时间。最后仔细的查看SDK接口才发现解决方式,希望能够给看到这篇文章的人提供到一点帮助。在接下来一段时间,还会继续写几篇关于 微信、微博、Facebook等等的SDK集成指南。还在研究中,共勉啦。

你可能感兴趣的:(iOS第三方登录及分享入门指南 —— QQ(一))