美文网首页程序员
我的APP不可能这么胖之QQ好友分享

我的APP不可能这么胖之QQ好友分享

作者: 萌恬丶 | 来源:发表于2017-07-18 13:51 被阅读327次

    简介

    这一系列讲述的是免SDK实现分享、登录、支付等业务。

    将会使用ShareSDK Demo进行部分试验。

    一、拦截分享参数

    1、打开ShareSDK Demo,找到AppDelegate.m 添加如下代码

    //头文件不要忘
    #import <objc/runtime.h>
    
    //对UIApplication的openURL:方法进行hook
    -(void)swizzleOpenUrl{
        SEL openUrlSEL=@selector(openURL:);
        BOOL (*openUrlIMP)(id,SEL,id) =(BOOL(*)(id,SEL,id))[UIApplication instanceMethodForSelector:openUrlSEL];
        static int count=0;
        BOOL (^myOpenURL)(id SELF,NSURL * url)=^(id SELF,NSURL *url){
            
            //打印出分享的URL
            NSLog(@"\n----------open url: %d----------\n%@\n%@\n",count++,url,@"\n"/*[NSThread callStackSymbols]*/);
            
            //获取系统剪切板
            UIPasteboard * pasteboard = [UIPasteboard generalPasteboard];
            //打印获取QQ在剪切板的key 得知key为 com.tencent.mqq.api.apiLargeData
            NSLog(@"%@",pasteboard.pasteboardTypes);
            
            //获取QQ在剪切板参数 图片与链接分享时才有值
            NSData * qqInfoData = [pasteboard valueForPasteboardType:@"com.tencent.mqq.api.apiLargeData"];
            //QQ是使用NSKeyedArchiver序列化数据的
            //图片分享是会有file_data previewimagedata,链接分享只有previewimagedata
            //qqInfoDic:
            //{
            //    "file_data" = NSData数据
            //    "previewimagedata" = NSData数据
            //}
            NSDictionary * qqInfoDic = [NSKeyedUnarchiver unarchiveObjectWithData:qqInfoData];
            //图片
            NSData * file_data = qqInfoDic[@"file_data"];
            UIImage * image = [UIImage imageWithData:file_data];
            
            //缩略图 小于32k
            NSData * previewimagedata = qqInfoDic[@"previewimagedata"];
            UIImage * previewimage = [UIImage imageWithData:previewimagedata];
            
            return (BOOL)openUrlIMP(SELF,openUrlSEL,url);
        };
        class_replaceMethod([UIApplication class], openUrlSEL, imp_implementationWithBlock(myOpenURL), NULL);
    }
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        
        //只要添加这句
        [self swizzleOpenUrl];
    }
    
    

    2、查看控制台打印的URL

    文字分享

    ----------open url: 0----------
    mqqapi://share/to_fri?thirdAppDisplayName=U2hhcmVTREtEZW1v&shareType=0&file_type=text&callback_name=QQ05FB8B52&src_type=app&file_data=U2hhcmUgU0RL&version=1&cflag=0&callback_type=scheme&generalpastboard=1&sdkv=3.2.1
    

    图片分享 图片存在剪切板里

    ----------open url: 1----------
    mqqapi://share/to_fri?thirdAppDisplayName=U2hhcmVTREtEZW1v&shareType=0&objectlocation=pasteboard&file_type=img&callback_name=QQ05FB8B52&src_type=app&version=1&description=U2hhcmUgU0RL&cflag=0&callback_type=scheme&generalpastboard=1&sdkv=3.2.1
    

    链接分享 图片存在剪切板里

    ----------open url: 2----------
    mqqapi://share/to_fri?file_type=news&generalpastboard=1&src_type=app&version=1&description=U2hhcmUgU0RLIExpbmsgRGVzYw==&callback_type=scheme&url=aHR0cHM6Ly93d3cubW9iLmNvbQ==&shareType=0&title=U2hhcmUgU0RL&thirdAppDisplayName=U2hhcmVTREtEZW1v&callback_name=QQ05FB8B52&objectlocation=pasteboard&cflag=0&sdkv=3.2.1
    

    3、参数解释

    //QQ的URL Scheme
    mqqapi   
    
    //固定开头 
    share/to_fri  
    
    //我们app的名字(这里要对名字做Base64编码) 
    thirdAppDisplayName  
    
    // 0 QQ好友
    shareType   
    
    // 分享类型 
    // text(纯文本)、img(图片,可为图文)、news(链接)  
    file_type   
    
    // 例如QQ05FB8B52 QQ是固定写法,05FB8B52是appId  
    //需要做8位16进制转换(%08llx)
    callback_name   
    
    // 客户端分享固定写法 src_type=app   
    src_type   
    
    // 版本号 version=1 
    version  
    
    //cflag = 0
    cflag
    
    //callback_type=scheme 固定写法 
    callback_type   
    
    // 固定写法 generalpastboard=1  
    generalpastboard   
    
    //SDK版本
    sdkv 
    
    //带图片的分享,包括链接、图片分享需要用到
    //需要把图片放到剪切板里
    //objectlocation=pasteboard 固定写法
    objectlocation   
    
    // 当file_type为text时,file_data为分享内容(内容需要Base64编码)。file_data直接作为URl参数。
    // 当file_type为img时,file_data为UIImage的NSData(即需要将UIImage转成NSData)。QQ好友分享只能一张图片。
    //file_data需要放到剪切板里。  
    file_data   
    
    //缩略图(QQ好友分享专属字段,小于32k) 
    //当file_type为img、news时用到。
    previewimagedata 
    
    //QQ好友图片分享、链接分享。该参数为分享内容(Base64编码)
    description 
    
    //当file_type为news时用到,该参数为链接标题
    title   
    
    //当file_type为news时用到,该参数为网页url(Base64编码)
    url
    
    

    二、构造分享参数

    代码仅供参考,部分代码做了封装,需要到demo里的TQQPlatform类查看。

    //分享到QQ好友
    + (NSString *)shareToQQParameters:(NSMutableDictionary *)parameters appId:(NSString *)appId onStateChanged:(TStateChangedHandler)stateChangedHandler {
        
        if (stateChangedHandler) {
            [TQQPlatform shareInstance].stateChangedHandler = stateChangedHandler;
        }
        
        if ([TQQPlatform isQQInstalled]) {
            NSString * file_type = @"";
            TContentType TPlatformType = [[parameters typeForParams] integerValue];
            if (TPlatformType == TContentTypeText) {
                //文本类型
                file_type = @"text";
            }
            else if (TPlatformType == TContentTypeImage) {
                //图片类型
                file_type = @"img";
            }
            else if (TPlatformType == TContentTypeWebPage) {
                //链接
                file_type = @"news";
            }
            
            //公共参数
            NSMutableString *qqInfo = [[NSMutableString alloc] initWithString:@"mqqapi://share/to_fri?thirdAppDisplayName="];
            [qqInfo appendString:[NSString base64Encode:kCFBundleDisplayName]];
            [qqInfo appendString:@"&shareType=0"];
            [qqInfo appendString:@"&file_type="];
            [qqInfo appendString:file_type];
            [qqInfo appendString:@"&callback_name="];
            [qqInfo appendString:[NSString stringWithFormat:@"QQ%08llx",[appId longLongValue]]];
            [qqInfo appendString:@"&src_type=app"];
            [qqInfo appendString:@"&version=1"];
            [qqInfo appendString:@"&cflag=0"];
            [qqInfo appendString:@"&callback_type=scheme"];
            [qqInfo appendString:@"&sdkv=3.2.1"];
            [qqInfo appendString:@"&generalpastboard=1"];
            
            //纯文本时才会有file_data字段
            if ([file_type isEqualToString:@"text"]) {
                [qqInfo appendString:@"&file_data="];
                [qqInfo appendString:[NSString base64Encode:[parameters textForParams]]];
            }
            
            //图片分享、链接分享
            if ([file_type isEqualToString:@"text"] == NO) {
                [qqInfo appendString:@"&objectlocation=pasteboard"];
                [qqInfo appendString:@"&description="];
                [qqInfo appendString:[NSString base64Encode:[parameters textForParams]]];
                [qqInfo appendString:@"&title="];
                [qqInfo appendString:[NSString base64Encode:[parameters titleForParams]]];
                
                //图片集合,传入参数可以为UIImage、数组(UIImage、NSString(图片路径)、NSURL(图片路径))
                NSMutableArray * img = [NSMutableArray arrayWithImages:[parameters imagesForParams] isCompress:NO];
                //如果缩略图为空 就使用大图压缩
                NSMutableArray * thumbImg = [parameters thumbImageForParams] == nil ? [NSMutableArray arrayWithImages:[parameters imagesForParams] isCompress:YES] : [NSMutableArray arrayWithImages:[parameters thumbImageForParams] isCompress:YES];
                NSDictionary *data = nil;
                
                if ([file_type isEqualToString:@"img"]) {
                    //图片分享 QQ好友只支持一张,默认选取数组第0位置图片
                    data=@{@"file_data":img[0],
                           @"previewimagedata":thumbImg[0]};
                    
                }
                else if ([file_type isEqualToString:@"news"]) {
                    //链接分享 QQ好友只支持一张,默认选取数组第0位置图片
                    data=@{@"previewimagedata":thumbImg[0]};
                }
                [UIPasteboard setPasteboard:@"com.tencent.mqq.api.apiLargeData" value:data encoding:TPboardEncodingKeyedArchiver];
            }
            
            //链接分享
            if ([file_type isEqualToString:@"news"]) {
                
                [qqInfo appendString:@"&url="];
                [qqInfo appendString:[NSString base64Encode:[parameters[@"URL"] absoluteString]]];
                
            }
            
            return qqInfo;
        }
        else {
            
            if (stateChangedHandler) {
                NSError * err = [NSError errorWithDomain:@"TrochilusErrorDomain" code:-1001 userInfo:@{@"error_message":@"分享平台[QQ]尚未安装QQ或者QQ空间客户端!无法进行分享!"}];
                stateChangedHandler(TResponseStateFail,nil,err);
    
            }
        }
        
        return nil;
        
    }
    
    

    三、发起请求

    代码仅供参考,部分代码做了封装,需要到demo里的Trochilus类查看。

    + (void)share:(TPlatformType)platformType parameters:(NSMutableDictionary *)parameters onStateChanged:(TStateChangedHandler)stateChangedHandler {
        
        NSString * shareUrl = @"";
        switch (platformType) {
            case TPlatformSubTypeQQFriend: {
                
                shareUrl = [TQQPlatform shareToQQParameters:parameters
                                                     appId:[self platformForKey:@"QQ"][@"appId"]
                                            onStateChanged:^(TResponseState state, NSDictionary *userData, NSError *error) {
                                                if (stateChangedHandler) {
                                                    stateChangedHandler(state,userData,error);
                                                }
                                            }];
            }
                break;
            default:
                break;
        }
        
        [Trochilus sendToURL:shareUrl];
    }
    
    
    + (void)sendToURL:(NSString *)url {
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.001 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]];
        });
        
    }
    

    四、QQ客户端回调

    代码仅供参考,部分代码做了封装,需要到demo里的TQQPlatform类查看。

    //回调
    + (BOOL)handleUrlWithQQ:(NSURL *)url {
        
        if ([url.scheme hasPrefix:@"QQ"]) {
            //分享
            NSDictionary *dic=[NSMutableDictionary dictionaryWithUrl:url];
            if (dic[@"error_description"]) {
                [dic setValue:[NSString base64Decode:dic[@"error_description"]] forKey:@"error_description"];
            }
            
            if ([dic[@"error"] intValue] == -4) {
                
                if ([TQQPlatform shareInstance].stateChangedHandler) {
                    [TQQPlatform shareInstance].stateChangedHandler(TResponseStateCancel, nil, nil);
                }
                
            }
            else if ([dic[@"error"] intValue] == 0) {
                //分享成功
                if ([TQQPlatform shareInstance].stateChangedHandler) {
                    [TQQPlatform shareInstance].stateChangedHandler(TResponseStateSuccess, nil, nil);
                }
            }
            else{
                //分享失败 失败是什么状态 我也不知道 等测试到再说
                NSError *err=[NSError errorWithDomain:@"QQErrorDomain" code:[dic[@"error"] intValue] userInfo:dic];
                
                if ([TQQPlatform shareInstance].stateChangedHandler) {
                    [TQQPlatform shareInstance].stateChangedHandler(TResponseStateFail, nil, err);
                }
                
            }
            return YES;
        }
        return NO;
    }
    
    

    五、参考资料

    https://github.com/100apps/openshare

    六、Demo

    https://github.com/quanweiwang/Trochilus

    目录

    分享篇
    1、我的APP不可能这么胖之QQ好友分享
    2、我的APP不可能这么胖之QQ空间分享
    3、我的APP不可能这么胖之微信好友分享
    4、我的APP不可能这么胖之微信朋友圈分享
    5、我的APP不可能这么胖之新浪微博分享
    登录篇
    6、我的APP不可能这么胖之QQ登录
    7、我的APP不可能这么胖之微信登录
    8、我的APP不可能这么胖之新浪微博登录
    支付篇
    9、我的APP不可能这么胖之微信支付
    10、我的APP不可能这么胖之支付宝支付

    相关文章

      网友评论

        本文标题:我的APP不可能这么胖之QQ好友分享

        本文链接:https://www.haomeiwen.com/subject/pufhkxtx.html